Python數據分析 筆記3(pandas)

參考書籍 《利用Python進行數據分析(原書第2版)》第5章 pandas入門

pandas是用來處理表格型或異質型數據的。而NumPy則相反,它更適合處理同質型的數值類數組數據。

導入慣例 -> import pandas as pd

5.1 pandas數據結構介紹

兩個常用的工具數據結構 -> Series和DataFrame
5.1.1 Series

Series是一種一維的數組型對象,它包含了一個值序列,並且包含了數據標籤,稱爲索引(index)。
可以通過values屬性和index屬性分別獲得Series對象的值和索引。

默認生成的索引是從0到N-1(N是數據的長度)
可以創建一個索引序列,用標籤標識每個數據點 => 類似Python的字典,但長度固定且有序,和鍵不同,其索引值能重複

In [11]: import pandas as pd

In [12]: obj = pd.Series([222,666,888,999])

In [13]: obj
Out[13]:
0    222
1    666
2    888
3    999
dtype: int64

In [14]: obj.values
Out[14]: array([222, 666, 888, 999], dtype=int64)

In [15]: obj.index
Out[15]: RangeIndex(start=0, stop=4, step=1)

In [16]: obj2 = pd.Series([222,666,888,999], index=['a','b','c','d'])

In [17]: obj2
Out[17]:
a    222
b    666
c    888
d    999
dtype: int64

@使用布爾值對Series進行過濾

In [18]: obj[obj>666]
Out[18]:
2    888
3    999
dtype: int64

@使用一個Python字典生成Series

In [19]: sdata = {'Ohio': 35000, 'Texas': 71000, 'Oregon': 16000, 'Utah': 5000}

In [20]: obj3 = pd.Series(sdata)

In [21]: obj3
Out[21]:
Ohio      35000
Texas     71000
Oregon    16000
Utah       5000
dtype: int64

當你把字典傳遞給Series構造函數時,產生的Series的索引將是排序好的字典鍵。
你可以將字典鍵按照你所想要的順序傳遞給構造函數,從而使生成的Series的索引順序符合你的預期:

In [22]: states = ['California', 'Ohio', 'Oregon', 'Texas']

In [23]: obj4 = pd.Series(sdata, index=states)

In [24]: obj4
Out[24]:
California        NaN
Ohio          35000.0
Oregon        16000.0
Texas         71000.0
dtype: float64

說明:因爲’California’沒有出現在sdata的鍵中,它對應的值是NaN,這是pandas中標記缺失值或NA值的方式。

In [25]: pd.isnull(obj4)
Out[25]:
California     True
Ohio          False
Oregon        False
Texas         False
dtype: bool

In [26]: obj4.notnull()
Out[26]:
California    False
Ohio           True
Oregon         True
Texas          True
dtype: bool

@Series的自動對齊索引特性 

In [27]: obj3 + obj4
Out[27]:
California         NaN
Ohio           70000.0
Oregon         32000.0
Texas         142000.0
Utah               NaN
dtype: float64

@爲Series對象自身和其索引的name屬性賦值

In [28]: obj4.name

In [29]: obj4.name = 'population'
In [30]: obj4.name
Out[30]: 'population'

In [31]: obj4.index.name

In [32]: obj4.index.name = 'state'
In [33]: obj4.index.name
Out[33]: 'state'

@修改Series的索引
Series的索引可以通過按位置賦值的方式進行改變,且能重複

In [37]: obj
Out[37]:
7     222
8     666
78    888
7     999
dtype: int64

In [40]: obj.index=[7,8,7,7]
In [41]: obj[7]
Out[41]:
7    222
7    888
7    999
dtype: int64

In [42]: obj[7]=666
In [43]: obj
Out[43]:
7    666
8    666
7    666
7    666
dtype: int64

5.1.2 DataFrame
DataFrame表示的是矩陣的數據表,它包含已排序的列集合,每一列可以是不同的值類型(數值、字符串、布爾值等)。
DataFrame既有行索引也有列索引,它可以被視爲一個共享相同索引的Series的字典。在DataFrame中,數據被存儲爲一個以上的二維塊。有多種方式可以構建DataFrame,其中最常用的方式是利用包含等長度列表或NumPy數組的字典來形成DataFrame。
產生的DataFrame會自動爲Sereies分配索引,並且列會按照排序的順序排列:

In [44]: data = {'state': ['Ohio', 'Ohio', 'Ohio', 'Nevada', 'Nevada', 'Nevada'],
    ...:         'year': [2000, 2001, 2002, 2001, 2002, 2003],
    ...:         'pop': [1.5, 1.7, 3.6, 2.4, 2.9, 3.2]}

