pandas之索引操作


索引(index)是 Pandas 的重要工具,通過索引可以從 DataFame 中選擇特定的行數和列數,這種選擇數據的方式稱為“子集選擇”。

在 Pandas 中,索引值也被稱為標簽(label),它在 Jupyter 筆記本中以粗體字進行顯示。索引可以加快數據訪問的速度,它就好比數據的書簽,通過它可以實現數據的快速查找。

創建索引

通過示例對 index 索引做進一步講解。下面創建一個帶有 index 索引的數據,並使用 read_csv() 這些讀取數據:

  1. import pandas as pd
  2. data = pd.read_csv("person.csv")
  3. print(data)

輸出結果:

   ID   Name  Age      City  Salary
0   1   Jack   28   Beijing   22000
1   2   Lida   32  Shanghai   19000
2   3   John   43  Shenzhen   12000
3   4  Helen   38  Hengshui    3500

通過列索引(標簽)讀取多列數據。

  1. import pandas as pd
  2. #設置"Name"為行索引
  3. data = pd.read_csv("person.csv", index_col ="Name")
  4. # 通過列標簽選取多列數據
  5. a = data[["City","Salary"]]
  6. print(a)

輸出結果:

           City  Salary
Name                  
Jack    Beijing   22000
Lida   Shanghai   19000
John   Shenzhen   12000
Helen  Hengshui    3500

再看一組簡單的示例:

  1. import pandas as pd
  2. info =pd.read_csv("person.csv", index_col ="Name")
  3. #獲取單列數據,或者以列表的形式傳入["Salary"]
  4. a =info["Salary"]
  5. print(a)

輸出結果:

       Salary
Name        
Jack    22000
Lida    19000
John    12000
Helen    3500

設置索引

set_index() 將已存在的列標簽設置為 DataFrame 行索引。除了可以添加索引外,也可以替換已經存在的索引。比如您也可以把 Series 或者一個 DataFrme 設置成另一個 DataFrame 的索引。示例如下:

  1. info = pd.DataFrame({'Name': ['Parker', 'Terry', 'Smith', 'William'], 'Year': [2011, 2009, 2014, 2010],
  2. 'Leaves': [10, 15, 9, 4]})
  3. #設置Name為行索引
  4. print(info.set_index('Name'))

輸出結果:

         Year  Leaves
Name                
Parker   2011      10
Terry    2009      15
Smith    2014       9
William  2010       4

重置索引

您可以使用 reset_index() 來恢復初始行索引,示例如下:

  1. import pandas as pd
  2. import numpy as np
  3. info = pd.DataFrame([('William', 'C'),
  4. ('Smith', 'Java'),
  5. ('Parker', 'Python'),
  6. ('Phill', np.nan)],
  7. index=[1, 2, 3, 4],
  8. columns=('name', 'Language'))
  9. print(info)
  10. print(info.reset_index())

輸出結果:

重置前:
     name    Language
1  William        C
2    Smith     Java
3   Parker   Python
4    Phill      NaN
重置后:
   index     name    Language
0      1  William        C
1      2    Smith     Java
2      3   Parker   Python
3      4    Phill      NaN

 ---------------------------------------------------------------------------------------

分層索引(Multiple Index)是 Pandas 中非常重要的索引類型,它指的是在一個軸上擁有多個(即兩個以上)索引層數,這使得我們可以用低維度的結構來處理更高維的數據。比如,當想要處理三維及以上的高維數據時,就需要用到分層索引。

分層索引的目的是用低維度的結構(Series 或者 DataFrame)更好地處理高維數據。通過分層索引,我們可以像處理二維數據一樣,處理三維及以上的數據。分層索引的存在使得分析高維數據變得簡單,讓抽象的高維數據變得容易理解,同時它比廢棄的 Panel 結構更容易使用。

Pandas 可以通過 MultiIndex() 方法來創建分層索引對象,該對象本質上是一個元組序列,序列中每一個元組都是唯一的。下面介紹幾種創建分層索引的方式。

創建分層索引

1) 直接創建

