pandas初阶使用

pandas数据类型

pandas 基于两种数据类型,series 和 dataframe。

  • series 是一种一维的数据类型,其中的每个元素都有各自的标签。标签可以是数字或者字符。
  • dataframe 是一个二维的、表格型的数据结构。pandas 的 dataframe 可以储存许多不同类型的数据,类似于我们常用的excel。dataframe 可以看成一个series的字典{"key1":series1,"key2":series2}。

接入pandas

pandas是python的一个第三方库,使用前需要先进行安装:

pip3 install pandas

安装完成后我们来导入这个库:

import pandas as pd

接下来我们新建一个数据集,并对它进行操作。我们可以选择新建一个数据集,或者从本地文件中导入,这里我们选择后者,因为这更符合我平时的使用场景。pandas提供了丰富的api来读取各种文件:


pandas_read.png

这里我们新建一个Excel,读取并打印:

标题1 标题2 标题3 标题4
1 11 111 1a
2 22 222 2a
3 33 333 3a
4 44 444 4a
5 55 555 5a
df = pd.read_excel("C:/Users/Administrator/Desktop/新建 Microsoft Excel 工作表.xlsx")
print(df)
#   标题1  标题2  标题3 标题4
#0    1   11  111  1a
#1    2   22  222  2a
#2    3   33  333  3a
#3    4   44  444  4a
#4    5   55  555  5a

数据前面的0,1,2,3,4为行索引,从0开始。

获取数据基本信息

获取行数、列数

print(df.shape)
# (5, 4)

我们得到一个tuple,tuple[0]为行,tuple[1]为列。并且我们可以得到一个信息,它会默认第一个非空行为题头,数据的行数并没有计算标题行。

获取标题

print(df.columns.values.tolist())
# ['标题1', '标题2', '标题3', '标题4']

如果某列没有标题头,会得到Unnamed x。

获取数据数目

print(len(df))
# 5

这里的数据指的一行为一条数据,所以返回的实际就是行数。

数据的过滤

获取前几行或者后几行

print("前两行:\n")
print(df.head(2))
print("-----------")
print("后两行:\n")
print(df.tail(2))

#前两行:
#   标题1  标题2  标题3 标题4
#0    1   11  111  1a
#1    2   22  222  2a
#-----------
#后两行:
#   标题1  标题2  标题3 标题4
#3    4   44  444  4a
#4    5   55  555  5a

获取某列

print(df["标题1"])
#0    1
#1    2
#2    3
#3    4
#4    5


# 将 标题1 这列切割出来,注意会再原数据集中删除
# print(df.pop("标题1"))

注意前面的第一列01234为它的索引。
除了这种方式外,我们也可以使用小数点来调用:

print(df.标题1)

得到的结果是一样的,不过在程序里面用中文总觉得哪里怪怪的,我们可以自定义标题:

df.columns = ["title_1", "title_2", "title_3", "title_4"]
print(df.title_1)

获取符合条件的数据

比如我们需要获取第一列小于3的数据:

print(df[df.title_1 < 3])
#   title_1  title_2  title_3 title_4
#0        1       11      111      1a
#1        2       22      222      2a

比如我们需要获取第一列小于3并且第二列小于20的数据:

print(df[(df.title_1 < 3) & (df.title_2 < 20)]) 
#   title_1  title_2  title_3 title_4
#0        1       11      111      1a

注意不能使用and、or,必须用 &、| 和圆括号。
如果数据为字符串,我们也可以用字符串的方法来进行过滤,格式为.str.[string method]:

print(df[df.title_4.str.startswith("2")])
#   title_1  title_2  title_3 title_4
#1        2       22      222      2a
print(df[df.title_4.str.endswith("a")])
#   title_1  title_2  title_3 title_4
#0        1       11      111      1a
#1        2       22      222      2a
#2        3       33      333      3a
#3        4       44      444      4a
#4        5       55      555      5a

数据的索引

获取某条数据

比如我想获取第4行数据:

print(df.iloc[3])
#title_1      4
#title_2     44
#title_3    444
#title_4     4a
#Name: 3, dtype: object

注意索引是从0开始的。
比如我想获取第4列值为3a的那一条数据,我们可以先设置第四列为索引:

df = df.set_index(["title_4"])
print(df.loc["3a"])
#title_1      3
#title_2     33
#title_3    333
#Name: 3a, dtype: int64

此时我们打印一下数据集:

print(df)
#         title_1  title_2  title_3
#title_4                           
#1a             1       11      111
#2a             2       22      222
#3a             3       33      333
#4a             4       44      444
#5a             5       55      555