In [45]: frame = pd.DataFrame(data)

In [47]: frame
Out[47]:
    state  year  pop
0    Ohio  2000  1.5
1    Ohio  2001  1.7
2    Ohio  2002  3.6
3  Nevada  2001  2.4
4  Nevada  2002  2.9
5  Nevada  2003  3.2

如果你指定了列的順序,DataFrame的列將會按照指定順序排列:

In [50]: pd.DataFrame(data, columns=['year', 'state', 'pop'])
Out[50]:
   year   state  pop
0  2000    Ohio  1.5
1  2001    Ohio  1.7
2  2002    Ohio  3.6
3  2001  Nevada  2.4
4  2002  Nevada  2.9
5  2003  Nevada  3.2

如果你傳的列不包含在字典中,將會在結果中出現缺失值:

In [53]: frame2 = pd.DataFrame(data, columns=['year', 'state', 'pop', 'debt'],index=['one', 'two', 'three', 'four','five', 'six'])

In [54]: frame2
Out[54]:
       year   state  pop debt
one    2000    Ohio  1.5  NaN
two    2001    Ohio  1.7  NaN
three  2002    Ohio  3.6  NaN
four   2001  Nevada  2.4  NaN
five   2002  Nevada  2.9  NaN
six    2003  Nevada  3.2  NaN

In [55]: frame2.columns
Out[55]: Index(['year', 'state', 'pop', 'debt'], dtype='object')

DataFrame中的一列,可以按字典型標記或屬性那樣檢索爲Series。
注意:frame[colunm]對於任意列名均有效,但是frame.column只在列名是有效的Python變量名時有效。所以新建列只能用前者方法。

@給DataFrame的列賦值

列的引用是可以修改的。例如,1)空的’debt’列可以賦值爲標量值 或 和DataFrame的長度相匹配的數組:

eg1: frame2['debt'] = 16.5
eg2: frame2['debt'] = np.arange(6.)

2)還可以通過Series給一列賦值,空缺的地方填充缺失值。

注意:從DataFrame中選取的列是數據的視圖,而不是拷貝。因此,對Series的修改會映射到DataFrame中。
如果需要複製,則應當顯式地使用Series的copy方法。

In [58]: val = pd.Series([-1.2, -1.5, -1.7], index=['two', 'four', 'five'])
In [59]: frame2['debt'] = val
In [60]: frame2
Out[60]:
        year    state  pop  debt
one     2000     Ohio  1.5  NaN
two     2001     Ohio  1.7  -1.2
three   2002     Ohio  3.6  NaN
four    2001   Nevada  2.4  -1.5
five    2002   Nevada  2.9  -1.7

如果被賦值的列並不存在,則會生成一個新的列。del關鍵字 => 對DataFrame刪除列

In [56]: frame2['eastern'] = frame2.state == 'Ohio'

In [57]: frame2
Out[57]:
       year   state  pop debt  eastern
one    2000    Ohio  1.5  NaN     True
two    2001    Ohio  1.7  NaN     True
three  2002    Ohio  3.6  NaN     True
four   2001  Nevada  2.4  NaN    False
five   2002  Nevada  2.9  NaN    False
six    2003  Nevada  3.2  NaN    False

In [58]: frame2.columns
Out[58]: Index(['year', 'state', 'pop', 'debt', 'eastern'], dtype='object')

In [59]: del frame2['eastern']

In [60]: frame2.columns
Out[60]: Index(['year', 'state', 'pop', 'debt'], dtype='object')

@將包含字典的嵌套字典賦值給DataFrame
=> pandas會將字典的鍵作爲列,將內部字典的鍵作爲行索引:

In [1]: pop = {'Nevada': {2001: 2.4, 2002: 2.9},
   ...: 'Ohio': {2000: 1.5, 2001: 1.7, 2002: 3.6}}

In [3]: frame3 = pd.DataFrame(pop)
In [4]: frame3
Out[4]:
      Nevada  Ohio
2001     2.4   1.7
2002     2.9   3.6
2000     NaN   1.5

如果DataFrame的索引和列擁有name屬性,則這些name屬性也會被顯示:

In [5]: frame3.index.name = 'year'; frame3.columns.name = 'state'
In [6]: frame3
Out[6]:
state  Nevada  Ohio
year
2001      2.4   1.7
2002      2.9   3.6
2000      NaN   1.5

DataFrame的values屬性會將包含在DataFrame中的數據以二維ndarray的形式返回:

In [7]: frame3.values
Out[7]:
array([[2.4, 1.7],
       [2.9, 3.6],
       [nan, 1.5]])

5.1.3 索引對象
pandas中的索引對象是用於存儲軸標籤和其他元數據的(例如軸名稱或標籤)。
在構造Series或DataFrame時,你所使用的任意數組或標籤序列都可以在內部轉換爲索引對象:

In [24]: obj = pd.Series(range(3), index=['a', 'b', 'c'])
In [25]: index = obj.index
In [26]: index
Out[26]: Index(['a', 'b', 'c'], dtype='object')

索引對象是不可變的,因此無法修改索引對象:
index[1] = 'd' =>  TypeError: Index does not support mutable operations

注意:使用 pd.Series(range(3), index=['a', 'd', 'c']) 看似改變達到改變的目的,實際是改變了obj.index指向的數組,可以使用id命令查看新的索引地址id(obj.index) 和之前的索引地址id(index),會發現二者不同。

In [28]: index1 = obj.index

In [29]: obj = pd.Series(range(3), index=['a', 'd', 'c'])

In [30]: obj
Out[30]:
a    0
d    1
c    2
dtype: int64

In [31]: id(obj.index)
Out[31]: 2334912679112

In [32]: id(index)
Out[32]: 2334912240584

可以使用pd.Index() 創建索引對象=>  eg: pd.Index(np.arange(3))

pandas索引對象長度固定,且可以包含重複標籤。根據重複標籤進行篩選,會選取所有重複標籤對應的數據。

每個索引都有一些集合邏輯的方法和屬性:

一些索引對象的方法和屬性

 

5.2 基本功能

5.2.1 重建索引
reindex -> 該方法用於創建一個符合新索引的新對象

@reindex與Series
Series調用reindex方法時,會將數據按照新的索引進行排列,如果某個索引值之前並不存在,則會引入缺失值

In [34]: obj = pd.Series([4.5, 7.2, -5.3, 3.6], index=['d', 'b', 'a', 'c'])
In [35]: obj
Out[35]:
d    4.5
b    7.2
a   -5.3
c    3.6
dtype: float64

In [36]: obj2 = obj.reindex(['a', 'b', 'c', 'd', 'e'])
In [38]: obj2
Out[38]:
a   -5.3
b    7.2
c    3.6
d    4.5
e    NaN
dtype: float64

對於順序數據,比如時間序列,在重建索引時可能會需要進行插值。method可選參數允許使用諸如ffill等方法在重建索引時插值,ffill方法會將值前向填充。

In [40]: obj3 = pd.Series(['blue', 'purple', 'yellow'], index=[0, 2, 4])
In [41]: obj3
Out[41]:
0      blue
2    purple
4    yellow
dtype: object

In [42]: obj3.reindex(range(6), method='ffill')
Out[42]:
0      blue
1      blue
2    purple
3    purple
4    yellow
5    yellow
dtype: object

@reindex與DataFrame
DataFrame中,reindex可以改變行索引和列索引。1)當僅傳入一個序列時,結果中的行會重建索引

In [47]: frame = pd.DataFrame(np.arange(9).reshape((3, 3)),
    ...: index=['a', 'c', 'd'],
    ...: columns=['Ohio', 'Texas', 'California'])

In [48]: frame
Out[48]:
   Ohio  Texas  California
a     0      1           2
c     3      4           5
d     6      7           8

2)列可以使用columns關鍵字重建索引

In [49]: states = ['Texas', 'Utah', 'California']

In [50]: frame.reindex(columns=states)
Out[50]:
   Texas  Utah  California
a      1   NaN           2
c      4   NaN           5
d      7   NaN           8

3)行列索引同時改變

In [51]: frame.reindex(['a', 'b', 'c', 'd'])
Out[51]:
   Ohio  Texas  California
a   0.0    1.0         2.0
b   NaN    NaN         NaN
c   3.0    4.0         5.0
d   6.0    7.0         8.0

5.2.2 軸向上刪除條目

drop方法會返回一個含有指示值或軸向上刪除值的新對象。

【例】刪除Series的行

In [3]: obj = pd.Series(np.arange(5.), index=['a', 'b', 'c', 'd', 'e'])

In [4]: obj.drop('c')
Out[4]:
a    0.0
b    1.0
d    3.0
e    4.0
dtype: float64

In [5]: obj
Out[5]:
a    0.0
b    1.0
c    2.0
d    3.0
e    4.0
dtype: float64

In [6]: new_obj = obj.drop('c')

In [7]: new_obj
Out[7]:
a    0.0
b    1.0
d    3.0
e    4.0
dtype: float64

