《利用Python进行数据分析》第五章 pandas的基本功能

来源:互联网 发布:ubuntu 中文输入 编辑:程序博客网 时间:2024/06/08 02:44

介绍操作Series和DataFrame中的数据的基本功能

重新索引
pandas对象的一个重要方法是reindex,其作用是创建一个适应新索引的新对象。以之前的一个简单示例来说

In [1]: from pandas import Series,DataFrameIn [2]: import pandas as pdIn [3]: import numpy as npIn [4]: obj=Series([6.5,7.8,-5.9,8.6],index=['d','b','a','c'])In [5]: objOut[5]: d 6.5b 7.8a -5.9c 8.6dtype: float64

调用该Series的reindex将会根据新索引进行重排。如果某个索引值当前不存在,就引入缺失值

In [6]: obj2=obj.reindex(['a', 'b', 'c', 'd', 'e'])In [7]: obj2Out[7]: a -5.9b 7.8c 8.6d 6.5e NaNdtype: float64In [8]: obj.reindex(['a', 'b', 'c', 'd', 'e'], fill_value=0)Out[8]: a -5.9b 7.8c 8.6d 6.5e 0.0dtype: float64In [9]: obj3=Series(['blue', 'purple', 'yellow'], index=[0, 2, 4])In [10]: obj3.reindex(range(6), method='ffill')Out[10]: 0 blue1 blue2 purple3 purple4 yellow5 yellowdtype: objectIn [11]: obj3.reindex(range(6), method='bfill')Out[11]: 0 blue1 purple2 purple3 yellow4 yellow5 NaNdtype: objectIn [12]: obj3.reindex(range(6), method='pad')Out[12]: 0 blue1 blue2 purple3 purple4 yellow5 yellowdtype: object


对于DataFrame,reindex可以修改(行)索引、列,或两个都修改。如果仅传入一个序列,则会重新索引行

In [13]: frame = DataFrame(np.arange(9).reshape((3, 3)), index=['a', 'c', 'd'],columns=['Ohio', 'Texas', 'California'])In [14]: frameOut[14]: Ohio Texas Californiaa 0 1 2c 3 4 5d 6 7 8In [15]: frame2=frame.reindex(['a', 'b', 'c', 'd'])In [16]: frame2Out[16]: Ohio Texas Californiaa 0.0 1.0 2.0b NaN NaN NaNc 3.0 4.0 5.0d 6.0 7.0 8.0

使用columns关键字即可重新索引列

In [17]: states = ['Texas', 'Utah', 'California']In [18]: frame.reindex(columns=states)Out[18]: Texas Utah Californiaa 1 NaN 2c 4 NaN 5d 7 NaN 8

利用ix的标签索引功能

In [28]: frameOut[28]: Ohio Texas Californiaa 0 1 2c 3 4 5d 6 7 8In [31]: states = ['Texas', 'Utah', 'California']In [32]: frame.ix[['a', 'b', 'c', 'd'], states]Out[32]: Texas Utah Californiaa 1.0 NaN 2.0b NaN NaN NaNc 4.0 NaN 5.0d 7.0 NaN 8.0


丢弃某条轴上的一个或多个项很简单,只要有一个索引数组或列表即可。由于需要执行一些数据整理和集合逻辑,所以drop方法返回的是一个在指定轴上删除了指定值的新对象

In [33]: obj=Series(np.arange(5.),index=['a', 'b', 'c', 'd', 'e'])In [34]: objOut[34]: a 0.0b 1.0c 2.0d 3.0e 4.0dtype: float64In [35]: new_obj=obj.drop('c')In [36]: new_objOut[36]: a 0.0b 1.0d 3.0e 4.0dtype: float64In [37]: obj.drop(['d','b'])Out[37]: a 0.0c 2.0e 4.0dtype: float64

对于DataFrame,可以删除任意轴上的索引值