刚好可以验证我们之前0,1,2,3,4是索引的说法。
如果我们使用完毕,可以用以下方法来将索引恢复成数据形式:

df = df.reset_index(["title_4"]) 
print(df)
#  title_4  title_1  title_2  title_3
#0      1a        1       11      111
#1      2a        2       22      222
#2      3a        3       33      333
#3      4a        4       44      444
#4      5a        5       55      555

数据排序

我们将数据按降序排列:

df.sort_index(ascending=False, inplace=True)
print(df)
#  title_4  title_1  title_2  title_3
#4      5a        5       55      555
#3      4a        4       44      444
#2      3a        3       33      333
#1      2a        2       22      222
#0      1a        1       11      111

ascending:True为升序,False为降序。 inplace:是否替换原数据,默认False。
注意它的索引一起跟着倒序了,这时候我们调用df.iloc[1]得到的依然是2a那行数据。

数据的修改

删除行、列

我们可以使用drop方法来删除行或者列:

# 删除title_1列
result_2 = df.drop(labels=["title_1"], axis=1, inplace=False)
print(result_2)
#  title_4  title_2  title_3
#4      5a       55      555
#3      4a       44      444
#2      3a       33      333
#1      2a       22      222
#0      1a       11      111

# 删除前两列
result_2 = df.drop(labels=df.columns[[0, 1]], axis=1, inplace=False)
print(result_2)
#   title_2  title_3
#4       55      555
#3       44      444
#2       33      333
#1       22      222
#0       11      111

# 删除前两行
result_2 = df.drop(labels=[0, 1], axis=0, inplace=False)
print(result_2)
#  title_4  title_1  title_2  title_3
#4      5a        5       55      555
#3      4a        4       44      444
#2      3a        3       33      333

参数labels表示要删除的标签;axis为0表示行,1表示列,默认0;inplace表示是否要替换原数据集。

插入行、列

# 再最后添加一列
#df["title_5"] = ["1","2","3","4","5"]

# 插入到第一列
#data = ["1","2","3","4","5"]
#df2.insert(0,'title_5',data)

# 插入行,先切割两部分再拼接,可以使用append或者concat
#df_1.append(insertRow,ignore_index=True).append(df_2,ignore_index=True)
# 或者
#pd.concat([df_1,insertRow,df_2],ignore_index=True)

修改具体数据值

apply

当我们想让操作作用在一维的向量上时,可以使用apply。它可以作用于Series,也可以作用于DataFrame数据。

# 作用于某一列,Series数据。
df["title_5"] = df.title_4.apply(self.apply_data)   # 新增一列
print(df)

def apply_data(self, data):
    result = data[:1]
    return result + "b"

#  title_4  title_1  title_2  title_3 title_5
#4      5a        5       55      555      5b
#3      4a        4       44      444      4b
#2      3a        3       33      333      3b
#1      2a        2       22      222      2b
#0      1a        1       11      111      1b


# 作用于DataFrame 数据
result_2 = df.apply(self.apply_data_2)    # 获取第二行数据
print(result_2)

def apply_data_2(self, data):
   return data[1]

#title_4     2a
#title_1      2
#title_2     22
#title_3    222
#title_5     2b
#dtype: object

applymap

如果想让操作作用于DataFrame中的每一个元素,可以使用applymap():

df = df.applymap(self.applymap_data)
print(df)

def applymap_data(self, data):
    return str(data) + "c"

#  title_4 title_1 title_2 title_3 title_5
#4     5ac      5c     55c    555c     5bc
#3     4ac      4c     44c    444c     4bc
#2     3ac      3c     33c    333c     3bc
#1     2ac      2c     22c    222c     2bc
#0     1ac      1c     11c    111c     1bc

map

map()只能是将函数作用于一个Series的每一个元素:

print(df.title_1.map(self.apply_data))

#4    5b
#3    4b
#2    3b
#1    2b
#0    1b
#Name: title_1, dtype: object

总的来说就是apply()是一种让函数作用于列或者行操作,applymap()是一种让函数作用于DataFrame每一个元素的操作,而map是一种让函数作用于Series每一个元素的操作。

数据分组

为了方便演示我们先添加一列数据,然后通过groupby进行分组:

df["title_6"] = ["1", "0", "1", "0", "1"]
print(df.groupby(df.title_6).max())  # 获取每个分组里面最大的数据

#        title_4 title_1 title_2 title_3 title_5 title_6
#title_6                                                
#0           4ac      4c     44c    444c     4bc       0
#1           5ac      5c     55c    555c     5bc       1