【例】刪除DataFrame的行/列

在調用drop時使用標籤序列會根據行標籤刪除值(軸0)
 

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

In [10]: data.drop(['Colorado', 'Ohio'])
Out[10]:
          one  two  three  four
Utah        8    9     10    11
New York   12   13     14    15
In [11]: data
Out[11]:
          one  two  three  four
Ohio        0    1      2     3
Colorado    4    5      6     7
Utah        8    9     10    11
New York   12   13     14    15

通過傳遞axis=1或axis='columns’來從列中刪除值
 

In [12]: data.drop('two', axis=1)
Out[12]:
          one  three  four
Ohio        0      2     3
Colorado    4      6     7
Utah        8     10    11
New York   12     14    15
In [13]: data
Out[13]:
          one  two  three  four
Ohio        0    1      2     3
Colorado    4    5      6     7
Utah        8    9     10    11
New York   12   13     14    15

In [14]: data.drop(['two', 'four'], axis='columns')
Out[14]:
          one  three
Ohio        0      2
Colorado    4      6
Utah        8     10
New York   12     14

drop方法帶上inplace屬性,它會清除被刪除的數據,直接操作原對象而不是返回新對象。

In [15]: obj
Out[15]:
a    0.0
b    1.0
c    2.0
d    3.0
e    4.0
dtype: float64

In [16]: obj.drop('c', inplace=True)

In [17]: obj
Out[17]:
a    0.0
b    1.0
d    3.0
e    4.0
dtype: float64

In [18]: data
Out[18]:
          one  two  three  four
Ohio        0    1      2     3
Colorado    4    5      6     7
Utah        8    9     10    11
New York   12   13     14    15

In [19]: data.drop(['two', 'four'], axis='columns',inplace=True)

In [20]: data
Out[20]:
          one  three
Ohio        0      2
Colorado    4      6
Utah        8     10
New York   12     14

5.2.3 索引、選擇與過濾

(1)Series

Series的索引(obj[...])與NumPy數組索引的功能類似,不過Series的索引值可以不僅僅是整數。

In [22]: obj = pd.Series(np.arange(4.), index=['a', 'b', 'c', 'd'])
In [23]: obj
Out[23]:
a    0.0
b    1.0
c    2.0
d    3.0
dtype: float64

In [24]: obj['b']
Out[24]: 1.0
In [25]: obj[1]
Out[25]: 1.0

In [26]: obj[:3]
Out[26]:
a    0.0
b    1.0
c    2.0
dtype: float64
In [27]: obj[2:4]
Out[27]:
c    2.0
d    3.0
dtype: float64

In [28]: obj[['b', 'a', 'd']]
Out[28]:
b    1.0
a    0.0
d    3.0
dtype: float64
In [30]: obj[[1, 0, 3]]
Out[30]:
b    1.0
a    0.0
d    3.0
dtype: float64

In [31]: obj[obj < 2]
Out[31]:
a    0.0
b    1.0
dtype: float64

注意:Series使用索引進行切片是包含尾部的:

In [32]: obj['b':'c']
Out[32]:
b    1.0
c    2.0
dtype: float64

使用這些方法設值時會修改Series相應的部分,eg: obj['b':'c'] = 5

(2)DataFrame使用單個值或序列,可以從DataFrame中索引出一個或多個列

In [35]: data = pd.DataFrame(np.arange(16).reshape((4, 4)),
    ...: index=['Ohio', 'Colorado', 'Utah', 'New York'],
    ...: columns=['one', 'two', 'three', 'four'])

In [36]: data
Out[36]:
          one  two  three  four
Ohio        0    1      2     3
Colorado    4    5      6     7
Utah        8    9     10    11
New York   12   13     14    15

In [37]: data['two']
Out[37]:
Ohio         1
Colorado     5
Utah         9
New York    13
Name: two, dtype: int32

In [39]: data[['three', 'one']]
Out[39]:
          three  one
Ohio          2    0
Colorado      6    4
Utah         10    8
New York     14   12

這種索引方式也有特殊案例。
【例1】可以根據一個布爾值數組切片或選擇數據

In [45]: data[:2]
Out[45]:
          one  two  three  four
Ohio        0    1      2     3
Colorado    4    5      6     7

In [46]: data[2:]
Out[46]:
          one  two  three  four
Utah        8    9     10    11
New York   12   13     14    15

In [47]: data[data['three'] > 5]
Out[47]:
          one  two  three  four
Colorado    4    5      6     7
Utah        8    9     10    11
New York   12   13     14    15

