pandas快速入门
numpy之后让我们紧接着学习pandas。Pandas最初被作为金融数据分析工具而开发出来,后来因为其强大性以及友好性,在数据分析领域被广泛使用,下面让我们一窥究竟。
本文参考官网给出的10 Minutes to pandas
对象创建
创建Series
#创建Series对象,index参数可省,默认为0~n-1的数字索引
#与numpy中的array一样,统一Series要求数据类型一致,这样可以加快处理速度
In [12]: s = pd.Series([1,2,3,np.nan,5,7],index=list('ABCDEF'))
In [13]: s
Out[13]:
A 1.0
B 2.0
C 3.0
D NaN
E 5.0
F 7.0
dtype: float64
创建dataFrame
1.使用numpy array创建
In [4]: dates = pd.date_range('20170909',periods=6) #pandas对于时间的处理也很出色
In [5]: dates
Out[5]:
DatetimeIndex(['2017-09-09', '2017-09-10', '2017-09-11', '2017-09-12',
'2017-09-13', '2017-09-14'],
dtype='datetime64[ns]', freq='D')
In [6]: df = pd.DataFrame(np.random.randn(6,4),index=dates,columns=list('ABCD'))
...: #pd.DataFrame(数组, 行索引(可省), 列索引一般不省略)
In [7]: df
Out[7]:
A B C D
2017-09-09 -0.874363 -0.682658 0.533449 -0.396235
2017-09-10 0.878331 0.825946 1.075934 -0.820331
2017-09-11 0.720920 0.095851 -1.521827 1.252951
2017-09-12 -1.338117 0.787224 0.450896 0.586154
2017-09-13 0.954178 -0.475164 0.356891 -1.428600
2017-09-14 1.081780 0.846195 -0.070906 -0.805635
2.使用字典创建
df2 = pd.DataFrame({ 'A':[1,2,3],
'B':[3,4,5],
'C':np.arange(3)
})
print df2
A B C
0 1 3 0
1 2 4 1
2 3 5 2
网上使用多种数据类型也是可以的,博主认为同种类型更加常用一点吧
查看数据类型与numpy一样,是
df.dtypes
完成创建后,列将作为df的属性,可以通过df.A直接访问列
查看数据
查看数据就需要数据,博主这里使用的数据样例是之前爬取的中国城市历史天气
In [41]: df = pd.read_csv('./weather.csv')
In [42]: df.head(10) #这里取前10条记录,默认为5条
Out[42]:
city pinYin rainy cloudy sunny overcast snowy
0 阿城 acheng 563 761 809 8 215
1 昂昂溪区 angangxiqu 158 474 213 28 29
2 爱民区 aiminqu 269 304 253 17 72
3 安达 anda 523 977 700 0 169
4 安图 antu 580 868 704 2 219
5 鞍山 anshan 504 736 988 3 133
6 阿鲁旗 aluqi 445 821 935 54 120
7 敖汉 aohan 462 821 928 48 109
8 阿巴嘎 abaga 363 694 1086 54 169
9 阿荣旗 arongqi 522 942 624 74 212
...
In [47]: df.tail() #tail同理
Out[47]:
city pinYin rainy cloudy sunny overcast snowy
3200 资源 ziyuan 1230 824 199 95 23
3201 昭平 zhaoping 1333 845 131 61 0
3202 钟山 zhongshan1 1317 861 131 63 0
3203 昭平区 zhaopingqu 467 326 66 38 0
3204 彰化 zhanghua 1241 472 93 117 0
查看元数据
In [48]: df.index #行属性
Out[48]: RangeIndex(start=0, stop=3205, step=1)
In [49]: df.columns #列属性
Out[49]:
Index([u'city', u'pinYin', u'rainy', u'cloudy', u'sunny', u'overcast',
u'snowy'],
dtype='object')
#统计数据,只会对数值类的进行计算
In [51]: df.describe()
Out[51]:
rainy cloudy sunny overcast snowy
count 3205.000000 3205.000000 3205.000000 3205.000000 3205.000000
mean 651.232137 797.288300 423.981591 104.118565 62.204680
std 344.324084 292.436344 302.132459 90.538331 81.090957
min 0.000000 0.000000 0.000000 0.000000 0.000000
25% 404.000000 596.000000 174.000000 43.000000 9.000000
50% 543.000000 855.000000 326.000000 86.000000 39.000000
75% 957.000000 991.000000 668.000000 136.000000 74.000000
max 1775.000000 1761.000000 1424.000000 614.000000 726.000000
另外,df.T求转置
排序
In [64]: df.sort_values(by='sunny',ascending=False).head()
Out[64]:
city pinYin rainy cloudy sunny overcast snowy
356 磴口 dengkou 221 675 1424 6 33
2418 乌后旗 wuhouqi 174 718 1421 8 29
790 杭锦后旗 hangjinhouqi 204 694 1421 11 28
508 额济纳 ejina 75 761 1405 30 17
2415 五原 wuyuan 234 675 1405 6 38
选择数据
基本操作(不推荐)
df['city'] #列选择,跟df.city一样
df[0:3] #行选择
- 通过标签选择
In [74]: df.loc[0:5,['city','rainy']]
Out[74]:
city rainy
0 阿城 563
1 昂昂溪区 158
2 爱民区 269
3 安达 523
4 安图 580
5 鞍山 504
#如果只选择一个标量,用at可以加速
In [79]: df.at[2,'snowy']
Out[79]: 72
- 通过位置(整数)索引
#单行记录
In [80]: df.iloc[2]
Out[80]:
city 爱民区
pinYin aiminqu
rainy 269
cloudy 304
sunny 253
overcast 17
snowy 72
Name: 2, dtype: object
#中间切片
In [82]: df.iloc[3:6]
Out[82]:
city pinYin rainy cloudy sunny overcast snowy
3 安达 anda 523 977 700 0 169
4 安图 antu 580 868 704 2 219
5 鞍山 anshan 504 736 988 3 133
#取指定一个属性
In [83]: df.iloc[3:6,[2,4]]
Out[83]:
rainy sunny
3 523 700
4 580 704
5 504 988
#同样,如果只选择一个标量,用at可以加速
In [84]: df.iloc[3,3]
Out[84]: 977
In [85]: df.iat[3,3]
Out[85]: 977
- 布尔索引
In [92]: df[df.cloudy>1600]
Out[92]:
city pinYin rainy cloudy sunny overcast snowy
493 东方 dongfang 555 1761 3 58 0
841 哈密 hami 107 1752 467 0 44
2249 三亚 sanya 722 1621 16 18 0
2870 伊吾 yiwu 170 1627 466 1 110
2913 宜昌县 yichangxian 469 1667 121 80 19
#集合包含可以用isin来过滤
In [95]: df[df.snowy.isin([0,1,2,3,4,5])]
设置新值
1.通过Series添加新列
In [45]: s1 = pd.Series([1,2,3,4,5,6], index=pd.date_range('20130102', periods=6))
In [47]: df['F'] = s1
2.直接修改数据项
In [48]: df.at[dates[0],'A'] = 0
In [49]: df.iat[0,1] = 0
In [50]: df.loc[:,'D'] = np.array([5] * len(df))
#更高阶技巧
In [52]: df2 = df.copy()
In [53]: df2[df2 > 0] = -df2
处理缺失值nan
In [58]: df1.dropna(how='any') #删除有确实的记录
In [59]: df1.fillna(value=n5) #用默认值填充
In [60]: pd.isnull(df1) #返回布尔矩阵,找出有nan的位置
相关操作
统计
In [61]: df.mean() #对每一列进行统计
Out[61]:
A -0.004474
B -0.383981
C -0.687758
D 5.000000
F 3.000000
dtype: float64
In [62]: df.mean(1) #横轴统计
Out[62]:
2013-01-01 0.872735
2013-01-02 1.431621
2013-01-03 0.707731
2013-01-04 1.395042
2013-01-05 1.883656
2013-01-06 1.592306
Freq: D, dtype: float64
Apply定制函数
In [66]: df.apply(np.cumsum)
Out[66]:
A B C D F
2013-01-01 0.000000 0.000000 -1.509059 5 NaN
2013-01-02 1.212112 -0.173215 -1.389850 10 1.0
2013-01-03 0.350263 -2.277784 -1.884779 15 3.0
2013-01-04 1.071818 -2.984555 -2.924354 20 6.0
2013-01-05 0.646846 -2.417535 -2.648122 25 10.0
2013-01-06 -0.026844 -2.303886 -4.126549 30 15.0
In [67]: df.apply(lambda x: x.max() - x.min())
Out[67]:
A 2.073961
B 2.671590
C 1.785291
D 0.000000
F 4.000000
dtype: float64
直方图统计
In [102]: df.cloudy.value_counts() #对于Series进行计数统计
字符串操作
#字符串的操作权包含在 str里面,也是对于Series
In [104]: df.pinYin.str.upper()
合并
concat
In [106]: df
Out[106]:
0 1 2 3
0 3 1 3 8
1 9 8 5 1
2 1 8 5 2
3 9 6 8 3
4 7 2 6 8
5 5 8 1 2
6 7 3 9 1
7 1 1 9 4
8 3 5 9 5
9 9 2 9 1
In [107]: pieces = [df[:3],df[3:7],df[7:]]
In [108]: pieces
Out[108]:
[ 0 1 2 3
0 3 1 3 8
1 9 8 5 1
2 1 8 5 2, 0 1 2 3
3 9 6 8 3
4 7 2 6 8
5 5 8 1 2
6 7 3 9 1, 0 1 2 3
7 1 1 9 4
8 3 5 9 5
9 9 2 9 1]
In [109]: pd.concat(pieces,axis=1)
Out[109]:
0 1 2 3 0 1 2 3 0 1 2 3
0 3.0 1.0 3.0 8.0 NaN NaN NaN NaN NaN NaN NaN NaN
1 9.0 8.0 5.0 1.0 NaN NaN NaN NaN NaN NaN NaN NaN
2 1.0 8.0 5.0 2.0 NaN NaN NaN NaN NaN NaN NaN NaN
3 NaN NaN NaN NaN 9.0 6.0 8.0 3.0 NaN NaN NaN NaN
4 NaN NaN NaN NaN 7.0 2.0 6.0 8.0 NaN NaN NaN NaN
5 NaN NaN NaN NaN 5.0 8.0 1.0 2.0 NaN NaN NaN NaN
6 NaN NaN NaN NaN 7.0 3.0 9.0 1.0 NaN NaN NaN NaN
7 NaN NaN NaN NaN NaN NaN NaN NaN 1.0 1.0 9.0 4.0
8 NaN NaN NaN NaN NaN NaN NaN NaN 3.0 5.0 9.0 5.0
9 NaN NaN NaN NaN NaN NaN NaN NaN 9.0 2.0 9.0 1.0
In [110]: pd.concat(pieces,axis=0)
Out[110]:
0 1 2 3
0 3 1 3 8
1 9 8 5 1
2 1 8 5 2
3 9 6 8 3
4 7 2 6 8
5 5 8 1 2
6 7 3 9 1
7 1 1 9 4
8 3 5 9 5
9 9 2 9 1
join
与SQL中的join一致,调用的是merge方法
#key出现重复,所以直接使用笛卡尔积
In [114]: left = pd.DataFrame({'key':['a','a'],'value':[1,2]})
In [115]: right = pd.DataFrame({'key':['a','a'],'value':[3,4]})
In [116]: pd.merge(left, right, on='key')
Out[116]:
key value_x value_y
0 a 1 3
1 a 1 4
2 a 2 3
3 a 2 4
#on的key是unique则去重进行join
In [117]: right = pd.DataFrame({'key':['a','b'],'value':[3,4]})
In [118]: left = pd.DataFrame({'key':['a','b'],'value':[1,2]})
In [120]: pd.merge(left,right,on='key')
Out[120]:
key value_x value_y
0 a 1 3
1 b 2 4
append
添加一条记录
In [87]: df = pd.DataFrame(np.random.randn(8, 4), columns=['A','B','C','D'])
In [88]: df
Out[88]:
A B C D
0 1.346061 1.511763 1.627081 -0.990582
1 -0.441652 1.211526 0.268520 0.024580
2 -1.577585 0.396823 -0.105381 -0.532532
3 1.453749 1.208843 -0.080952 -0.264610
4 -0.727965 -0.589346 0.339969 -0.693205
5 -0.339355 0.593616 0.884345 1.591431
6 0.141809 0.220390 0.435589 0.192451
7 -0.096701 0.803351 1.715071 -0.708758
In [89]: s = df.iloc[3]
In [90]: df.append(s, ignore_index=True)
Out[90]:
A B C D
0 1.346061 1.511763 1.627081 -0.990582
1 -0.441652 1.211526 0.268520 0.024580
2 -1.577585 0.396823 -0.105381 -0.532532
3 1.453749 1.208843 -0.080952 -0.264610
4 -0.727965 -0.589346 0.339969 -0.693205
5 -0.339355 0.593616 0.884345 1.591431
6 0.141809 0.220390 0.435589 0.192451
7 -0.096701 0.803351 1.715071 -0.708758
8 1.453749 1.208843 -0.080952 -0.264610
#注意添加的记录数据类型是Series
In [124]: s
Out[124]:
A 0.077384
B -0.716115
C 0.427943
D 0.057282
Name: 3, dtype: float64
分组
In [91]: df = pd.DataFrame({'A' : ['foo', 'bar', 'foo', 'bar',
....: 'foo', 'bar', 'foo', 'foo'],
....: 'B' : ['one', 'one', 'two', 'three',
....: 'two', 'two', 'one', 'three'],
....: 'C' : np.random.randn(8),
....: 'D' : np.random.randn(8)})
....:
In [92]: df
Out[92]:
A B C D
0 foo one -1.202872 -0.055224
1 bar one -1.814470 2.395985
2 foo two 1.018601 1.552825
3 bar three -0.595447 0.166599
4 foo two 1.395433 0.047609
5 bar two -0.392670 -0.136473
6 foo one 0.007207 -0.561757
7 foo three 1.928123 -1.623033
In [93]: df.groupby('A').sum()
Out[93]:
C D
A
bar -2.802588 2.42611
foo 3.146492 -0.63958
#也可以使用其他函数 如
#df.groupby('A').apply(np.sum)
作图
In [135]: ts = pd.Series(np.random.randn(1000), index=pd.date_range('1/1/2000', periods=1000))
In [136]: ts = ts.cumsum()
In [137]: ts.plot()
Out[137]: <matplotlib.axes._subplots.AxesSubplot at 0x1187d7278>
In [138]: plt.show()
#以Index为横坐标,其他值为纵坐标作图
小结
pandas还有很多高级用法,博主也在学习中,以上只列出比较常用的。
根据二八定理,差不多可以开始使用pandas愉快地处理数据了,其他的高级用法就即用即查吧,欢迎大家讨论交流。