print(df.groupby(df.title_6).max()["title_1"])  # 获取分组后的某列
 print(df.groupby([df.title_6, df.title_5]).max())
#title_6
#0    4c
#1    5c
#Name: title_1, dtype: object

类似的还有min(),mean()等方法。
我们也可以根据多个列进行分组:

df = df.groupby([df.title_6, df.title_5]).max()
print(df)
#                title_4 title_1 title_2 title_3 title_5 title_6
#title_6 title_5                                                
#0       2bc         2ac      2c     22c    222c     2bc       0
#        4bc         4ac      4c     44c    444c     4bc       0
#1       1bc         1ac      1c     11c    111c     1bc       1
#        3bc         3ac      3c     33c    333c     3bc       1
#        5bc         5ac      5c     55c    555c     5bc       1

我们也可以通过unstack方法来改变分组后的显示形式:

print(df.unstack(0))
#        title_4      title_1      title_2 ...  title_3 title_5      title_6     
#title_6       0    1       0    1       0 ...        1       0    1       0    1
#title_5                                   ...                                   
#1bc         NaN  1ac     NaN   1c     NaN ...     111c     NaN  1bc     NaN    1
#2bc         2ac  NaN      2c  NaN     22c ...      NaN     2bc  NaN       0  NaN
#3bc         NaN  3ac     NaN   3c     NaN ...     333c     NaN  3bc     NaN    1
#4bc         4ac  NaN      4c  NaN     44c ...      NaN     4bc  NaN       0  NaN
#5bc         NaN  5ac     NaN   5c     NaN ...     555c     NaN  5bc     NaN    1

#[5 rows x 12 columns]

print(df.unstack(1))
#        title_4                     ...  title_6                    
#title_5     1bc  2bc  3bc  4bc  5bc ...      1bc  2bc  3bc  4bc  5bc
#title_6                             ...                             
#0           NaN  2ac  NaN  4ac  NaN ...      NaN    0  NaN    0  NaN
#1           1ac  NaN  3ac  NaN  5ac ...        1  NaN    1  NaN    1

#[2 rows x 30 columns]

传入的参数0、1表示将第几个索引置为横向。
其中很多的NaN表示空记录,比如第一条记录对应title_5 = 1bc & title_6 = 0,实际数据集中没有这样的数据,因此显示NaN,如果觉得看起来不直观,也可以使用fillna方法来替换调NaN的显示:

print(df.unstack(0).fillna(""))

#        title_4      title_1     title_2 ... title_3 title_5      title_6   
#title_6       0    1       0   1       0 ...       1       0    1       0  1
#title_5                                  ...                                
#1bc              1ac          1c         ...    111c          1bc          1
#2bc         2ac           2c         22c ...             2bc            0   
#3bc              3ac          3c         ...    333c          3bc          1
#4bc         4ac           4c         44c ...             4bc            0   
#5bc              5ac          5c         ...    555c          5bc          1

#[5 rows x 12 columns]

fillna传入的参数表示你想要替换的显示值,这里传入空字符串,当然你也可以传入任意的字符串或者数字。

上面的一系列操作也可以用pivot方法来代替:

print(df)
#  title_4 title_1 title_2 title_3 title_5 title_6
#4     5ac      5c     55c    555c     5bc       1
#3     4ac      4c     44c    444c     4bc       0
#2     3ac      3c     33c    333c     3bc       1
#1     2ac      2c     22c    222c     2bc       0
#0     1ac      1c     11c    111c     1bc       1

print(df.pivot(index="title_6", columns="title_5", values=["title_1", "title_2"]).fillna(""))
#        title_1                 title_2                    
#title_5     1bc 2bc 3bc 4bc 5bc     1bc  2bc  3bc  4bc  5bc
#title_6                                                    
#0                2c      4c              22c       44c     
#1            1c      3c      5c     11c       33c       55c

参数index代表索引列,columns代表横向的那个分组,values表示要显示的值。上面的写法也可以写成:

# 获取所有数据再单独显示某几列
print(df.pivot("title_6", "title_5")[["title_1", "title_2"]].fillna(""))

数据合并

如果有两个相关联的数据集,比如两个数据集有相同的某列,可以用merge方法合并成一个数据集。

# 以title_1为根据将两个数据集合并
df.merge(df_other, on='title_1')

数据的保存

还是以Excel为例,我们将数据读取进来,进行一系列操作后,很多时候会希望保存下来,我们可以直接使用to_excel方法,注意需要安装openpyxl库:

df.to_excel("data_new.xlsx")
to_excel.png
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容