In [41]: data = DataFrame(np.arange(16).reshape((4, 4)),    ...: index=['Ohio', 'Colorado', 'Utah', 'New York'],     ...: columns=['one', 'two', 'three', 'four'])In [42]: dataOut[42]: one two three fourOhio 0 1 2 3Colorado 4 5 6 7Utah 8 9 10 11New York 12 13 14 15In [43]: data.drop(['Colorado', 'Ohio'])Out[43]: one two three fourUtah 8 9 10 11New York 12 13 14 15In [44]: data.drop('two',axis=1)Out[44]: one three fourOhio 0 2 3Colorado 4 6 7Utah 8 10 11New York 12 14 15In [45]: data.drop(['two', 'four'], axis=1)Out[45]: one threeOhio 0 2Colorado 4 6Utah 8 10New York 12 14

索引、选取和过滤
Series的索引值不只是整数

In [47]: obj=Series(np.arange(5.),index=['a', 'b', 'c', 'd','e'])In [48]: objOut[48]: a 0.0b 1.0c 2.0d 3.0e 4.0dtype: float64In [49]: obj['b']Out[49]: 1.0In [50]: obj[3]Out[50]: 3.0In [51]: obj[3:5]Out[51]: d 3.0e 4.0dtype: float64In [52]: obj[['b','e','d']]Out[52]: b 1.0e 4.0d 3.0dtype: float64In [53]: obj[[1,4]]Out[53]: b 1.0e 4.0dtype: float64In [54]: obj[obj<3]Out[54]: a 0.0b 1.0c 2.0dtype: float64

利用标签的切片运算与普通的Python切片运算不同,其末端是包含的(inclusive)

In [55]: obj['b':'d']Out[55]: b 1.0c 2.0d 3.0dtype: float64In [56]: obj['b':'d']=6In [57]: objOut[57]: a 0.0b 6.0c 6.0d 6.0e 4.0dtype: float64

DataFrame进行索引其实就是获取一个或多个列

In [60]: data = DataFrame(np.arange(16).reshape((4, 4)),    ...: index=['Ohio', 'Colorado', 'Utah', 'New York'],    ...: columns=['one', 'two', 'three', 'four'])In [61]: dataOut[61]: one two three fourOhio 0 1 2 3Colorado 4 5 6 7Utah 8 9 10 11New York 12 13 14 15In [62]: data['two']Out[62]: Ohio 1Colorado 5Utah 9New York 13Name: two, dtype: int32In [63]: data[['three','one']]Out[63]: three oneOhio 2 0Colorado 6 4Utah 10 8New York 14 12

通过切片或布尔型数组选取行

In [64]: data[:3]Out[64]: one two three fourOhio 0 1 2 3Colorado 4 5 6 7Utah 8 9 10 11In [65]: data[data['three']>5]Out[65]: one two three fourColorado 4 5 6 7Utah 8 9 10 11New York 12 13 14 15

通过布尔型DataFrame(比如下面由标量比较运算得出的)进行索引

In [66]: data<6Out[66]: one two three fourOhio True True True TrueColorado True True False FalseUtah False False False FalseNew York False False False FalseIn [67]: data[data<5]=0In [68]: dataOut[68]: one two three fourOhio 0 0 0 0Colorado 0 5 6 7Utah 8 9 10 11New York 12 13 14 15

利用索引字段ix,它可以通过NumPy式的标记法以及轴标签从DataFrame中选取行和列的子集。其中:ix is deprecated,可以使用loc