注意:data[:2]是行選擇語法,但data[2]不是 -> KeyError: 2

【例2】使用"布爾值DataFrame"進行索引(類似NumPy二維數組),其中"布爾值DataFrame"可以是對標量值進行比較產生的

In [48]: data[data < 5]
Out[48]:
          one  two  three  four
Ohio      0.0  1.0    2.0   3.0
Colorado  4.0  NaN    NaN   NaN
Utah      NaN  NaN    NaN   NaN
New York  NaN  NaN    NaN   NaN

In [49]: data < 5
Out[49]:
            one    two  three   four
Ohio       True   True   True   True
Colorado   True  False  False  False
Utah      False  False  False  False
New York  False  False  False  False

In [52]: data[data < 5] = 0
In [53]: data
Out[53]:
          one  two  three  four
Ohio        0    0      0     0
Colorado    0    5      6     7
Utah        8    9     10    11
New York   12   13     14    15

@使用loc和iloc選擇數據
=> 使用軸標籤(loc)或整數標籤(iloc)以NumPy風格的語法從DataFrame中選出數組的行和列的子集。

loc => 用於標籤,iloc => 用於整數

使用loc選出單行單列的數據

In [56]: data.loc['Colorado', 'two']
Out[56]: 5

使用loc選出單行多列的數據

In [57]: data.loc['Colorado', ['two', 'three']]
Out[57]:
two      5
three    6
Name: Colorado, dtype: int32

使用iloc選出單行單列的數據

In [58]: data.iloc[1,1]
Out[58]: 5

使用iloc選出單行多列的數據

In [59]: data.iloc[2, [3, 0, 1]]
Out[59]:
four    11
one      8
two      9
Name: Utah, dtype: int32

使用iloc選出單行的完整數據

In [60]: data.iloc[2]
Out[60]:
one       8
two       9
three    10
four     11
Name: Utah, dtype: int32

指定的行列數據

In [61]: data.iloc[[1, 2], [3, 0, 1]]
Out[61]:
          four  one  two
Colorado     7    0    5
Utah        11    8    9

使用loc結合切片選出行

In [62]: data.loc[:'Utah', 'two']
Out[62]:
Ohio        0
Colorado    5
Utah        9
Name: two, dtype: int32

使用iloc結合過濾列的值選出行

In [63]: data.iloc[:, :3][data.three > 5]
Out[63]:
          one  two  three
Colorado    0    5      6
Utah        8    9     10
New York   12   13     14

5.2.5 算術和數據對齊
當你將對象相加時,
s1 + s2 -> Series如果存在索引對不同,返回索引對的並集
df1 + df2 -> DataFrame行和列上都會執行對齊

沒有交疊的標籤位置上,內部數據對齊會產生缺失值。

@使用填充值的算術方法
在兩個不同的索引化對象之間進行算術操作時,可以使用特殊填充值。
比如當軸標籤在一個對象中存在,在另一個對象中不存在時,將缺失值填充爲0:
在df1上使用add方法,將df2和一個fill_value作爲參數傳入:df1.add(df2, fill_value=0)

@DataFrame和Series間的操作
DataFrame和Series間的算術操作與NumPy中不同維度數組間的操作類似。
首先,考慮二維數組和其中一行的運算:

In [3]: arr = np.arange(12).reshape((3, 4))

In [4]: arr
Out[4]:
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

In [5]: arr[0]
Out[5]: array([0, 1, 2, 3])

In [6]: arr - arr[0]
Out[6]:
array([[0, 0, 0, 0],
       [4, 4, 4, 4],
       [8, 8, 8, 8]])

In [7]: arr + arr[0]
Out[7]:
array([[ 0,  2,  4,  6],
       [ 4,  6,  8, 10],
       [ 8, 10, 12, 14]])

當我們從arr中減去/加上arr[0]時,在每一行都進行了操作 => 廣播機制
DataFrame和Series間的操作是類似的。

In [14]: frame = pd.DataFrame(np.arange(12.).reshape((4, 3)),columns=list('bde'),index=['Utah', 'Ohio', 'Texas', 'Oregon'])

In [15]: series = frame.iloc[0]

In [16]: frame
Out[16]:
          b     d     e
Utah    0.0   1.0   2.0
Ohio    3.0   4.0   5.0
Texas   6.0   7.0   8.0
Oregon  9.0  10.0  11.0

In [17]: series
Out[17]:
b    0.0
d    1.0
e    2.0
Name: Utah, dtype: float64

In [18]: frame - series
Out[18]:
          b    d    e