通過 MultiIndex() 的levels參數能夠直接創建分層索引,示例如下:

  1. import pandas as pd
  2. import numpy as np
  3. #為leves傳遞一個1行5列的二維數組
  4. df=pd.MultiIndex(levels=[[np.nan, 2, pd.NaT, None, 5]], codes=[[4, -1, 1, 2, 3, 4]])
  5. print(df.levels)
  6. print(df)

輸出結果:

[[nan, 2, NaT, None, 5]]

MultiIndex([(  5,),
            (nan,),
            (  2,),
            (nan,),
            (nan,),
            (  5,)],
           )

上述代碼中,levels參數用來創建層級索引,這里只有一層,該層的索引值分別是 np.nan, 2, NaT, None, 5;codes表示按參數值對層級索引值排序(與 levels 中的值相對應),也就說 codes 中數值是 leves 序列的下標索引。需要注意,這里的 -1 代表 NaN。

2) 從元組創建

通過 from_tuples() 實現從元組創建分層索引。

  1. #創建元組序列
  2. arrays = [['it', 'it', 'of', 'of', 'for', 'for', 'then', 'then'],
  3. ['one', 'two', 'one', 'two', 'one', 'two', 'one', 'two']]
  4. #使用zip()函數創建元組
  5. tuples = list(zip(*arrays))
  6. print(tuples)

輸出結果如下:

[('it', 'one'),
('it', 'two'),
('of', 'one'),
('of', 'two'),
('for', 'one'),
('for', 'two'),
('then', 'one'),
('then', 'two')]

然后使用 tuples 創建分層索引,如下所示:

  1. import pandas as pd
  2. #創建了兩層索引,並使用names對它們命名
  3. index = pd.MultiIndex.from_tuples(tuples, names=['first', 'second'])
  4. print(index)

輸出結果:

MultiIndex([(  'it', 'one'),
            (  'it', 'two'),
            (  'of', 'one'),
            (  'of', 'two'),
            ( 'for', 'one'),
            ( 'for', 'two'),
            ('then', 'one'),
            ('then', 'two')],
           names=['first', 'second'])

3) 從DataFrame對象創建

通過 from_frame() 創建分層索引,示例如下:

  1. #首先創建一個 DataFrame。
  2. import pandas as pd
  3. df = pd.DataFrame([['bar', 'one'], ['bar', 'two'],
  4. ['foo', 'one'], ['foo', 'two']],
  5. columns=['first', 'second'])
  6. #然后使用 from_frame()創建分層索引。
  7. index = pd.MultiIndex.from_frame(df)
  8. #將index應用於Series
  9. s=pd.Series(np.random.randn(4), index=index)
  10. print(s)

輸出結果:

first  second
bar    one       1.151928
       two      -0.694435
foo    one      -1.701611
       two      -0.486157
dtype: float64

4) 笛卡爾積創建

笛卡爾積(又稱直積)是數學運算的一種方式,下面使用 from_product() 笛卡爾積創建分層索引。

  1. import pandas as pd
  2. #構建數據
  3. numbers = [0, 1, 2]
  4. language = ['Python', 'Java']
  5. #經過笛卡爾積處理后會得到6中組合方式
  6. index = pd.MultiIndex.from_product([numbers, language],names=['number', 'language'])
  7. #將分層索引對象應用於Series
  8. dk_er=pd.Series(np.random.randn(6), index=index)
  9. print(dk_er)

輸出結果:

number  language
0       Python     -0.319739
        Java        1.599170
1       Python     -0.010520
        Java        0.262068
2       Python     -0.124177
        Java        0.315120
dtype: float64

5) 數組創建分層索引

通過 from_array() 方法,同樣可以創建分層索引。示例如下:

  1. import pandas as pd
  2. df=pd.MultiIndex.from_arrays([['a', 'a', 'b', 'b'],[1, 2, 1, 2]])
  3. df

輸出結果:

MultiIndex([('a', 1),
            ('a', 2),
            ('b', 1),
            ('b', 2)],
           )

應用分層索引

