1. 程式人生 > >Pandas快速教程-必要的基本功能

Pandas快速教程-必要的基本功能

一.資料的快速檢視head和tail

這兩個方法可以快速的檢視一組資料的小抽樣,預設的設定是5行,當然也可以設定要返回的數目.

t=df.head(2)

t
Out[134]: 
   First  Secend Third
0    2.0     1.0     1
1    4.0     2.0     2

df.tail(3)
Out[135]: 
   First  Secend Third
1    4.0     2.0     2
2    NaN     3.0     a
3    8.0     NaN     b

二.二元操作

在pandas結構化資料的二元化操作中,有兩點是需要特別注意的:

1.從高緯資料向低維資料的廣播(broadcasting )

2.缺失值(Missing Value)的計算中的處理

DataFrame的add(),sub()等等二元函式方法實現了二元化的操作.對於DataFrame結構的資料的廣播方式來說,與Series物件進行計算的廣播是最常見的.在二元函式中,可以使用axis引數來控制廣播方向.

df
Out[7]: 
   one  two  three
a  2.0    9    NaN
b  6.0    5    1.0
c  5.0    8    6.0
d  NaN    6    1.0

row=df.loc['b']
col=df['two']

df.sub(row,axis='columns')
Out[20]: 
   one  two  three
a -4.0  4.0    NaN
b  0.0  0.0    0.0
c -1.0  3.0    5.0
d  NaN  1.0    0.0

df.sub(row,axis=1)
Out[21]: 
   one  two  three
a -4.0  4.0    NaN
b  0.0  0.0    0.0
c -1.0  3.0    5.0
d  NaN  1.0    0.0

df.add(col,axis='index')
Out[22]: 
    one   two  three
a  11.0  18.0    NaN
b  11.0  10.0    6.0
c  13.0  16.0   14.0
d   NaN  12.0    7.0

df.add(col,axis=0)
Out[23]: 
    one   two  three
a  11.0  18.0    NaN
b  11.0  10.0    6.0
c  13.0  16.0   14.0
d   NaN  12.0    7.0

對於多級索引的資料來說,可以增加一個level引數以控制層級

df_mul=df.copy()

df_mul.index=pd.MultiIndex.from_tuples([(1,'a'),(1,'b'),(1,'c'),(2,'a')], names=['first','second'])

df_mul
Out[26]: 
              one  two  three
first second                 
1     a       2.0    9    NaN
      b       6.0    5    1.0
      c       5.0    8    6.0
2     a       NaN    6    1.0

df_mul.sub(col, axis=0, level='second')
Out[29]: 
              one  two  three
first second                 
1     a      -7.0  0.0    NaN
      b       1.0  0.0   -4.0
      c      -3.0  0.0   -2.0
2     a       NaN -3.0   -8.0

對於缺失值在計算中的處理,fill_value引數可以為missing value指定替換值.

值得注意的是,只有在兩個相同shape的資料進行二元操作且相對應位置的元素不同時為缺失值時,fill_value引數才能使用

在存在廣播行為的計算中中,fill_value是無法使用的

df
Out[51]: 
   one  two  three
a  2.0    9    NaN
b  6.0    5    1.0
c  5.0    8    6.0
d  NaN    6    1.0

df1
Out[49]: 
   one  two  three
a  2.0    9    9.0
b  6.0    5    1.0
c  5.0    8    6.0
d  9.0    6    1.0

df.sub(df1,fill_value=0)
Out[50]: 
   one  two  three
a  0.0    0   -9.0
b  0.0    0    0.0
c  0.0    0    0.0
d -9.0    0    0.0

靈活的比較操作

pandas中提供了eq,ne,lt,gt,le,ge 比較方法,操作方式與上面介紹的基本一致,只是,這些方法返回的都是與比較資料同shape的boolean型別的資料.

在比較重,NaN與任何值(包括標量和NaN)進行大小比較都是返回False,只有進行等於或不等於比較時才能根據實際情況返回(此情況需注意一點,np.nan 與 np.nan 相比永遠是返回False)