Utah    0.0  0.0  0.0
Ohio    3.0  3.0  3.0
Texas   6.0  6.0  6.0
Oregon  9.0  9.0  9.0

如果一個索引值不在DataFrame的列中,也不在Series的索引中,則對象會重建索引並形成聯合:

In [19]: series2 = pd.Series(range(3), index=['b', 'e', 'f'])

In [20]: frame + series2
Out[20]:
          b   d     e   f
Utah    0.0 NaN   3.0 NaN
Ohio    3.0 NaN   6.0 NaN
Texas   6.0 NaN   9.0 NaN
Oregon  9.0 NaN  12.0 NaN

In [21]: frame - series2
Out[21]:
          b   d     e   f
Utah    0.0 NaN   1.0 NaN
Ohio    3.0 NaN   4.0 NaN
Texas   6.0 NaN   7.0 NaN
Oregon  9.0 NaN  10.0 NaN

如果要在列上進行廣播(即以DataFrame的列作爲單位進行操作),使用算術方法 frame.sub(series3, axis='index')。
說明:傳遞的axis值是用於匹配軸的。例子是在DataFrame的行索引上對行匹配(axis='index’或axis=0),並進行廣播。

In [22]: series3 = frame['d']

In [23]: series3
Out[23]:
Utah       1.0
Ohio       4.0
Texas      7.0
Oregon    10.0
Name: d, dtype: float64

In [24]: frame.sub(series3, axis='index')
Out[24]:
          b    d    e
Utah   -1.0  0.0  1.0
Ohio   -1.0  0.0  1.0
Texas  -1.0  0.0  1.0
Oregon -1.0  0.0  1.0

5.2.6 函數應用和映射
NumPy的通用函數(逐元素數組方法)對pandas對象也有效。
eg: frame = pd.DataFrame(np.random.randn(2, 3), columns=list('bde'),index=['Utah', 'Ohio'])
np.abs(frame) => 每個元素取絕對值

@DataFrame的apply方法
將函數應用到一行或一列的一維數組上 -> DataFrame的apply方法可以實現
【例】找到每列的極值

In [6]: frame = pd.DataFrame(np.arange(12).reshape(4, 3), columns=list('bde'),index=['Utah', 'Ohio', 'Texas', 'Oregon'
   ...: ])

In [7]: f = lambda x: x.max() - x.min()

In [8]: frame.apply(f)
Out[8]:
b    9
d    9
e    9
dtype: int64

In [9]: frame
Out[9]:
        b   d   e
Utah    0   1   2
Ohio    3   4   5
Texas   6   7   8
Oregon  9  10  11

這裏的函數f,可以計算Series最大值和最小值的差,會被frame中的每一列調用一次。
結果是一個以frame的列作爲索引的Series。
如果你傳遞axis='columns'給apply函數,函數將會被每行調用一次:

In [14]: frame.apply(f,axis='columns')
Out[14]:
Utah      2
Ohio      2
Texas     2
Oregon    2
dtype: int64

傳遞給apply的函數並不一定要返回一個標量值,也可以返回帶有多個值的Series。

In [16]: frame
Out[16]:
               b         d         e
Utah    0.154905  0.849439  0.213608
Ohio    0.454309  2.043070 -1.523084
Texas   1.618059  0.051750  0.023853
Oregon -0.673935 -0.373966  2.711141

In [17]: def f(x):
    ...:     return pd.Series([x.min(), x.max()], index=['min', 'max'])
    ...:

In [18]: frame.apply(f)
Out[18]:
            b         d         e
min -0.673935 -0.373966 -1.523084
max  1.618059  2.043070  2.711141

In [20]: frame.apply(f,axis='columns')
Out[20]:
             min       max
Utah    0.154905  0.849439
Ohio   -1.523084  2.043070
Texas   0.023853  1.618059
Oregon -0.673935  2.711141

@DataFrame的applymap方法
逐元素使用Python函數 -> DataFrame的applymap方法可以實現

【例】格式化字符串
 

In [21]: format = lambda x: '%.2f' % x

In [22]: frame.applymap(format)
Out[22]:
            b      d      e
Utah     0.15   0.85   0.21
Ohio     0.45   2.04  -1.52
Texas    1.62   0.05   0.02
Oregon  -0.67  -0.37   2.71

注:使用applymap作爲函數名是因爲Series有map方法,可以將一個逐元素的函數應用到Series上。

In [24]: frame['e'].map(format)
Out[24]:
Utah       0.21
Ohio      -1.52
Texas      0.02
Oregon     2.71
Name: e, dtype: object

5.2.7 排序和排名

@sort_index方法排序 ->使用sort_index方法,返回一個新的、排序好的對象

(1)Series

In [25]: obj = pd.Series(range(4), index=['d', 'a', 'b', 'c'])
In [26]: obj.sort_index()
Out[26]:
a    1
b    2
c    3
d    0
dtype: int64

In [27]: obj
Out[27]:
d    0
a    1
b    2
c    3
dtype: int64

(2)DataFrame
在DataFrame中,可以在各個軸上按索引排序。
1)行索引升序排序