下面示例講解了如何在 DataFrame 中應用分層索引。

  1. import pandas as pd
  2. import numpy as np
  3. #創建一個數組
  4. arrays = [[0, 0, 1, 1], ['A', 'B', 'A', 'B']]
  5. #從數組創建
  6. index=pd.MultiIndex.from_arrays(arrays, names=('number', 'letter'))
  7. print(index)

輸出結果

MultiIndex([(0, 'A'),
            (0, 'B'),
            (1, 'A'),
            (1, 'B')],
           names=['number', 'letter'])

上述示例中,第一層為 number,該層有 0、1 兩個元素,第二層為 letter,有兩個字母 A 和 B。

下面把已經創建的分層索引應用到 DataFrame 中,如下所示:

  1. import pandas as pd
  2. import numpy as np
  3. #創建一個數組
  4. arrays = [[0, 0, 1, 1], ['A', 'B', 'A', 'B']]
  5. index=pd.MultiIndex.from_arrays(arrays, names=('number', 'letter'))
  6. #在行索引位置應用分層索引
  7. df=pd.DataFrame([{'a':11, 'b':22}], index=index)
  8. print(df)

輸出結果:

                a   b
number letter       
0      A       11  22
       B       11  22
1      A       11  22
       B       11  22

通過 set_index() 可以將 DataFrame 的已有列的標索設置為 index 行索引,示例如下:

  1. import pandas as pd
  2. df= pd.DataFrame({'a': range(5), 'b': range(5, 0, -1),
  3. 'c': ['one', 'one', 'one', 'two', 'two'],
  4. 'd': [0, 1, 2, 0, 1]})
  5. print(df)
  6. df1=df.set_index(['a','d'],drop=False)
  7. print(df1)
  8. df1=df.set_index(['a','d'],drop=False,append=Ture)
  9. print(df2)

輸出結果:

轉換前:
   a  b    c  d
0  0  5  one  0
1  1  4  one  1
2  2  3  one  2
3  3  2  two  0
4  4  1  two  1
轉換后:
     a  b    c  d
a d             
0 0  0  5  one  0
1 1  1  4  one  1
2 2  2  3  one  2
3 0  3  2  two  0
4 1  4  1  two  1
帶append參數:
       a  b    c  d
  a d            
0 0 0  0  5  one  0
1 1 1  1  4  one  1
2 2 2  2  3  one  2
3 3 0  3  2  two  0
4 4 1  4  1  two  1

通過 set_index() 將列索引轉換為了分層行索引,其中 drop=False 表示更新索引的同時,不刪除 a、d 列;同時,該函數還提供了一個 append = Ture 參數表示不添加默認的整數索引值(0到4)

分層索引切片取值

下面講解分層索引切片取值操作,示例如下:

1) 分層行索引操作

  1. import pandas as pd
  2. #構建多層索引
  3. tuple = [('湖人',2008),('步行者',2008),
  4. ('湖人',2007),('凱爾特人',2007),
  5. ('籃網',2007),('熱火',2008)]
  6. salary = [10000,20000,11000,30000,19000,22000]
  7. #其次應用於DataFrame
  8. index = pd.MultiIndex.from_tuples(tuple)
  9. s = pd.Series(salary, index=index)
  10. print(s)
  11. #切片取值
  12. print(s['湖人',2007])
  13. print(s['湖人'])
  14. print(s[:,2008])
  15. #比較value
  16. print(s[s<=20000])

輸出結果:

湖人    2008    10000
步行者   2008    20000
湖人    2007    11000
凱爾特人  2007    30000
籃網    2007    19000
熱火    2008    22000
dtype: int64

湖人隊2007年工資:
11000

湖人隊的工資:
2008    10000
2007    11000
dtype: int64

2008年所有隊伍工資:
湖人     10000
步行者    20000
熱火     22000
dtype: int64

小於等於20000的年份和隊伍:
湖人   2008    10000
步行者  2008    20000
湖人   2007    11000
籃網   2007    19000
dtype: int64

2) 行、列多層索引操作