df
Out[77]: 
    one  two  three
a   2.0    9   10.0
b   6.0    5    1.0
c   5.0    8    6.0
d  10.0    6    1.0

df1
Out[78]: 
   one  two  three
a  2.0    9    9.0
b  6.0    5    1.0
c  5.0    8    6.0
d  9.0    6    1.0

df2
Out[79]: 
   one  two  three
a  2.0    9    NaN
b  6.0    5    1.0
c  5.0    8    6.0
d  9.0    6    1.0

df.gt(df1)
Out[80]: 
     one    two  three
a  False  False   True
b  False  False  False
c  False  False  False
d   True  False  False

df1.gt(df2)
Out[81]: 
     one    two  three
a  False  False  False
b  False  False  False
c  False  False  False
d  False  False  False

df.eq(df2)
Out[82]: 
     one   two  three
a   True  True  False
b   True  True   True
c   True  True   True
d  False  True   True

boolean值的推斷概要可以從emptyany()all(), and bool() 這幾個函式獲得.同樣可以控制軸方向

(df>5).any(0)
Out[88]: 
one      True
two      True
three    True
dtype: bool

(df>1).all(1)
Out[89]: 
a     True
b    False
c     True
d    False
dtype: bool

上面的比較返回的是一組比較結果boolean值構成的資料集,要單獨比較兩個資料集是否相等(或者說一致),是需要另外一個方法的.

在pandas中,np.nan是不等於np.nan的

 np.nan == np.nan
Out[91]: False

要比較兩個資料集是否一致,可以使用equals方法:

df.eq(df)
Out[93]: 
    one   two  three
a  True  True   True
b  True  True   True
c  True  True   True
d  True  True   True

df.equals(df)
Out[94]: True

(df+df).equals(df*2)

list-like物件的比較分為兩種

與標量比較是使用element-wise形式的,既自動廣播到所有元素

與list-like物件比較時,要求兩個比較的物件長度必須一致

pd.Series(['foo', 'bar', 'baz']) == 'foo'
Out[96]: 
0     True
1    False
2    False
dtype: bool

pd.Series(['foo', 'bar', 'baz']) == np.array(['foo', 'bar', 'qux'])
Out[97]: 
0     True
1     True
2    False
dtype: bool