In [30]: frame = pd.DataFrame(np.arange(12).reshape((3, 4)),index=['three', 'one','four'],columns=['d', 'a', 'b', 'c'])
In [31]: frame.sort_index()
Out[31]:
       d  a   b   c
four   8  9  10  11
one    4  5   6   7
three  0  1   2   3


In [32]: frame.sort_index(axis=1)
Out[32]:
       a   b   c  d
three  1   2   3  0
one    5   6   7  4
four   9  10  11  8

數據默認會升序排序,也可以按照降序排序。
2)列索引降序排序

In [33]: frame.sort_index(axis=1, ascending=False)
Out[33]:
       d   c   b  a
three  0   3   2  1
one    4   7   6  5
four   8  11  10  9

@sort_values方法排序

(1)Series
根據Series的值進行排序,使用sort_values方法。

In [34]: obj = pd.Series([4, 7, -3, 2])

In [35]: obj.sort_values()
Out[35]:
2   -3
3    2
0    4
1    7
dtype: int64

默認情況下,無論升序、降序 所有的缺失值(np.nan)都會被排序至Series的尾部:
(2)DataFrame
使用一列或多列作爲鍵對DataFrame排序時。
=> 傳遞一個或多個列名給sort_values的可選參數by

In [38]: frame = pd.DataFrame({'b': [4, 7, -3, 2], 'a': [0, 1, 0, 1]})
In [39]: frame.sort_values(by='b')
Out[39]:
   b  a
2 -3  0
3  2  1
0  4  0
1  7  1

In [40]: frame
Out[40]:
   b  a
0  4  0
1  7  1
2 -3  0
3  2  1

In [41]: frame.sort_values(by=['a', 'b'])
Out[41]:
   b  a
2 -3  0
0  4  0
3  2  1
1  7  1

@rank方法排名

(1)Series
Series和DataFrame的rank方法是實現排名的方法,1)默認情況下,rank通過將平均排名分配到每個組來打破平級關係:

In [42]: obj = pd.Series([7, -5, 7, 4, 2, 0, 4])

In [43]: obj.rank()
Out[43]:
0    6.5
1    1.0
2    6.5
3    4.5
4    3.0
5    2.0
6    4.5
dtype: float64

說明:對條目0和2設置的名次爲6.5,(6+7)/2 =>平均排名6.5

2)排名也可以根據他們在數據中的觀察順序進行分配

In [217]: obj.rank(method='first')
Out[217]:
0     6.0
1     1.0
2     7.0
3     4.0
4     3.0
5     2.0
6     5.0
dtype: float64

說明:對條目0和2設置的名次爲6和7,而不是之前的平均排名6.5,是因爲在數據中標籤0在標籤2的前面。

3)按降序排名:

In [44]: obj.rank(ascending=False, method='max')
Out[44]:
0    2.0
1    7.0
2    2.0
3    4.0
4    5.0
5    6.0
6    4.0
dtype: float64

In [45]: obj.rank(ascending=False, method='min')
Out[45]:
0    1.0
1    7.0
2    1.0
3    3.0
4    5.0
5    6.0
6    3.0
dtype: float64

(2)DataFrameDataFrame可以對行或列計算排名。

In [46]: frame = pd.DataFrame({'b': [4.3, 7, -3, 2], 'a': [0, 1, 0, 1],'c': [-2, 5, 8, -2.5]})

In [47]: frame
Out[47]:
     b  a    c
0  4.3  0 -2.0
1  7.0  1  5.0
2 -3.0  0  8.0
3  2.0  1 -2.5

In [48]: frame.rank()
Out[48]:
     b    a    c
0  3.0  1.5  2.0
1  4.0  3.5  3.0
2  1.0  1.5  4.0
3  2.0  3.5  1.0

In [49]: frame.rank(axis='columns')
Out[49]:
     b    a    c
0  3.0  2.0  1.0
1  3.0  1.0  2.0
2  1.0  2.0  3.0
3  3.0  2.0  1.0