In [69]: data.ix['Colorado', ['two', 'three']]C:\ProgramData\Anaconda3\lib\site-packages\ipykernel_launcher.py:1: DeprecationWarning: .ix is deprecated. Please use.loc for label based indexing or.iloc for positional indexingSee the documentation here:http://pandas.pydata.org/pandas-docs/stable/indexing.html#deprecate_ix"""Entry point for launching an IPython kernel.Out[69]: two 5three 6Name: Colorado, dtype: int32In [70]: data.loc['Colorado', ['two', 'three']]Out[70]: two 5three 6Name: Colorado, dtype: int32In [71]: data.ix[['Colorado', 'Utah'], [3, 0, 1]]Out[71]: four one twoColorado 7 0 5Utah 11 8 9In [72]: data.ix[2]Out[72]: one 8two 9three 10four 11Name: Utah, dtype: int32In [73]: data.loc[:'Utah','two']Out[73]: Ohio 0Colorado 5Utah 9Name: two, dtype: int32In [74]: data.ix[data.three>5]Out[74]: one two three fourColorado 0 5 6 7Utah 8 9 10 11New York 12 13 14 15In [75]: data.ix[data.three > 5, :3]Out[75]: one two threeColorado 0 5 6Utah 8 9 10New York 12 13 14

对pandas对象中的数据的选取和重排方式有很多

为什么不是输出7 4 5,而输出的是7 0 5,是不能理解的小地方,只能慢慢体会其中的用法。

其中,get_value方法是选取,set-value方法是设置

算术运算和数据对齐
Pandas可以对不同索引的对象进行算术运算。在将对象相加时,如果存在不同的索引对,则结果的索引就是该索引对的并集。

In [77]: s1=Series([6.8,-4.5,3.6,5.6],index=['a','c','d','e'])In [78]: s2 = Series([-6.5, 3.6, -5.6, 4, 3.1], index=['a', 'c', 'e', 'f', 'g'])In [79]: s1Out[79]: a 6.8c -4.5d 3.6e 5.6dtype: float64In [80]: s2Out[80]: a -6.5c 3.6e -5.6f 4.0g 3.1dtype: float64In [81]: s1+s2Out[81]: a 0.3c -0.9d NaNe 0.0f NaNg NaNdtype: float64

自动的数据对齐操作在不重叠的索引处引入了NA值。缺失值会在算术运算过程中传播。对于DataFrame,对齐操作会同时发生在行和列上。相加后将会返回一个新的DataFrame,其索引和列为原来那两个DataFrame的并集

In [85]: df1 = DataFrame(np.arange(9.).reshape((3, 3)), columns=list('bcd'),    ...: index=['Ohio', 'Texas', 'Colorado'])In [86]: df2 = DataFrame(np.arange(12.).reshape((4, 3)), columns=list('bde'),    ...: index=['Utah', 'Ohio', 'Texas', 'Oregon'])In [87]: df1Out[87]: b c dOhio 0.0 1.0 2.0Texas 3.0 4.0 5.0Colorado 6.0 7.0 8.0In [88]: df2Out[88]: b d eUtah 0.0 1.0 2.0Ohio 3.0 4.0 5.0Texas 6.0 7.0 8.0Oregon 9.0 10.0 11.0In [89]: df1+df2Out[89]: b c d eColorado NaN NaN NaN NaNOhio 3.0 NaN 6.0 NaNOregon NaN NaN NaN NaNTexas 9.0 NaN 12.0 NaNUtah NaN NaN NaN NaN

在算术方法中填充值
在对不同索引的对象进行算术运算时,你可能希望当一个对象中某个轴标签在另一个对象中找不到时填充一个特殊值(比如0),相加时,没有重叠的位置就会产生NA值。

In [95]: f1 = DataFrame(np.arange(12.).reshape((3, 4)), columns=list('abcd'))In [96]: f2 = DataFrame(np.arange(20.).reshape((4, 5)), columns=list('abcde'))In [97]: f1Out[97]: a b c d0 0.0 1.0 2.0 3.01 4.0 5.0 6.0 7.02 8.0 9.0 10.0 11.0In [98]: f2Out[98]: a b c d e0 0.0 1.0 2.0 3.0 4.01 5.0 6.0 7.0 8.0 9.02 10.0 11.0 12.0 13.0 14.03 15.0 16.0 17.0 18.0 19.0In [99]: f1+f2Out[99]: a b c d e0 0.0 2.0 4.0 6.0 NaN1 9.0 11.0 13.0 15.0 NaN2 18.0 20.0 22.0 24.0 NaN3 NaN NaN NaN NaN NaN