下面看一種更加復雜的情況,就是行、列同時存在多層索引時候,應該如何通過切片取值。示例如下:

  1. df = pd.DataFrame(np.arange(1,13).reshape((4, 3)),
  2. index=[['a', 'a', 'b', 'b'], [1, 2, 1, 2]],
  3. columns=[['Jack', 'Jack', 'Helen'],
  4. ['Python', 'Java', 'Python']])
  5. #選擇同一層級的索引,切記不要寫成['Jack','Helen']
  6. print(df[['Jack','Helen']])
  7. #在不同層級分別選擇索引
  8. print(df['Jack','Python'])
  9. #iloc整數索引
  10. print(df.iloc[:3,:2])
  11. #loc列標簽索引
  12. print(df.loc[:,('Helen','Python')])

輸出結果:

      Jack       Helen
    Python Java Python
a 1      1    2      3
  2      4    5      6
b 1      7    8      9
  2     10   11     12

a  1     1
   2     4
b  1     7
   2    10
Name: (Jack, Python), dtype: int32

      Jack    
    Python Java
a 1      1    2
  2      4    5
b 1      7    8

a  1     3
   2     6
b  1     9
   2    12
Name: (Helen, Python), dtype: int32

聚合函數應用

通過給level傳遞參數值,您可以指定在哪個層上進行聚合操作,比如求和、求均值等。示例如下:

  1. import pandas as pd
  2. df = pd.DataFrame(np.arange(1,13).reshape((4, 3)),
  3. index=[['a', 'a', 'b', 'b'], [1, 2, 1, 2]],
  4. columns=[['Jack', 'Jack', 'Helen'],
  5. ['Python', 'Java', 'Python']])
  6. #第一步,給行列層級起名字
  7. df.index.names=['key1','key2']
  8. df.columns.names=['name','course']
  9. print(df.sum(level='key2'))
  10. print(df.mean(level="course",axis=1))

輸出結果:

#對key2層1/2對應的元素值求和
name     Jack       Helen
course Python Java Python
key2                    
1           8   10     12
2          14   16     18

#axis=1沿着水平方向求均值
course     Python  Java
key1 key2             
a    1          2     2
     2          5     5
b    1          8     8
     2         11    11

在數據分析的過程中,我們把大部分時間都花費在數據的准備和預處理上,Pandas 作為一個靈活、高效的數據預處理工具,提供了諸多數據處理的方法,分層索引(Multiple Index)就是其中之一,分層索引(或多層索引)是 Pandas 的基本特性,它能夠增強 Pands 數據預處理的能力。

對於 Series 結構來說,通過給index參數傳遞一個二維數組就可以創建一個具有兩層索引的 MultiIndex 對象,示例如下:

  1. import pandas as pd
  2. info = pd.Series([11, 14, 17, 24, 19, 32, 34, 27],
  3. index = [['x', 'x', 'x', 'x', 'y', 'y', 'y', 'y'],
  4. ['obj1', 'obj2', 'obj3', 'obj4', 'obj1', 'obj2', 'obj3', 'obj4']])
  5. print(info)

輸出結果:

x  obj1    11
   obj2    14
   obj3    17
   obj4    24
y  obj1    19
   obj2    32
   obj3    34
   obj4    27
dtype: int64

上述示例,創建了兩個層級的索引,即 (x, y) 和 (obj1,…, obj4),您可以使用 'index' 命令查看索引。

info.index

輸出結果:

MultiIndex([('x', 'obj1'),
            ('x', 'obj2'),
            ('x', 'obj3'),
            ('x', 'obj4'),
            ('y', 'obj1'),
            ('y', 'obj2'),
            ('y', 'obj3'),
            ('y', 'obj4')],
           )

此外,您還可以基於內部索引層(也就是'obj')來選擇數據。如下所示:

info [:,'obj2' ]

輸出結果:

x    14
y    32
dtype: int64

局部索引

