1. 程式人生 > >利用python進行資料分析-pandas入門3

利用python進行資料分析-pandas入門3

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