Pandas數據處理之層級索引

3.6 層級索引

3.6.1 多級索引Series

  在實際工作中,我們會經常遇到多維數據,數據索引超過一兩個鍵。我們可以通過層級索引配合多個不同等級的一級索引一起使用,這樣就可以將多維數組轉換成類似Series和DataFrame的形式.

舉例:分析美國各種在兩個不同年份的數據:

In [1] :import pandas as pd
		import numpy as np
In [2] :index = [('California', 2000), ('California', 2010),('New York', 2000), ('New York', 2010),('Texas', 2000), ('Texas', 2010)]
		populations = [33871648, 37253956,18976457, 19378102,20851820, 25145561]
		pop = pd.Series(populations, index=index)
		pop
Out[2] :(California, 2000)    33871648
		(California, 2010)    37253956
		(New York, 2000)      18976457
		(New York, 2010)      19378102
		(Texas, 2000)         20851820
		(Texas, 2010)         25145561
		dtype: int64

  現在我們想查看所有州2000年的數據,那麼會稍微複雜一些:

In [2] :pop[[i for i in pop.index if i[1]==2010]]
Out[2] :(California, 2010)    37253956
		(New York, 2010)      19378102
		(Texas, 2010)         25145561
		dtype: int64

  雖然這種辦法是可行的,但是不夠簡潔,特別是當數據量變大時,效率會很低。所以,pandas提過了更好的解決方案,使用MultiIndex將元組創建一個多級索引。

In [3] :index = pd.MultiIndex.from_tuples(index)
		index 
Out[3] :MultiIndex(levels=[['California', 'New York', 'Texas'], [2000, 2010]],labels=[[0, 0, 1, 1, 2, 2], [0, 1, 0, 1, 0, 1]])

  使用新索引替換pop原有索引,得到一個類似DataDrame的Series。其中:前兩列表示Series的多級索引值,第三列是數據。第一列中的空格等同於上面的索引。

In [3] :pop = pop.reindex(index)
		pop
Out[3] :
California  2000    33871648
            2010    37253956
New York    2000    18976457
            2010    19378102
Texas       2000    20851820
            2010    25145561
dtype: int64

  現在,我們再來獲取某一年美國各州的人口數據:

In [4] :pop[:,2010]
Out[4] :
California    37253956
New York      19378102
Texas         25145561
dtype: int64

  可以看到,取值操作更簡潔。其實,上面的Series可以用DataFrame來表示,unstack() 方法可以快速將一個多級索引的Series 轉化爲普通索引的DataFrame:

In [5] :pop_df = pop.unstack()
		pop_df
Out[5] :
			  2000		  2010
California	33871648	37253956
New York	18976457	19378102
Texas		20851820	25145561

  stack()方法可以實現相反的效果,將DataFrame轉爲一個多級索引的Series:

In [6] :pop_df.stack()
Out[6] :
California  2000    33871648
            2010    37253956
New York    2000    18976457
            2010    19378102
Texas       2000    20851820
            2010    25145561
dtype: int64

  意義:我們可以用多級索引的一維Series數據表示二維數據,那麼就可以用DataFrame表示三維甚至更高維度的數據。理論上可以表示任意維度的數據。

3.6.2 多級索引的創建方法

1.顯式地創建多級索引

  通過一個有不同等級的若干簡單數組組成的列表來構建MultiIndex:

In [7] :pd.MultiIndex.from_arrays([['a', 'a', 'b', 'b'], [1, 2, 1, 2]])
Out[7] :MultiIndex(levels=[['a', 'b'], [1, 2]],
           labels=[[0, 0, 1, 1], [0, 1, 0, 1]])

  也可以通過包含多個索引值的元組構成的列表創建MultiIndex:

In [8] :pd.MultiIndex.from_tuples([('a', 1), ('a', 2), ('b', 1), ('b', 2)])
Out[8] :MultiIndex(levels=[['a', 'b'], [1, 2]],
           labels=[[0, 0, 1, 1], [0, 1, 0, 1]])

  更可以直接提供levels(包含每個等級的索引值列表的列表)和labels(包含每個索引值標籤列表的列表)創建MultiIndex:

In [9] :pd.MultiIndex(levels=[['a', 'b'], [1, 2]],labels=[[0, 0, 1, 1], [0, 1, 0, 1]])
Out[9] :MultiIndex(levels=[['a', 'b'], [1, 2]],labels=[[0, 0, 1, 1], [0, 1, 0, 1]])

  在創建Series 或DataFrame 時,可以將這些對象作爲index 參數,或者通過reindex 方法更新Series 或DataFrame 的索引。

2. 多級索引的等級名稱

  給MultiIndex 的等級加上名稱會爲一些操作提供便利。你可以在前面任何一個MultiIndex構造器中通過names 參數設置等級名稱,也可以在創建之後通過索引的names 屬性來修改名稱:

In [10]:pop.index.names = ['state', 'year']
		pop
Out[10]: 
			state     year
California  2000    33871648
            2010    37253956
New York    2000    18976457
            2010    19378102
Texas       2000    20851820
            2010    25145561
dtype: int64

3. 多級列索引

  每個DataFrame 的行與列都是對稱的,也就是說既然有多級行索引,那麼同樣可以有多級列索引

In [11]: # 多級行索引
index = pd.MultiIndex.from_product([[2013, 2014], [1, 2]],names=['year', 'visit'])

In [12]: # 多級列索引
columns = pd.MultiIndex.from_product([['Bob', 'Guido', 'Sue'], ['HR', 'Temp']],names=['subject', 'type'])

In [13]:# 模擬數據
data = np.round(np.random.randn(4, 6), 1)
data[:, ::2] *= 10
data += 37

In [14]: # 創建DataFrame
health_data = pd.DataFrame(data, index=index, columns=columns)
health_data
Out[14]:

	subject	 	  Bob		 Guido		  Sue
	type		HR	Temp	HR	Temp	HR	Temp
year  visit						
2013	1	19.0	-0.9	-10.0	-0.6	-2.0	-1.1
		2	15.0	-0.3	16.0	-0.3	10.0	-1.2
2014	1	-12.0	 0.4	-4.0	 0.2	11.0	-1.3
		2	4.0		 0.5	 9.0	-0.9	 7.0	 0.4

3.6.3 多級索引的取值與切片

1. Series多級索引

  對於美國各州人口數據的多級索引Series來說:

In [15]:pop
Out[15]:
			state     year
California  2000    33871648
            2010    37253956
New York    2000    18976457
            2010    19378102
Texas       2000    20851820
            2010    25145561
dtype: int64

  可以通過對多個級別索引值獲取單個元素:

In [16]:pop['California', 2010]
Out[16]:37253956

  Miltiindex也支持局部取值,即只取索引的某一個層級。假設只取最高級別的索引(California),獲得的結果是一個新的Series,未被選中的低索引值(2000,2010)會被保留。

In [17]:pop['California']
Out[17]:
year
2000    33871648
2010    37253956
dtype: int64

2. DataFrame多級索引

  DataFrame多級索引的用法與Series類似。

In [18]:health_data
Out[18]:

	subject	 	  Bob		 Guido		  Sue
	type		HR	Temp	HR	Temp	HR	Temp
year  visit						
2013	1	19.0	-0.9	-10.0	-0.6	-2.0	-1.1
		2	15.0	-0.3	16.0	-0.3	10.0	-1.2
2014	1	-12.0	 0.4	-4.0	 0.2	11.0	-1.3
		2	4.0		 0.5	 9.0	-0.9	 7.0	 0.4

  由於DataFrame的基本索引是列索引,因此Series中多級索引的用法到了DataFrame中就應用在列上了。例如,可以通過簡單的操作獲取Guido的心率數據:

In [19]:health_data['Guido', 'HR']
Out[19]:
year  visit
2013  1       -10.0
      2        16.0
2014  1        -4.0
      2         9.0
Name: (Guido, HR), dtype: float64

  與單索引類似,loc、iloc 和ix 索引器都可以使用,例如:

In [20]:health_data.iloc[:2, :2]
Out[20]:
	subject		  Bob
	type		HR	Temp
year  visit		
2013	1		19.0 -0.9
		2		15.0 -0.3
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章