使用add方法,传入f2以及一个fill_value参数

In [102]: f1.add(f2, fill_value=0)Out[102]: a b c d e0 0.0 2.0 4.0 6.0 4.01 9.0 11.0 13.0 15.0 9.02 18.0 20.0 22.0 24.0 14.03 15.0 16.0 17.0 18.0 19.0

在对Series或DataFrame重新索引时,也可以指定一个填充值

In [103]: f1.reindex(columns=f2.columns, fill_value=0)Out[103]: a b c d e0 0.0 1.0 2.0 3.0 01 4.0 5.0 6.0 7.0 02 8.0 9.0 10.0 11.0 0In [105]: f1*f2Out[105]: a b c d e0 0.0 1.0 4.0 9.0 NaN1 20.0 30.0 42.0 56.0 NaN2 80.0 99.0 120.0 143.0 NaN3 NaN NaN NaN NaN NaN


DataFrame和Series之间的运算
计算一个二维数组与其某行之间的差,出现的结果这就叫做广播(broadcasting),如下:

In [106]: arr=np.arange(12.).reshape((3,4))In [107]: arrOut[107]: array([[ 0., 1., 2., 3.],[ 4., 5., 6., 7.],[ 8., 9., 10., 11.]])In [108]: arr[0]Out[108]: array([ 0., 1., 2., 3.])In [109]: arr-arr[0]Out[109]: array([[ 0., 0., 0., 0.],[ 4., 4., 4., 4.],[ 8., 8., 8., 8.]])

默认情况下,DataFrame和Series之间的算术运算会将Series的索引匹配到DataFrame的列,然后沿着行一直向下广播

In [110]: frame = DataFrame(np.arange(12.).reshape((4, 3)), columns=list('bde'),     ...: index=['Utah', 'Ohio', 'Texas', 'Oregon'])In [111]: frameOut[111]: b d eUtah 0.0 1.0 2.0Ohio 3.0 4.0 5.0Texas 6.0 7.0 8.0Oregon 9.0 10.0 11.0In [112]: series = frame.ix[0]In [113]: seriesOut[113]: b 0.0d 1.0e 2.0Name: Utah, dtype: float64In [114]: frame-seriesOut[114]: b d eUtah 0.0 0.0 0.0Ohio 3.0 3.0 3.0Texas 6.0 6.0 6.0Oregon 9.0 9.0 9.0

如果某个索引值在DataFrame的列或Series的索引中找不到,则参与运算的两个对象就会被重新索引以形成并集

In [115]: series2 = Series(range(3), index=['b', 'e', 'f'])In [116]: series2Out[116]: b 0e 1f 2dtype: int32In [117]: frame + series2Out[117]: b d e fUtah 0.0 NaN 3.0 NaNOhio 3.0 NaN 6.0 NaNTexas 6.0 NaN 9.0 NaNOregon 9.0 NaN 12.0 NaN

如果你希望匹配行且在列上广播,则必须使用算术运算方法。

In [118]: series3 = frame['d']In [119]: series3Out[119]: Utah 1.0Ohio 4.0Texas 7.0Oregon 10.0Name: d, dtype: float64In [120]: frameOut[120]: b d eUtah 0.0 1.0 2.0Ohio 3.0 4.0 5.0Texas 6.0 7.0 8.0Oregon 9.0 10.0 11.0In [121]: frame.sub(series3, axis=0)Out[121]: b d eUtah -1.0 0.0 1.0Ohio -1.0 0.0 1.0Texas -1.0 0.0 1.0Oregon -1.0 0.0 1.0

传入的轴号就是希望匹配的轴。

函数应用和映射
NumPy的ufuncs(元素级数组方法)也可用于操作pandas对象