局部索引可以理解為:從分層索引中選擇特定索引層的一種方法。比如在下列數據中,選擇所有'y'索引指定的數據,示例如下:

  1. import pandas as pd
  2. info = pd.Series([11, 14, 17, 24, 19, 32, 34, 27],
  3. index = [['x', 'x', 'x', 'x', 'y', 'y', 'y', 'y'],
  4. ['obj1', 'obj2', 'obj3', 'obj4', 'obj1', 'obj2', 'obj3', 'obj4']])
  5. info['y']

輸出結果:

obj1    19
obj2    32
obj3    34
obj4    27
dtype: int64

當然您也可以基於內層索引選擇數據。

行索引層轉換為列索引

unstack() 用來將行索引轉變成列索引,相當於轉置操作。通過 unstack() 可以將 Series(一維序列)轉變為 DataFrame(二維序列)。示例如下:

  1. import pandas as pd
  2. info = pd.Series([11, 14, 17, 24, 19, 32, 34, 27],
  3. index = [['x', 'x', 'x', 'x', 'y', 'y', 'y', 'y'],
  4. ['obj1', 'obj2', 'obj3', 'obj4', 'obj1', 'obj2', 'obj3', 'obj4']])
  5. #行索引標簽默認是最外層的 x, y
  6. #0代表第一層索引,而1代表第二層
  7. print(info.unstack(0))

輸出結果:

  1. x y
  2. obj1 11 19
  3. obj2 14 32
  4. obj3 17 34
  5. obj4 24 27

從示例可以看出,unstack(0) 表示選擇第一層索引作為列,unstack(1) 表示選擇第二層,如下所示:

  1. import pandas as pd
  2. info = pd.Series([11, 14, 17, 24, 19, 32, 34, 27],
  3. index = [['x', 'x', 'x', 'x', 'y', 'y', 'y', 'y'],
  4. ['obj1', 'obj2', 'obj3', 'obj4', 'obj1', 'obj2', 'obj3', 'obj4']])
  5. print(info.unstack(1))

輸出結果:

   obj1  obj2  obj3  obj4
x    11    14    17    24
y    19    32    34    27

列索引實現分層

我們知道,列索引存在於 DataFrame 結構中,下面創建一個 DataFrame 來演示列索引如何實現分層。

  1. import numpy as np
  2. info = pd.DataFrame(np.arange(12).reshape(4, 3),
  3. index = [['a', 'a', 'b', 'b'], ['one', 'two', 'three', 'four']],
  4. columns = [['num1', 'num2', 'num3'], ['x', 'y', 'x']] )
  5. print(info)

輸出結果:

        num1 num2 num3
           x    y    x
a one      0    1    2
  two      3    4    5
b three    6    7    8
  four     9   10   11

查看所有列索引:

info.columns

輸出結果:

MultiIndex([('num1', 'x'),
            ('num2', 'y'),
            ('num3', 'x')],)

交換層和層排序

1) 交換層

通過 swaplevel() 方法輕松地實現索引層交換,示例如下:

  1. import pandas as pd
  2. frame = pd.DataFrame(np.arange(12).reshape((4, 3)),
  3. index=[['a', 'a', 'b', 'b'], [1, 2, 1, 2]],
  4. columns=[['Ohio', 'Ohio', 'Colorado'],
  5. ['Green', 'Red', 'Green']])
  6. #設置index的levels名稱
  7. frame.index.names = ['key1', 'key2']
  8. #設置columns的levels名稱
  9. frame.columns.names = ['state','color']
  10. #交換key1層與key層
  11. frame.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

2) 層排序

通過 sort_index() 的level參數實現對層的排序。下面示例,按“key1”的字母順序重新排序。

  1. import pandas as pd
  2. frame = pd.DataFrame(np.arange(12).reshape((4, 3)),
  3. index=[['a', 'a', 'b', 'b'], [1, 2, 1, 2]],
  4. columns=[['Ohio', 'Ohio', 'Colorado'],
  5. ['Green', 'Red', 'Green']])
  6. #設置index的levels的名稱,key1 與 key2分別對應不同的層
  7. frame.index.names = ['key1', 'key2']
  8. #設置columns的levels的名稱
  9. frame.columns.names = ['state','color']
  10. print(frame.sort_index(level='key1'))

輸出結果:

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM