1.函数应用和映射
NumPy的ufuncs(元素级数组方法)也可用于操作pandas对象
frame=DataFrame(np.random.randn(4,3),columns=list('bde'),index=['Uath','Ohio','Texas','Oregon'])
print frame
print np.abs(frame)
结果为:
b d e
Uath 1.187068 1.589404 0.328555
Ohio -0.040634 1.489594 -0.453027
Texas 0.362667 0.601500 2.177313
Oregon 0.019020 -0.315751 -0.480646
b d e
Uath 1.187068 1.589404 0.328555
Ohio 0.040634 1.489594 0.453027
Texas 0.362667 0.601500 2.177313
Oregon 0.019020 0.315751 0.480646
另一个常见的操作是,将函数应用到由各列或行所形成的一维数组上。DataFrame的apply方法即可实现此功能
f=lambda x:x.max()-x.min()
print frame.apply(f)
print frame.apply(f,axis=1)
结果为:
b 0.605155
d 2.173279
e 2.737098
dtype: float64
Uath 1.913344
Ohio 0.302252
Texas 1.663901
Oregon 1.654397
dtype: float64
许多最为常见的数组统计功能都能被实现成DataFrame的方法(比如sum和mean),因此无需使用apply方法
除标量值外,传递给apply的函数还可以返回由多个值组成的Series
def f(x):
return Series([x.min(),x.max()],index=['min','max'])
print frame.apply(f)
结果为:
b d e
min -1.878553 -1.339043 -2.638153
max 1.051156 1.322494 0.242260
此外,元素级的Python函数也是可以用的。如你想得到frame中各个浮点值的格式化字符串,可以使用applymap
format=lambda x:'%.2f' % x
print frame.applymap(format)
结果为:
b d e
Uath 0.27 0.94 0.73
Ohio -0.81 0.78 -1.04
Texas 1.00 0.64 0.61
Oregon 0.55 -0.17 -0.40
之所以叫做applymap,是因为Series有一个用于应用元素级函数的map方法
print frame['e'].map(format)
结果为:
Uath 0.17
Ohio 2.22
Texas 0.58
Oregon 0.18
Name: e, dtype: object
2.排序和排名
要对行或列索引进行排序(按字典排序),可使用sort_index方法,它将返回一个已排序的新对象
obj=Series(range(4),index=['d','a','b','c'])
print obj.sort_index()
结果为:
a 1
b 2
c 3
d 0
dtype: int64
而对于DataFrame,可以根据任意一个轴上的索引进行排序
frame2=DataFrame(np.arange(8).reshape(2,4),index=['three','one'],columns=['d','a','b','c'])
print frame2.sort_index()
print frame2.sort_index(axis=1)
结果为:
d a b c
one 4 5 6 7
three 0 1 2 3
a b c d
three 1 2 3 0
one 5 6 7 4
数据默认是按照升序排序的,也可以降序排序
print frame2.sort_index(axis=1,ascending=False)
结果为:
d c b a
three 0 3 2 1
one 4 7 6 5
若要按值对Series进行排序,可使用其order方法
obj2=Series([4,7,-3,2])
print obj2.order()
结果为:
2 -3
3 2
0 4
1 7
在排序时,任何缺失值默认都会被放到Series末尾
obj3=Series([4,np.nan,7,np.nan,-3,2])
print obj3.order()
结果为:
4 -3
5 2
0 4
2 7
1 NaN
3 NaN
dtype: float64
在DataFrame上,你可能希望根据一个或多个列中的值进行排序。将一个或多个列的名字传递给by选项即可达到该目的
frame3=DataFrame({'b':[4,7,-3,2],'a':[0,1,0,1]})
print frame3
print frame3.sort_index(by='b')
结果为:
a b
0 0 4
1 1 7
2 0 -3
3 1 2
a b
2 0 -3
3 1 2
0 0 4
1 1 7
要根据多个列进行排序,传入名称的列表即可
print frame3.sort_index(by=['a','b'])
结果为:
a b
2 0 -3
0 0 4
3 1 2
1 1 7
排名(ranking)跟排序关系密切,且它会增设一个排名值(从1开始,一直到数组中有效数据的数量)。默认情况下,rank是通过“为各组分配一个平均排名”的方式破坏平级关系的
obj4=Series([7,-5,7,4,2,0,4])
print obj4.rank()
结果为:
0 6.5
1 1.0
2 6.5
3 4.5
4 3.0
5 2.0
6 4.5
也可以根据值在原数据中出现的顺序给出排名
print obj4.rank(method='first')
结果为:
0 6
1 1
2 7
3 4
4 3
5 2
6 5
dtype: float64
也可以按降序进行排名
print obj4.rank(method='max',ascending=False)
结果为:
0 2
1 7
2 2
3 4
4 5
5 6
6 4
dtype: float64
3.带有重复值的轴索引
索引的is_unique属性可以告诉你它的值是否是唯一的
obj5=Series(range(5),index=['a','a','b','b','c'])
print obj5
print obj5.index.is_unique
结果为:
a 0
a 1
b 2
b 3
c 4
dtype: int64
False
如果某个索引对应多个值,则返回一个Series
print obj5['a']
结果为:
a 0
a 1
dtype: int64
对DataFrame进行索引时也是如此
df=DataFrame(np.arange(12).reshape(4,3),index=['a','a','b','b'])
print df.ix['b']
结果为:
0 1 2
b 6 7 8
b 9 10 11
4.汇总和计算描述统计
df2=DataFrame([[1.4,np.nan],[7.1,-4.5],[np.nan,np.nan],[0.75,-1.3]],index=['a','b','c','d'],columns=['one','two'])
print df2
print df2.sum()
print df2.sum(axis=1)
结果为:
one two
a 1.40 NaN
b 7.10 -4.5
c NaN NaN
d 0.75 -1.3
one 9.25
two -5.80
dtype: float64
a 1.40
b 2.60
c 0.00
d -0.55
dtype: float64
NA值会自动被排除,除非整个切片(这里指的是行或列)都是NA。通过skipna选项可以禁用该功能
print df2.sum(axis=1,skipna=False)
结果为:
a NaN
b 2.60
c NaN
d -0.55
dtype: float64
有些方法(如idxmin和idxmax)返回的是间接统计(比如达到最小值或最大值的索引)
print df2.idxmax()
结果为:
one b
two d
dtype: object
另一些方法则是累计型的
print df2.cumsum()
结果为:
one two
a 1.40 NaN
b 8.50 -4.5
c NaN NaN
d 9.25 -5.8
还有一种方法,它既不是约简型也不是累计型。describe就是一个例子,它用于一次性产生多个汇总统计
print df2.describe()
结果为:
one two
count 3.000000 2.000000
mean 3.083333 -2.900000
std 3.493685 2.262742
min 0.750000 -4.500000
25% 1.075000 -3.700000
50% 1.400000 -2.900000
75% 4.250000 -2.100000
max 7.100000 -1.300000
5.相关系数与协方差
import pandas.io.data as web
all_data={}
for ticker in ['AAPL','IBM','MSFT','GOOG']:
all_data[ticker]=web.get_data_yahoo(ticker,'1/1/2000','1/1/2010')
price=DataFrame({tic:data['Adj Close']
for tic,data in all_data.iteritems()})
volume=DataFrame({tic:data['Volume']
for tic,data in all_data.iteritems()})
returns=price.pct_change()
print returns.tail()
结果为:
AAPL GOOG IBM MSFT
Date
2009-12-24 0.034339 0.011117 0.004385 0.002587
2009-12-28 0.012294 0.007098 0.013326 0.005484
2009-12-29 -0.011861 -0.005571 -0.003477 0.007058
2009-12-30 0.012147 0.005376 0.005461 -0.013699
2009-12-31 -0.004300 -0.004416 -0.012597 -0.015504
Series的corr方法用于计算两个Series中重叠、非NA的、按索引对齐的值的相关系数。与此类似,cov用于计算协方差
print returns.MSFT.corr(returns.IBM)
print returns.MSFT.cov(returns.IBM)
结果为:
0.495979684549
0.000215957648434
DataFrame的corr和cov方法将以DataFrame的形式返回完整的相关系数与协方差矩阵
print returns.corr()
print returns.cov()
结果为:
AAPL GOOG IBM MSFT
AAPL 1.000000 0.470676 0.410011 0.424305
GOOG 0.470676 1.000000 0.390689 0.443587
IBM 0.410011 0.390689 1.000000 0.495980
MSFT 0.424305 0.443587 0.495980 1.000000
AAPL GOOG IBM MSFT
AAPL 0.001027 0.000303 0.000252 0.000309
GOOG 0.000303 0.000580 0.000142 0.000205
IBM 0.000252 0.000142 0.000367 0.000216
MSFT 0.000309 0.000205 0.000216 0.000516
利用DataFrame的corrwith方法,你可以计算其列或行跟另一个Series或DataFrame之间的相关系数。传入一个Series将会返回一个相关系数值Series(针对各列进行计算)
print returns.corrwith(returns.IBM)
结果为:
AAPL 0.410011
GOOG 0.390689
IBM 1.000000
MSFT 0.495980
dtype: float64
传入一个DataFrame则会计算按列名配对的相关系数。这里,计算百分比变化与成交量的相关系数
print returns.corrwith(volume)
结果为:
AAPL -0.057549
GOOG 0.062647
IBM -0.007892
MSFT -0.014245
dtype: float64
传入axis=1即可按行进行计算。无论如何,在计算相关系数之前,所有的数据项都会按标签对齐
6.唯一值、值计数以及成员资格
obj6=Series(['c','a','d','a','a','b','b','c','c'])
uniques=obj6.unique()
print uniques
结果为:
['c' 'a' 'd' 'b']
返回的唯一值是未排序的,可以对结果再次进行排序(uniques.sort())。value_counts计算一个Series中各值出现的频率
print obj6.value_counts()
结果为:
c 3
a 3
b 2
d 1
dtype: int64
value_counts还有一个顶级pandas方法,可用于任何数组或序列
print pd.value_counts(obj6.values,sort=False)
结果为:
a 3
c 3
b 2
d 1
dtype: int64
isin,它用于判断矢量化集合的成员资格,可用于选取Series中或DataFrame列中数据的子集
mask=obj6.isin(['b','c'])
print mask
print obj6[mask]
结果为:
0 True
1 False
2 False
3 False
4 False
5 True
6 True
7 True
8 True
dtype: bool
0 c
5 b
6 b
7 c
8 c
dtype: object
有时,你希望得到DataFrame中多个相关列的一张柱状图
data2=DataFrame({'Qu1':[1,3,4,3,4],
'Qu2':[2,3,1,2,3],
'Qu3':[1,5,2,4,4]})
print data2
result=data2.apply(pd.value_counts).fillna(0)
print result
结果为:
Qu1 Qu2 Qu3
0 1 2 1
1 3 3 5
2 4 1 2
3 3 2 4
4 4 3 4
Qu1 Qu2 Qu3
1 1 1 1
2 0 2 1
3 2 2 0
4 2 0 2
5 0 0 1
7.处理丢失数据
pandas使用浮点值NAN表示浮点和非浮点数组中的缺失数据,它只是一个便于被检测出来的标记而已
string_data=Series(['aardvark','artichoke',np.nan,'avocado'])
print string_data
print string_data.isnull()
结果为:
0 aardvark
1 artichoke
2 NaN
3 avocado
dtype: object
0 False
1 False
2 True
3 False
dtype: bool
python内置的None值也会被当做NA处理
string_data[0]=None
print string_data.isnull()
结果为:
0 True
1 False
2 True
3 False
dtype: bool
8.滤除缺失数据
对于一个Series,dropna返回一个仅含非空数据和索引值的Series
from numpy import nan as NA
data=Series([1,NA,3.5,NA,7])
print data.dropna()
print data[data.notnull()]
结果为:
0 1.0
2 3.5
4 7.0
dtype: float64
0 1.0
2 3.5
4 7.0
dtype: float64
对于DataFrame对象,事情就有点复杂了。你可能希望丢弃全NA或含有NA的行或列。dropna默认丢弃任何含有缺失值的行
data3=DataFrame([[1,6.5,3],[1,NA,NA],[NA,NA,NA],[NA,6.5,3]])
print data3
cleaned=data3.dropna()
print cleaned
结果为:
0 1 2
0 1 6.5 3
1 1 NaN NaN
2 NaN NaN NaN
3 NaN 6.5 3
0 1 2
0 1 6.5 3
传入how='all'将只丢弃全为NA的那些行
print data3.dropna(how='all')
结果为:
0 1 2
0 1 6.5 3
1 1 NaN NaN
3 NaN 6.5 3
要用这种方式丢弃列,只需传入axis=1即可
data3[4]=NA
print data3
print data3.dropna(axis=1,how='all')
结果为:
0 1 2 4
0 1 6.5 3 NaN
1 1 NaN NaN NaN
2 NaN NaN NaN NaN
3 NaN 6.5 3 NaN
0 1 2
0 1 6.5 3
1 1 NaN NaN
2 NaN NaN NaN
3 NaN 6.5 3
另一个滤除DataFrame行的问题涉及到时间序列数据。假设你只想留下一部分观测数据,可以用thresh参数实现此目的
df3=DataFrame(np.random.randn(7,3))
df3.ix[:4,1]=NA
df3.ix[:2,2]=NA
print df3
print df3.dropna(thresh=3)
结果为:
0 1 2
0 2.399544 NaN NaN
1 0.430949 NaN NaN
2 -1.083213 NaN NaN
3 -0.431232 NaN 0.756593
4 0.529114 NaN -0.595716
5 1.444382 -0.195083 -0.930979
6 -1.412920 -0.934195 2.861213
0 1 2
5 1.444382 -0.195083 -0.930979
6 -1.412920 -0.934195 2.861213
9.填充缺失数据
fillna方法是最主要的函数
print df3.fillna(0)
print df3.fillna({1:0.5,3:-1})
结果为:
0 1 2
0 -0.034171 0.000000 0.000000
1 -0.115502 0.000000 0.000000
2 0.308157 0.000000 0.000000
3 1.367718 0.000000 -0.306751
4 -1.360234 0.000000 0.999463
5 -0.148457 0.156416 -2.017497
6 -0.408602 0.403680 -1.352914
0 1 2
0 -0.034171 0.500000 NaN
1 -0.115502 0.500000 NaN
2 0.308157 0.500000 NaN
3 1.367718 0.500000 -0.306751
4 -1.360234 0.500000 0.999463
5 -0.148457 0.156416 -2.017497
6 -0.408602 0.403680 -1.352914
fillna默认会返回新对象,但也可以对现有对象进行就地修改
_=df3.fillna(0,inplace=True)
print df3
结果为:
0 1 2
0 -1.901323 0.000000 0.000000
1 -0.431574 0.000000 0.000000
2 1.452733 0.000000 0.000000
3 0.013765 0.000000 0.572696
4 0.121601 0.000000 -0.972343
5 0.411238 -0.023716 0.827292
6 0.266131 0.706082 0.859971
对reindex有效的那些插值方法也可用于fillna
df4=DataFrame(np.random.randn(6,3))
df4.ix[2:,1]=NA
df4.ix[4:,2]=NA
print df4
print df4.fillna(method='ffill')
print df4.fillna(method='ffill',limit=2)
结果为:
0 1 2
0 0.132548 0.581560 0.539203
1 0.250056 0.676504 -0.645744
2 0.760809 NaN 1.073846
3 -0.480362 NaN 0.221771
4 -0.600295 NaN NaN
5 0.005458 NaN NaN
0 1 2
0 0.132548 0.581560 0.539203
1 0.250056 0.676504 -0.645744
2 0.760809 0.676504 1.073846
3 -0.480362 0.676504 0.221771
4 -0.600295 0.676504 0.221771
5 0.005458 0.676504 0.221771
0 1 2
0 0.132548 0.581560 0.539203
1 0.250056 0.676504 -0.645744
2 0.760809 0.676504 1.073846
3 -0.480362 0.676504 0.221771
4 -0.600295 NaN 0.221771
5 0.005458 NaN 0.221771
10.层次化索引
它使你能以低纬度形式处理高纬度数据
data4=Series(np.random.randn(10),index=[['a','a','a','b','b','b','c','c','d','d'],
[1,2,3,1,2,3,1,2,2,3]])
print data4
结果为:
a 1 -0.219090
2 -1.372102
3 1.108223
b 1 -0.796361
2 1.175877
3 0.520666
c 1 1.058822
2 1.325842
d 2 -0.040458
3 0.205163
dtype: float64
这就是带有MultiIndex索引的Series的格式化输出形式。索引之间的“间隔”表示“直接使用上面的标签”
print data4.index
结果为:
MultiIndex(levels=[[u'a', u'b', u'c', u'd'], [1, 2, 3]],
labels=[[0, 0, 0, 1, 1, 1, 2, 2, 3, 3], [0, 1, 2, 0, 1, 2, 0, 1, 1, 2]])
对于一个层次化索引的对象,选取数据子集的操作很简单
print data4['b']
结果为:
1 -0.094394
2 0.531658
3 -0.159814
dtype: float64
print data4['b':'c']
print data4.ix[['b','d']]
结果为:
b 1 -1.336168
2 0.074839
3 -0.615861
c 1 -0.349232
2 -0.024671
dtype: float64
b 1 -1.336168
2 0.074839
3 -0.615861
d 2 1.444744
3 -0.824043
dtype: float64
可以通过其unstack方法被重新安排到一个DataFrame中
print data4.unstack()
结果为:
1 2 3
a 1.483774 0.221626 0.085326
b 0.354429 -1.018716 0.423129
c -1.038540 2.103571 NaN
d NaN 0.596784 1.500782
unstack的逆运算是stack
print data4.unstack().stack()
结果为:
a 1 -0.718105
2 0.766081
3 -0.221549
b 1 -0.521521
2 -1.252716
3 -0.329751
c 1 1.912822
2 -0.794359
d 2 1.432758
3 1.244745
dtype: float64
对于一个DataFrame,每条轴上都可以有分层索引
frame4=DataFrame(np.arange(12).reshape((4,3)),
index=[['a','a','b','b'],[1,2,1,2]],
columns=[['Ohio','Ohio','Colorado'],
['Green','Red','Green']])
print frame4
frame4.index.names=['key1','key2']
frame4.columns.names=['state','color']
print frame4
结果为:
Ohio Colorado
Green Red Green
a 1 0 1 2
2 3 4 5
b 1 6 7 8
2 9 10 11
state Ohio Colorado
color Green Red Green
key1 key2
a 1 0 1 2
2 3 4 5
b 1 6 7 8
2 9 10 11
11.重排分级排序
swaplevel接受两个级别编号或名称,并返回一个互换了级别的新对象(但数据不会发生变化)
print frame4.swaplevel('key1','key2')
结果为:
state Ohio Colorado
color Green Red Green
key2 key1
1 a 0 1 2
2 a 3 4 5
1 b 6 7 8
2 b 9 10 11
而sortlevel则根据单个级别中的值对数据进行排序。交换级别时,常常也会用到sortlevel,这样最终结果就是有序的了
print frame4.sortlevel(1)
print frame4.swaplevel(0,1).sortlevel(0)
结果为:
state Ohio Colorado
color Green Red Green
key1 key2
a 1 0 1 2
b 1 6 7 8
a 2 3 4 5
b 2 9 10 11
state Ohio Colorado
color Green Red Green
key2 key1
1 a 0 1 2
b 6 7 8
2 a 3 4 5
b 9 10 11
12.根据级别汇总统计
print frame4.sum(level='key2')
print frame4.sum(level='color',axis=1)
结果为:
state Ohio Colorado
color Green Red Green
key2
1 6 8 10
2 12 14 16
color Green Red
key1 key2
a 1 2 1
2 8 4
b 1 14 7
2 20 10
13.使用DataFrame的列
frame5=DataFrame({'a':range(7),'b':range(7,0,-1),
'c':['one','one','one','two','two','two','two'],
'd':[0,1,2,0,1,2,3]})
print frame5
结果为:
a b c d
0 0 7 one 0
1 1 6 one 1
2 2 5 one 2
3 3 4 two 0
4 4 3 two 1
5 5 2 two 2
6 6 1 two 3
DataFrame的set_index函数会将其一个或多个列转换为行索引,并创建一个新的DataFrame
frame5=DataFrame({'a':range(7),'b':range(7,0,-1),
'c':['one','one','one','two','two','two','two'],
'd':[0,1,2,0,1,2,3]})
print frame5
frame6=frame5.set_index(['c','d'])
print frame6
结果为:
a b c d
0 0 7 one 0
1 1 6 one 1
2 2 5 one 2
3 3 4 two 0
4 4 3 two 1
5 5 2 two 2
6 6 1 two 3
a b
c d
one 0 0 7
1 1 6
2 2 5
two 0 3 4
1 4 3
2 5 2
3 6 1
默认情况下,那些列会从DataFrame中移除,但也可以将其保留下来
print frame5.set_index(['c','d'],drop=False)
结果为:
a b c d
c d
one 0 0 7 one 0
1 1 6 one 1
2 2 5 one 2
two 0 3 4 two 0
1 4 3 two 1
2 5 2 two 2
3 6 1 two 3
reset_index的功能跟set_index刚好相反,层次化索引的级别会被转移到列里面
print frame6.reset_index()
结果为:
c d a b
0 one 0 0 7
1 one 1 1 6
2 one 2 2 5
3 two 0 3 4
4 two 1 4 3
5 two 2 5 2
6 two 3 6 1