In [122]: frame = DataFrame(np.random.randn(4, 3), columns=list('bde'),     ...: index=['Utah', 'Ohio', 'Texas', 'Oregon'])In [123]: frameOut[123]: b d eUtah -0.976531 -1.511940 -0.018721Ohio 0.598117 0.047678 -0.058404Texas 2.469704 0.027215 1.154004Oregon 1.308615 -1.634739 0.096210In [124]: np.abs(frame)Out[124]: b d eUtah 0.976531 1.511940 0.018721Ohio 0.598117 0.047678 0.058404Texas 2.469704 0.027215 1.154004Oregon 1.308615 1.634739 0.096210

将函数应用到由各列或行所形成的一维数组上。DataFrame的apply方法即可实现此功能。

In [125]: f = lambda x: x.max() - x.min()In [126]: frame.apply(f)Out[126]: b 3.446234d 1.682417e 1.212408dtype: float64In [127]: frame.apply(f,axis=1)Out[127]: Utah 1.493219Ohio 0.656521Texas 2.442489Oregon 2.943355dtype: float64

sum和mean方法

In [128]: def f(x):     ...: return Series([x.min(), x.max()], index=['min', 'max'])     ...: In [129]: frame.apply(f)Out[129]: b d emin -0.976531 -1.634739 -0.058404max 2.469704 0.047678 1.154004

得到frame中各个浮点值的格式化字符串,使用applymap

In [128]: def f(x):     ...:return Series([x.min(), x.max()], index=['min', 'max'])In [129]: frame.apply(f)Out[129]: b d emin -0.976531 -1.634739 -0.058404max 2.469704 0.047678 1.154004In [130]: format = lambda x: '%.2f' % xIn [131]: frame.applymap(format)Out[131]: b d eUtah -0.98 -1.51 -0.02Ohio 0.60 0.05 -0.06Texas 2.47 0.03 1.15Oregon 1.31 -1.63 0.10

Series有一个用于应用元素级函数的map方法

In [132]: frame['e'].map(format)Out[132]: Utah -0.02Ohio -0.06Texas 1.15Oregon 0.10Name: e, dtype: object

排序和排名
根据条件对数据集排序(sorting)也是一种重要的内置运算。要对行或列索引进行排序(按字典顺序),可使用sort_index方法,它将返回一个已排序的新对象

In [133]: obj = Series(range(4), index=['d', 'a', 'b', 'c'])In [134]: objOut[134]: d 0a 1b 2c 3dtype: int32In [135]: obj.sort_index()Out[135]: a 1b 2c 3d 0dtype: int32

DataFrame,则可以根据任意一个轴上的索引进行排序

In [136]: frame = DataFrame(np.arange(8).reshape((2, 4)), index=['three', 'one'],     ...: columns=['d', 'a', 'b', 'c'])In [137]: frameOut[137]: d a b cthree 0 1 2 3one 4 5 6 7In [138]: frame.sort_index()Out[138]: d a b cone 4 5 6 7three 0 1 2 3In [139]: frame.sort_index(axis=1)Out[139]: a b c dthree 1 2 3 0one 5 6 7 4

数据默认是按升序排序的,但也可以降序排序

In [140]: frame.sort_index(axis=1,ascending=False)Out[140]: d c b athree 0 3 2 1one 4 7 6 5

series通过索引进行排序

In [148]: obj = Series([6, 9, -8, 3])In [149]: obj.sort_index()Out[149]: 0 61 92 -83 3dtype: int64

series通过升值进行排序

In [150]: obj.sort_values()Out[150]: 2 -83 30 61 9dtype: int64

在排序时,任何缺失值默认都会被放到Series的末尾,其中order不能排序,使用sort_values进行排序

In [151]: obj = Series([4, np.nan, 6, np.nan, -3, 3])In [152]: obj.order()---------------------------------------------------------------------------AttributeError Traceback (most recent call last)<ipython-input-152-4fc888977b98> in <module>()----> 1 obj.order()C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\generic.py in __getattr__(self, name)2968 if name in self._info_axis:2969 return self[name]-> 2970 return object.__getattribute__(self, name)2971 2972 def __setattr__(self, name, value):AttributeError: 'Series' object has no attribute 'order'In [153]: obj.sort_values()Out[153]: 4 -3.05 3.00 4.02 6.01 NaN3 NaNdtype: float64