5.2.8 含有重複標籤的軸索引
儘管很多pandas函數(比如reindex)需要標籤是唯一的,但並不強制。
索引的is_unique屬性可以告訴你它的標籤是否唯一 -> eg: obj.index.is_unique
Series根據一個標籤索引多個條目會返回一個序列,而單個條目會返回標量值。
相同的邏輯可以拓展到在DataFrame中進行行索引。

5.3 描述性統計的概述與計算

pandas對象裝配了一個常用數學、統計學方法的集合。

(1)歸約或彙總統計的類別

調用DataFrame的sum方法返回一個按列加和的Series(對每個列向量求和),傳入axis='columns’或axis=1,按行加和

In [3]: df = pd.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'])

In [4]: df
Out[4]:
    one  two
a  1.40  NaN
b  7.10 -4.5
c   NaN  NaN
d  0.75 -1.3

In [5]: df.sum()
Out[5]:
one    9.25
two   -5.80
dtype: float64

In [6]: df.sum(axis='columns')
Out[6]:
a    1.40
b    2.60
c    0.00
d   -0.55
dtype: float64

除非整個切片上(在本例中是行或列)都是NA,否則NA值是被自動排除的。可以通過禁用skipna來實現不排除NA值。

In [7]: df.mean(axis='columns', skipna=False)
Out[7]:
a      NaN
b    1.300
c      NaN
d   -0.275
dtype: float64

一些方法,返回間接統計信息,比如idxmin和idxmax,最小值或最大值的索引值

In [9]: df.idxmax()
Out[9]:
one    b
two    d
dtype: object

(2)積累型方法

In [10]: df.cumsum()
Out[10]:
    one  two
a  1.40  NaN
b  8.50 -4.5
c   NaN  NaN
d  9.25 -5.8

(3)describe一次性產生多個彙總統計

In [12]: df.describe()
Out[12]:
            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.3.1 相關性和協方差

Series的corr方法計算的是兩個Series中重疊的、非NA的、按索引對齊的值的相關性。相應地,cov計算的是協方差。

使用DataFrame的corrwith方法,你可以計算出DataFrame中的行或列與另一個序列或DataFrame的相關性。該方法傳入一個Series時,會返回一個含有爲每列計算相關性值的Series;傳入一個DataFrame時,會計算匹配到列名的相關性數值。

5.3.2 唯一值、計數和成員屬性
@unique給出Series中的唯一值

In [251]: obj = pd.Series(['c', 'a', 'd', 'a', 'a', 'b', 'b', 'c', 'c'])
In [252]: uniques = obj.unique()
In [253]: uniques
Out[253]: array(['c', 'a', 'd', 'b'], dtype=object)

唯一值並不一定按照排序好的順序返回,可以用uniques. sort()進行排序。

@value_counts計算Series包含的值的個數

In [254]: obj.value_counts()
Out[254]:
c     3
a     3
b     2
d     1
dtype: int64

返回的Series會按照數量降序排序。不排序帶上sort=False。

In [255]: pd.value_counts(obj.values, sort=False)
Out[255]:
a     3
b     2
c     3
d     1
dtype: int64

@isin執行向量化的成員屬性檢查,還可以將數據集以Series或DataFrame一列的形式過濾爲數據集的值子集。

In [256]: obj
Out[256]:
0     c
1     a
2     d
3     a
4     a
5     b
6     b
7     c
8     c
dtype: object
In [257]: mask = obj.isin(['b', 'c'])
In [258]: mask
Out[258]:
0      True
1     False
2     False
3     False
4     False
5      True
6      True
7      True
8      True
dtype: bool
In [259]: obj[mask]
Out[259]:
0     c
5     b
6     b
7     c
8     c
dtype: object

@計算DataFrame多個相關列的直方圖

將pandas.value_counts傳入DataFrame的apply函數可以得到如下結果,行標籤是所有列中出現的不同值,數值則是這些不同值在每個列中出現的次數。

In [13]: data = pd.DataFrame({'Qu1': [1, 3, 4, 3, 4],
    ...: 'Qu2': [2, 3, 1, 2, 3],
    ...: 'Qu3': [1, 5, 2, 4, 4]})

In [14]: data
Out[14]:
   Qu1  Qu2  Qu3
0    1    2    1
1    3    3    5
2    4    1    2
3    3    2    4
4    4    3    4

In [15]: result = data.apply(pd.value_counts).fillna(0)

In [16]: result
Out[16]:
   Qu1  Qu2  Qu3
1  1.0  1.0  1.0
2  0.0  2.0  1.0
3  2.0  2.0  0.0
4  2.0  0.0  2.0
5  0.0  0.0  1.0

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章