pd.Series(['foo', 'bar', 'baz']) == pd.Series(['foo', 'bar'])
Traceback (most recent call last):

  File "<ipython-input-98-93a189c0880c>", line 1, in <module>
    pd.Series(['foo', 'bar', 'baz']) == pd.Series(['foo', 'bar'])

  File "D:\Anaconda\lib\site-packages\pandas\core\ops.py", line 1190, in wrapper
    raise ValueError("Can only compare identically-labeled "

ValueError: Can only compare identically-labeled Series objects

合併重疊資料

當兩個相似資料集進行重疊合並時,我們是希望將一個數據中的未知的缺失值替換為另一個數據中的已知的值.

這時可以使用combine_first方法

 df
Out[135]: 
    one  two  three
a   2.0    9   10.0
b   6.0  100    1.0
c   5.0    8  100.0
d  10.0    6    1.0

df1
Out[136]: 
   one  two  three
a  2.0    9    NaN
b  6.0    5    NaN
c  5.0    8    NaN
d  NaN    6    1.0

df1.combine_first(df)
Out[137]: 
    one  two  three
a   2.0    9   10.0
b   6.0    5    1.0
c   5.0    8  100.0
d  10.0    6    1.0

實質上,combine_first方法是呼叫的DataFrame的combine方法

該方法接收一個與要合併資料相同shape的Datafram和一個合併函式

combiner = lambda x, y: np.where(pd.isna(x), y, x)

df1.combine(df,combiner)
Out[139]: 
    one  two  three
a   2.0    9   10.0
b   6.0    5    1.0
c   5.0    8  100.0
d  10.0    6    1.0

三.描述性統計

pandas中提供許多的描述性統計需要的方法,有些返回聚合資料後的結構,如sum,mean等,有些返回一個和原資料相同shape的資料集,如:cumsum,cumprod等.同樣計算的方向可以由asix引數指定.

df.sum(1)
Out[141]: 
a     21.0
b    107.0
c    113.0
d     17.0
dtype: float64

df.mean(0)
Out[142]: 
one       5.75
two      30.75
three    28.00
dtype: float64

如果有缺失值,可以通過skipna引數指定是否忽略

df2.mean()
Out[144]: 
one      5.500000
two      7.000000
three    2.666667
dtype: float64

df2.mean(skipna=False)
Out[145]: 
one      5.5
two      7.0
three    NaN
dtype: float64

使用describe方法可以快速資料統計的概要

df.describe()
Out[147]: 
             one         two       three
count   4.000000    4.000000    4.000000
mean    5.750000   30.750000   28.000000
std     3.304038   46.183511   48.187135
min     2.000000    6.000000    1.000000
25%     4.250000    7.500000    1.000000
50%     5.500000    8.500000    5.500000
75%     7.000000   31.750000   32.500000
max    10.000000  100.000000  100.000000

同時可以通過percentiles引數指定分位數

df.describe(percentiles=[.1,.7,.9])
Out[149]: 
             one         two       three
count   4.000000    4.000000    4.000000
mean    5.750000   30.750000   28.000000
std     3.304038   46.183511   48.187135
min     2.000000    6.000000    1.000000
10%     2.900000    6.600000    1.000000
50%     5.500000    8.500000    5.500000
70%     6.400000   18.100000   19.000000
90%     8.800000   72.700000   73.000000
max    10.000000  100.000000  100.000000

對應非數字型別的資料集,dexcribe返回的是對非數字元素的頻率統計,對應混合型資料集,dexcribe預設會提取其中的數字型別資料進行統計並只返回該結果

s = pd.Series(['a', 'a', 'b', 'b', 'a', 'a', np.nan, 'c', 'd', 'a'])

s.describe()
Out[154]: 
count     9
unique    4
top       a
freq      5
dtype: object

frame = pd.DataFrame({'a': ['Yes', 'Yes', 'No', 'No'], 'b': range(4)})

frame.describe()
Out[156]: 
              b
count  4.000000
mean   1.500000
std    1.290994
min    0.000000
25%    0.750000
50%    1.500000
75%    2.250000
max    3.000000

當然,對於混合型資料集的統計方式也是可以通過include引數指定的

frame.describe(include=['object'])
Out[104]: 
          a
count     4
unique    2
top     Yes
freq      2

In [105]: frame.describe(include=['number'])
Out[105]: 
              b
count  4.000000
mean   1.500000
std    1.290994
min    0.000000
25%    0.750000
50%    1.500000
75%    2.250000
max    3.000000

In [106]: frame.describe(include='all')
Out[106]: 
          a         b
count     4  4.000000
unique    2       NaN
top     Yes       NaN
freq      2       NaN
mean    NaN  1.500000
std     NaN  1.290994
min     NaN  0.000000
25%     NaN  0.750000
50%     NaN  1.500000
75%     NaN  2.250000
max     NaN  3.000000

使用idxmax/idxmin查詢最大/最小值的索引值(Index):

s1 = pd.Series(np.random.randint(1,10,5))

s1
Out[172]: 
0    9
1    1
2    3
3    1
4    4
dtype: int32

s1.idxmax()
Out[173]: 0

s1.idxmin()
Out[174]: 1

對於DataFrame來說同樣適用,適用axsi指定計算方向

df
Out[175]: 
    one  two  three
a   2.0    9   10.0
b   6.0  100    1.0
c   5.0    8  100.0
d  10.0    6    1.0

df.idxmax(0)
Out[176]: 
one      d
two      b
three    c
dtype: object

df.idxmax(1)
Out[177]: 
a    three
b      two
c    three
d      one
dtype: object

元素計數統計value_counts僅適用於Series物件(DataFrame不適用)

pd.Series(random.choices(list('adcd'),k=20)).value_counts()
Out[186]: 
d    9
a    6
c    5
dtype: int64

使用mode函式可以得到最高頻的元素(該方法適用DataFrame)

s = pd.Series([1, 1, 3, 3, 3, 3, 5, 7, 7, 7])

s.mode()
Out[189]: 
0    3
dtype: int64

df5 = pd.DataFrame({"A": np.random.randint(0, 7, size=50),
   .....:                     "B": np.random.randint(-10, 15, size=50)})
                    

df5.mode()
Out[193]: 
   A  B
0  2 -7

四.排序

支援三種方式的排序:

1.按照label排序(這個label'包含index和columns)

2.按照values排序(元素大小排序)

3.混合型(既按label又按照values)

第一種按照label排序的方式,label既可以是行的label(Index),也可以是列的label(columns),既可以升序也可以降序.

df = pd.DataFrame({'one' : pd.Series(np.random.randn(3), index=['a', 'b', 'c']),
   .....:                    'two' : pd.Series(np.random.randn(4), index=['a', 'b', 'c', 'd']),
   .....:                    'three' : pd.Series(np.random.randn(3), index=['b', 'c', 'd'])})
   .....: 

In [308]: unsorted_df = df.reindex(index=['a', 'd', 'c', 'b'],
   .....:                          columns=['three', 'two', 'one'])
   .....: 

In [309]: unsorted_df
Out[309]: 
      three       two       one
a       NaN  0.708543  0.036274
d -0.540166  0.586626       NaN
c  0.410238  1.121731  1.044630
b -0.282532 -2.038777 -0.490032

# DataFrame
In [310]: unsorted_df.sort_index()
Out[310]: 
      three       two       one
a       NaN  0.708543  0.036274
b -0.282532 -2.038777 -0.490032
c  0.410238  1.121731  1.044630
d -0.540166  0.586626       NaN

In [311]: unsorted_df.sort_index(ascending=False)
Out[311]: 
      three       two       one
d -0.540166  0.586626       NaN
c  0.410238  1.121731  1.044630
b -0.282532 -2.038777 -0.490032
a       NaN  0.708543  0.036274

In [312]: unsorted_df.sort_index(axis=1)
Out[312]: 
        one     three       two
a  0.036274       NaN  0.708543
d       NaN -0.540166  0.586626
c  1.044630  0.410238  1.121731
b -0.490032 -0.282532 -2.038777

# Series
In [313]: unsorted_df['three'].sort_index()
Out[313]: 
a         NaN
b   -0.282532
c    0.410238
d   -0.540166
Name: three, dtype: float64

第二種按values的順序來對整個資料集進行排序,如排序方向,升降序等引數基本與第一種方法類似

 df1 = pd.DataFrame({'one':[2,1,1,1],'two':[1,3,2,4],'three':[5,4,3,2]})

df1.sort_values(by='two',axis=0)
Out[213]: 
   one  two  three
0    2    1      5
2    1    2      3
1    1    3      4
3    1    4      2

df1.sort_values(by=1,axis=1)
Out[214]: 
   one  two  three
0    2    1      5
1    1    3      4
2    1    2      3
3    1    4      2

df1.iloc[1,1]=np.nan

df1.sort_values(by='two',ascending=False,na_position='first')
Out[216]: 
   one  two  three
1    1  NaN      4
3    1  4.0      2
2    1  2.0      3
0    2  1.0      5

第三種同時按照行列label排序,一般是用在多層級的資料集中,注意的是如果行label和列label同名的話,列標籤優先.

 idx = pd.MultiIndex.from_tuples([('a', 1), ('a', 2), ('a', 2),
   .....:                                 ('b', 2), ('b', 1), ('b', 1)])
   .....: 

In [321]: idx.names = ['first', 'second']

# Build DataFrame
In [322]: df_multi = pd.DataFrame({'A': np.arange(6, 0, -1)},
   .....:                         index=idx)
   .....: 

In [323]: df_multi
Out[323]: 
              A
first second   
a     1       6
      2       5
      2       4
b     2       3
      1       2
      1       1

df_multi.sort_values(by=['second', 'A'])
Out[324]: 
              A
first second   
b     1       1
      1       2
a     1       6
b     2       3
a     2       4
      2       5

最後介紹下去top值的問題,如果資料集很大的話,先對資料排序後再使用head或tail函式效率會非常低

這是可以使用nlargest或者nsmallest

s
Out[218]: 
0    3
1    6
2    5
3    1
4    4
5    8
6    2
7    0
8    7
9    9
dtype: int32

s.nlargest(3)
Out[219]: 
9    9
5    8
8    7
dtype: int32

s.nsmallest(3)
Out[220]: 
7    0
3    1
6    2
dtype: int32

df = pd.DataFrame({'a': [-2, -1, 1, 10, 8, 11, -1],'b': list('abdceff'),'c': [1.0, 2.0, 4.0, 3.2, np.nan, 3.0, 4.0]})


df.nlargest(3,'a')
Out[226]: 
    a  b    c
5  11  f  3.0
3  10  c  3.2
4   8  e  NaN

五.複製

pandas中的資料複製使用copy函式.

但大部分情況下,都不需要使用該函式.

這是因為pandas的資料的保護非常到位,也就是資料的不可觸碰原則(leaving the original object untouched)

只要不直接修改資料的自身屬性,其他的pandas提供的函式或者方法都不直接修改原資料,除非通過inplace引數指定

六.迭代

雖然pandas支援迴圈迭代,但從執行效率的角度並不建議,並且因為pandas的原資料不可觸碰性的原則,很多方法並不能對原資料集進行修改,而是返回新的物件或者檢視,所以有些迴圈迭代的修改資料並不一定能保證成功.

涉及到迴圈遍歷方面的操作,儘量採用向量化的操作方式或者使用函式應用的方式(函式應用方式後文會講)

首先,pandas中對不同型別資料的迴圈,得到的結果是不一樣的

對於Series物件,會像ndarray一樣得到的是每一個元素

s=pd.Series([1,2,3,'a','b'])

for i in s:
    print(i)
    
1
2
3
a
b

對於DataFrame物件的迭代,返回的是其columns

df
Out[235]: 
    a  b    c
0  -2  a  1.0
1  -1  b  2.0
2   1  d  4.0
3  10  c  3.2
4   8  e  NaN
5  11  f  3.0
6  -1  f  4.0

for i in df:
    print(i)
    
a
b
c

為了便於對對資料的迭代,pandas中也提供了幾個方法:

iteritems:類似字典似的介面,返回的是(key,value)對

iterows:將每一行作為一個Series物件進行迭代

itertuples:將每一行資料作為namedtuple的資料格式進行返回

鑑於pandas中迴圈迭代的少用性,在此就略了,如有需要可以查閱官網.

七.重新索引和修改標籤

pandas最重要的特性就是資料的自動對齊,而reindex函式就是一個可以資料對齊的方法.reindex方法可以實現以下三個方面:

1.根據舊資料去匹配新的資料

2.在匹配不到資料的的位置填充缺失值

3.可以指定填充缺失資料的邏輯方法

s = pd.Series(np.random.randn(5), index=['a', 'b', 'c', 'd', 'e'])

In [217]: s
Out[217]: 
a   -0.454087
b   -0.360309
c   -0.951631
d   -0.535459
e    0.835231
dtype: float64

In [218]: s.reindex(['e', 'b', 'f', 'd'])
Out[218]: 
e    0.835231
b   -0.360309
f         NaN
d   -0.535459
dtype: float64

對DataFrame資料,可以同時重新索引行標籤和列標籤

df
Out[219]: 
        one       two     three
a -1.101558  1.124472       NaN
b -0.177289  2.487104 -0.634293
c  0.462215 -0.486066  1.931194
d       NaN -0.456288 -1.222918

In [220]: df.reindex(index=['c', 'f', 'b'], columns=['three', 'two', 'one'])
Out[220]: 
      three       two       one
c  1.931194 -0.486066  0.462215
f       NaN       NaN       NaN
b -0.634293  2.487104 -0.177289

df.reindex(['c', 'f', 'b'], axis='index')
Out[221]: 
        one       two     three
c  0.462215 -0.486066  1.931194
f       NaN       NaN       NaN
b -0.177289  2.487104 -0.634293

Index或者columns物件是可以在資料集之間進行傳遞的

 rs = s.reindex(df.index)

In [223]: rs
Out[223]: 
a   -0.454087
b   -0.360309
c   -0.951631
d   -0.535459
dtype: float64

In [224]: rs.index is df.index
Out[224]: True

通過reindex_like方法,可以讓一個數據集根據另外一個數據集的index和columns來重新索引自身的index和columns

df2
Out[227]: 
        one       two
a -1.101558  1.124472
b -0.177289  2.487104
c  0.462215 -0.486066

In [228]: df3
Out[228]: 
        one       two
a -0.829347  0.082635
b  0.094922  1.445267
c  0.734426 -1.527903

In [229]: df.reindex_like(df2)
Out[229]: 
        one       two
a -1.101558  1.124472
b -0.177289  2.487104
c  0.462215 -0.486066

對於reindex過程中產生的缺失值同樣可以設定填充方式和填充數量限制

rng = pd.date_range('1/3/2000', periods=8)

In [240]: ts = pd.Series(np.random.randn(8), index=rng)

In [241]: ts2 = ts[[0, 3, 6]]

In [242]: ts
Out[242]: 
2000-01-03    0.466284
2000-01-04   -0.457411
2000-01-05   -0.364060
2000-01-06    0.785367
2000-01-07   -1.463093
2000-01-08    1.187315
2000-01-09   -0.493153
2000-01-10   -1.323445
Freq: D, dtype: float64

In [243]: ts2
Out[243]: 
2000-01-03    0.466284
2000-01-06    0.785367
2000-01-09   -0.493153
dtype: float64

In [244]: ts2.reindex(ts.index)
Out[244]: 
2000-01-03    0.466284
2000-01-04         NaN
2000-01-05         NaN
2000-01-06    0.785367
2000-01-07         NaN
2000-01-08         NaN
2000-01-09   -0.493153
2000-01-10         NaN
Freq: D, dtype: float64

In [245]: ts2.reindex(ts.index, method='ffill')
Out[245]: 
2000-01-03    0.466284
2000-01-04    0.466284
2000-01-05    0.466284
2000-01-06    0.785367
2000-01-07    0.785367
2000-01-08    0.785367
2000-01-09   -0.493153
2000-01-10   -0.493153
Freq: D, dtype: float64

In [246]: ts2.reindex(ts.index, method='bfill')
Out[246]: 
2000-01-03    0.466284
2000-01-04    0.785367
2000-01-05    0.785367
2000-01-06    0.785367
2000-01-07   -0.493153
2000-01-08   -0.493153
2000-01-09   -0.493153
2000-01-10         NaN
Freq: D, dtype: float64

In [247]: ts2.reindex(ts.index, method='nearest')
Out[247]: 
2000-01-03    0.466284
2000-01-04    0.466284
2000-01-05    0.785367
2000-01-06    0.785367
2000-01-07    0.785367
2000-01-08   -0.493153
2000-01-09   -0.493153
2000-01-10   -0.493153
Freq: D, dtype: float64

ts2.reindex(ts.index, method='ffill', limit=1)
Out[249]: 
2000-01-03    0.466284
2000-01-04    0.466284
2000-01-05         NaN
2000-01-06    0.785367
2000-01-07    0.785367
2000-01-08         NaN
2000-01-09   -0.493153
2000-01-10   -0.493153
Freq: D, dtype: float64

從資料集中刪除指定行標籤或者列標籤,使用drop函式即可

df
Out[251]: 
        one       two     three
a -1.101558  1.124472       NaN
b -0.177289  2.487104 -0.634293
c  0.462215 -0.486066  1.931194
d       NaN -0.456288 -1.222918

In [252]: df.drop(['a', 'd'], axis=0)
Out[252]: 
        one       two     three
b -0.177289  2.487104 -0.634293
c  0.462215 -0.486066  1.931194

In [253]: df.drop(['one'], axis=1)
Out[253]: 
        two     three
a  1.124472       NaN
b  2.487104 -0.634293
c -0.486066  1.931194
d -0.456288 -1.222918

重新命名行/列標籤的名稱,使用rename函式

df.rename(columns={'one': 'foo', 'two': 'bar'},
   .....:           index={'a': 'apple', 'b': 'banana', 'd': 'durian'})
   .....: 
Out[257]: 
             foo       bar     three
apple  -1.101558  1.124472       NaN
banana -0.177289  2.487104 -0.634293
c       0.462215 -0.486066  1.931194
durian       NaN -0.456288 -1.222918

df.rename({'one': 'foo', 'two': 'bar'}, axis='columns')
Out[258]: 
        foo       bar     three
a -1.101558  1.124472       NaN
b -0.177289  2.487104 -0.634293
c  0.462215 -0.486066  1.931194
d       NaN -0.456288 -1.222918

In [259]: df.rename({'a': 'apple', 'b': 'banana', 'd': 'durian'}, axis='index')
Out[259]: 
             one       two     three
apple  -1.101558  1.124472       NaN
banana -0.177289  2.487104 -0.634293
c       0.462215 -0.486066  1.931194
durian       NaN -0.456288 -1.222918

八.函式應用

pandas提供了不同的方法可以對每個物件進行函式操作,而每個方法有不同的作用範圍:

1.pipe:表格級範圍

2.apply:行列級範圍

3.agg/transform:聚合的API介面(行列級範圍)

4.applyamp:元素級範圍

首先從表格級範圍的pipe說起.DtatFrame或者Series當然也可以作為引數傳遞給其他的函式,如果函式鏈式執行的話,那麼可以簡單為以下模式:

# f, g, and h are functions taking and returning ``DataFrames``
>>> f(g(h(df), arg1=1), arg2=2, arg3=3)

使用pipe的話,可以表述為如下模式:

(df.pipe(h)
       .pipe(g, arg1=1)
       .pipe(f, arg2=2, arg3=3)
    )

行列級範圍函式

apply/agg(aggregate的別名)/transform三個方法都可以實現行/列範圍的函式運算.

DataFrame.apply(funcaxis=0raw=False,result_type=Noneargs=()**kwds)

DataFrame.agg(funcaxis=0*args**kwargs)

DataFrame.transform(func*args**kwargs).該方法不接受聚合型別的函式,如mean,sum.

 df = pd.DataFrame(np.random.randint(1, 10,30).reshape(10,3), columns=['A', 'B', 'C'],index=pd.date_range('1/1/2000', periods=10))

以上三個方法中.func可以接受四種類型:

a.部分描述性統計方法的字元形式

df.apply('mean')
Out[20]: 
A    4.3
B    6.6
C    5.0
dtype: float64

df.agg('mean')
Out[21]: 
A    4.3
B    6.6
C    5.0
dtype: float64

df.transform('abs')
Out[26]: 
            A  B  C
2000-01-01  4  8  2
2000-01-02  7  1  5
2000-01-03  4  9  9
2000-01-04  7  5  8
2000-01-05  1  9  6
2000-01-06  6  2  3
2000-01-07  4  8  2
2000-01-08  2  8  7
2000-01-09  4  8  1
2000-01-10  4  8  7

b.函式名,包含自定義的

def add1(item):
    return item+1


df.apply(func=add1)
Out[28]: 
            A   B   C
2000-01-01  5   9   3
2000-01-02  8   2   6
2000-01-03  5  10  10
2000-01-04  8   6   9
2000-01-05  2  10   7
2000-01-06  7   3   4
2000-01-07  5   9   3
2000-01-08  3   9   8
2000-01-09  5   9   2
2000-01-10  5   9   8

df.agg(func=add1)
Out[29]: 
            A   B   C
2000-01-01  5   9   3
2000-01-02  8   2   6
2000-01-03  5  10  10
2000-01-04  8   6   9
2000-01-05  2  10   7
2000-01-06  7   3   4
2000-01-07  5   9   3
2000-01-08  3   9   8
2000-01-09  5   9   2
2000-01-10  5   9   8

df.transform(func=add1)
Out[30]: 
            A   B   C
2000-01-01  5   9   3
2000-01-02  8   2   6
2000-01-03  5  10  10
2000-01-04  8   6   9
2000-01-05  2  10   7
2000-01-06  7   3   4
2000-01-07  5   9   3
2000-01-08  3   9   8
2000-01-09  5   9   2
2000-01-10  5   9   8

c.函式組成的列表

df.apply(['sum','min','max'])
Out[31]: 
      A   B   C
sum  43  66  50
min   1   1   1
max   7   9   9

df.agg(['sum','min','max'])
Out[32]: 
      A   B   C
sum  43  66  50
min   1   1   1
max   7   9   9

df.transform([abs,add1])
Out[33]: 
             A        B        C     
           abs add1 abs add1 abs add1
2000-01-01   4    5   8    9   2    3
2000-01-02   7    8   1    2   5    6
2000-01-03   4    5   9   10   9   10
2000-01-04   7    8   5    6   8    9
2000-01-05   1    2   9   10   6    7
2000-01-06   6    7   2    3   3    4
2000-01-07   4    5   8    9   2    3
2000-01-08   2    3   8    9   7    8
2000-01-09   4    5   8    9   1    2
2000-01-10   4    5   8    9   7    8

d.可以用字典方式指定列名和對應要執行的函式

 df.apply({'A':sum,'B':max,'C':min})
Out[34]: 
A    43
B     9
C     1
dtype: int64

df.agg({'A':sum,'B':max,'C':min})
Out[35]: 
A    43
B     9
C     1
dtype: int64

df.transform({'A':abs,'C':add1})
Out[36]: 
            A   C
2000-01-01  4   3
2000-01-02  7   6
2000-01-03  4  10
2000-01-04  7   9
2000-01-05  1   7
2000-01-06  6   4
2000-01-07  4   3
2000-01-08  2   8
2000-01-09  4   2
2000-01-10  4   8

至於apply方法中,其他引數可以查閱官網:

同時三個方法的差別,待後續研究明白再分析.

DataFrame元素級範圍的函式應用方法使用applymap,Series元素級範圍的函式應用方法使用map

In [188]: df4
Out[188]: 
        one       two     three
a -1.101558  1.124472       NaN
b -0.177289  2.487104 -0.634293
c  0.462215 -0.486066  1.931194
d       NaN -0.456288 -1.222918

In [189]: f = lambda x: len(str(x))

In [190]: df4['one'].map(f)
Out[190]: 
a    19
b    20
c    18
d     3
Name: one, dtype: int64

In [191]: df4.applymap(f)
Out[191]: 
   one  two  three
a   19   18      3
b   20   18     19
c   18   20     18
d    3   19     19

Series的map方法還有一個附件的功能,類似通過兩個有對應關係的Series建立新的Series

In [192]: s = pd.Series(['six', 'seven', 'six', 'seven', 'six'],
   .....:               index=['a', 'b', 'c', 'd', 'e'])
   .....: 

In [193]: t = pd.Series({'six' : 6., 'seven' : 7.})

In [194]: s
Out[194]: 
a      six
b    seven
c      six
d    seven
e      six
dtype: object

In [195]: s.map(t)
Out[195]: 
a    6.0
b    7.0
c    6.0
d    7.0
e    6.0
dtype: float64

小結

本章介紹了一些pandas的基礎性功能,但僅涉及到Series和Dataframe.

因為Panel結構會在以後的Pandas版本中被棄用,所以本章中介紹的基本型功能都不涉及Panel結構.