希望根据一个或多个列中的值进行排序,可以将一个或多个列的名字传递给by选项

In [154]: frame = DataFrame({'b': [5, 8, -6, 3], 'a': [0, 1, 0, 1]})In [155]: frameOut[155]: a b0 0 51 1 82 0 -63 1 3In [156]: frame.sort_index(by='b')Out[156]: a b2 0 -63 1 30 0 51 1 8In [157]: frame.sort_index(by=['a','b'])C:\ProgramData\Anaconda3\lib\site-packages\ipykernel_launcher.py:1: FutureWarning: by argument to sort_index is deprecated, pls use .sort_values(by=...)"""Entry point for launching an IPython kernel.Out[157]: a b2 0 -60 0 53 1 31 1 8

要根据多个列进行排序,传入名称的列表

In [158]: frame.sort_values(by=['a','b'])Out[158]: a b2 0 -60 0 53 1 31 1 8

排名(ranking)跟排序关系密切,且它会增设一个排名值(从1开始,一直到数组中有效数据的数量)。它跟numpy.argsort产生的间接排序索引差不多,只不过它可以根据某种规则破坏平级关系。默认情况下,rank是通过“为各组分配一个平均排名”的方式破坏平级关系的:

In [159]: obj = Series([8, -6, 5, 4, 2, 0, 4])In [160]: objOut[160]: 0 81 -62 53 44 25 06 4dtype: int64In [161]: obj.rank()Out[161]: 0 7.01 1.02 6.03 4.54 3.05 2.06 4.5dtype: float64

可以根据值在原数据中出现的顺序给出排名

In [162]: obj.rank(method='first')Out[162]: 0 7.01 1.02 6.03 4.04 3.05 2.06 5.0dtype: float64

按降序进行排名

In [163]: obj.rank(ascending=False, method='max')Out[163]: 0 1.01 7.02 2.03 4.04 5.05 6.06 4.0dtype: float64

在行或列上计算排名

In [164]: frame = DataFrame({'b': [4.3, 7, -3, 2], 'a': [0, 1, 0, 1],     ...: 'c': [-2, 5, 8, -2.5]})In [165]: frameOut[165]: a b c0 0 4.3 -2.01 1 7.0 5.02 0 -3.0 8.03 1 2.0 -2.5In [166]: frame.rank(axis=1)Out[166]: a b c0 2.0 3.0 1.01 1.0 3.0 2.02 2.0 1.0 3.03 2.0 3.0 1.0


带有重复值的轴索引值的Series

In [167]: obj = Series(range(5), index=['a', 'a', 'b', 'b', 'c'])In [168]: objOut[168]: a 0a 1b 2b 3c 4dtype: int32

is_unique属性可以告诉它的值是否是唯一的

In [169]: obj.index.is_uniqueOut[169]: False

对于带有重复值的索引,数据选取的行为将会有些不同。如果某个索引对应多个值,则返回一个Series;而对应单个值的,则返回一个标量值

In [170]: obj['a']Out[170]: a 0a 1dtype: int32In [171]: obj['c']Out[171]: 4In [172]: df = DataFrame(np.random.randn(4, 3), index=['a', 'a', 'b', 'b'])In [173]: dfOut[173]: 0 1 2a -0.199619 -0.871154 -0.674903a 1.573516 0.558822 0.511055b 0.029318 -0.654353 -0.682175b -0.563794 1.756565 0.105016In [174]: df.ix['b']Out[174]: 0 1 2b 0.029318 -0.654353 -0.682175b -0.563794 1.756565 0.105016

通过练习认识到有些地方不能很好的理解,以后学习中慢慢理解各种函数的使用。

阅读全文
0 0