pandas對象中的軸標簽信息有許多用途: 使用已知的指標標識數據(即提供元數據),這對於分析,可視化和交互式控制台顯示很重要。 啟用自動和顯式數據對齊。 允許直觀地獲取和設置數據集的子集。 在本節中,我們將重點關注最后一點:即如何切片,切塊,以及通常如何獲取和設置熊貓對象的子集。主要重點將放在Series和DataFrame上,因為它們在該領域得到了更多的開發關注。 注意 Python和NumPy索引運算符[]和屬性運算符. 可在各種用例中快速輕松地訪問熊貓數據結構。這使交互式工作變得直觀,因為如果您已經知道如何處理Python字典和NumPy數組,則沒有什么新的知識要學習。但是,由於事先不知道要訪問的數據類型,因此直接使用標准運算符存在一些優化限制。對於生產代碼,我們建議您利用本章中介紹的優化的熊貓數據訪問方法。 警告 為設置操作返回副本還是參考,可能取決於上下文。這有時被稱為,應該避免。請參閱返回視圖與復制。chained assignment 警告 在0.18.0中已闡明了對基於整數的帶有浮點數的索引的索引,有關更改的摘要,請參見此處。 見多指標/高級索引的MultiIndex和更先進的索引文件。 有關某些高級策略,請參見本食譜。 不同的選擇索引 對象選擇具有許多用戶請求的添加項,以支持更明確的基於位置的索引。熊貓現在支持三種類型的多軸索引。 .loc主要基於標簽,但也可以與布爾數組一起使用。找不到物品時.loc將升高KeyError。允許的輸入為: 單個標簽,例如5或'a'(請注意,它5被解釋為索引的 標簽。此用法不是沿索引的整數位置。) 標簽列表或標簽數組。['a', 'b', 'c'] 帶標簽的切片對象'a':'f'(注意,相反普通的Python片,都開始和停止都包括在內,存在於索引時!見切片用標簽)。 布爾數組 一個callable帶有一個參數的函數(調用Series或DataFrame),並且返回用於索引的有效輸出(上述之一)。 0.18.1版中的新功能。 有關更多信息,請參見按標簽選擇。 .iloc主要是整數位置(來自0於 length-1所述軸線的),但也可以用布爾陣列使用。 如果請求的索引器超出邊界,.iloc則將增加IndexError,但切片索引器除外,該索引允許越界索引。(這符合Python / NumPy slice 語義)。允許的輸入為: 整數,例如5。 整數列表或數組。[4, 3, 0] 具有int的slice對象1:7。 布爾數組。 一個callable帶有一個參數的函數(調用Series或DataFrame),並且返回用於索引的有效輸出(上述之一)。 0.18.1版中的新功能。 請參閱“ 按位置選擇”,“ 高級索引編制”和“ 高級層次結構”。 .loc,.iloc以及[]索引也可以接受callable作為索引器。有關更多信息,請參見“ 按呼叫選擇”。 從具有多軸選擇的對象中獲取值使用以下符號(.loc作為示例,但以下內容同樣適用.iloc)。任何軸訪問器都可以為null slice :。軸冷落的規格被假定為:,例如p.loc['a']相當於 。p.loc['a', :, :] 對象類型 索引器 系列 s.loc[indexer] 數據框 df.loc[row_indexer,column_indexer] 基礎 正如在上一節介紹數據結構時所提到的那樣,使用[](__getitem__ 對於熟悉在Python中實現類行為的人員而言)進行索引的主要功能是選擇低維切片。下表顯示了使用索引pandas對象時的返回類型值[]: 對象類型 選拔 返回值類型 系列 series[label] 標量值 數據框 frame[colname] Series 對應於姓 在這里,我們構造了一個簡單的時間序列數據集,用於說明索引功能: In [1]: dates = pd.date_range('1/1/2000', periods=8) In [2]: df = pd.DataFrame(np.random.randn(8, 4), ...: index=dates, columns=['A', 'B', 'C', 'D']) ...: In [3]: df Out[3]: A B C D 2000-01-01 0.469112 -0.282863 -1.509059 -1.135632 2000-01-02 1.212112 -0.173215 0.119209 -1.044236 2000-01-03 -0.861849 -2.104569 -0.494929 1.071804 2000-01-04 0.721555 -0.706771 -1.039575 0.271860 2000-01-05 -0.424972 0.567020 0.276232 -1.087401 2000-01-06 -0.673690 0.113648 -1.478427 0.524988 2000-01-07 0.404705 0.577046 -1.715002 -1.039268 2000-01-08 -0.370647 -1.157892 -1.344312 0.844885 注意 除非特別說明,否則索引功能都不是特定於時間序列的。 因此,如上所述,我們使用的是最基本的索引[]: In [4]: s = df['A'] In [5]: s[dates[5]] Out[5]: -0.6736897080883706 您可以將列列表傳遞[]給以該順序選擇列。如果DataFrame中不包含列,則將引發異常。也可以以這種方式設置多列: In [6]: df Out[6]: A B C D 2000-01-01 0.469112 -0.282863 -1.509059 -1.135632 2000-01-02 1.212112 -0.173215 0.119209 -1.044236 2000-01-03 -0.861849 -2.104569 -0.494929 1.071804 2000-01-04 0.721555 -0.706771 -1.039575 0.271860 2000-01-05 -0.424972 0.567020 0.276232 -1.087401 2000-01-06 -0.673690 0.113648 -1.478427 0.524988 2000-01-07 0.404705 0.577046 -1.715002 -1.039268 2000-01-08 -0.370647 -1.157892 -1.344312 0.844885 In [7]: df[['B', 'A']] = df[['A', 'B']] In [8]: df Out[8]: A B C D 2000-01-01 -0.282863 0.469112 -1.509059 -1.135632 2000-01-02 -0.173215 1.212112 0.119209 -1.044236 2000-01-03 -2.104569 -0.861849 -0.494929 1.071804 2000-01-04 -0.706771 0.721555 -1.039575 0.271860 2000-01-05 0.567020 -0.424972 0.276232 -1.087401 2000-01-06 0.113648 -0.673690 -1.478427 0.524988 2000-01-07 0.577046 0.404705 -1.715002 -1.039268 2000-01-08 -1.157892 -0.370647 -1.344312 0.844885 您可能會發現這對於將轉換(就地)應用於列的子集很有用。 警告 設置Series和DataFrame從.loc和中時,pandas會對齊所有軸.iloc。 這不會修改,df因為列對齊是在賦值之前。 In [9]: df[['A', 'B']] Out[9]: A B 2000-01-01 -0.282863 0.469112 2000-01-02 -0.173215 1.212112 2000-01-03 -2.104569 -0.861849 2000-01-04 -0.706771 0.721555 2000-01-05 0.567020 -0.424972 2000-01-06 0.113648 -0.673690 2000-01-07 0.577046 0.404705 2000-01-08 -1.157892 -0.370647 In [10]: df.loc[:, ['B', 'A']] = df[['A', 'B']] In [11]: df[['A', 'B']] Out[11]: A B 2000-01-01 -0.282863 0.469112 2000-01-02 -0.173215 1.212112 2000-01-03 -2.104569 -0.861849 2000-01-04 -0.706771 0.721555 2000-01-05 0.567020 -0.424972 2000-01-06 0.113648 -0.673690 2000-01-07 0.577046 0.404705 2000-01-08 -1.157892 -0.370647 交換列值的正確方法是使用原始值: In [12]: df.loc[:, ['B', 'A']] = df[['A', 'B']].to_numpy() In [13]: df[['A', 'B']] Out[13]: A B 2000-01-01 0.469112 -0.282863 2000-01-02 1.212112 -0.173215 2000-01-03 -0.861849 -2.104569 2000-01-04 0.721555 -0.706771 2000-01-05 -0.424972 0.567020 2000-01-06 -0.673690 0.113648 2000-01-07 0.404705 0.577046 2000-01-08 -0.370647 -1.157892 屬性訪問 您可以直接將Series或上的索引DataFrame作為屬性訪問: In [14]: sa = pd.Series([1, 2, 3], index=list('abc')) In [15]: dfa = df.copy() In [16]: sa.b Out[16]: 2 In [17]: dfa.A Out[17]: 2000-01-01 0.469112 2000-01-02 1.212112 2000-01-03 -0.861849 2000-01-04 0.721555 2000-01-05 -0.424972 2000-01-06 -0.673690 2000-01-07 0.404705 2000-01-08 -0.370647 Freq: D, Name: A, dtype: float64 In [18]: sa.a = 5 In [19]: sa Out[19]: a 5 b 2 c 3 dtype: int64 In [20]: dfa.A = list(range(len(dfa.index))) # ok if A already exists In [21]: dfa Out[21]: A B C D 2000-01-01 0 -0.282863 -1.509059 -1.135632 2000-01-02 1 -0.173215 0.119209 -1.044236 2000-01-03 2 -2.104569 -0.494929 1.071804 2000-01-04 3 -0.706771 -1.039575 0.271860 2000-01-05 4 0.567020 0.276232 -1.087401 2000-01-06 5 0.113648 -1.478427 0.524988 2000-01-07 6 0.577046 -1.715002 -1.039268 2000-01-08 7 -1.157892 -1.344312 0.844885 In [22]: dfa['A'] = list(range(len(dfa.index))) # use this form to create a new column In [23]: dfa Out[23]: A B C D 2000-01-01 0 -0.282863 -1.509059 -1.135632 2000-01-02 1 -0.173215 0.119209 -1.044236 2000-01-03 2 -2.104569 -0.494929 1.071804 2000-01-04 3 -0.706771 -1.039575 0.271860 2000-01-05 4 0.567020 0.276232 -1.087401 2000-01-06 5 0.113648 -1.478427 0.524988 2000-01-07 6 0.577046 -1.715002 -1.039268 2000-01-08 7 -1.157892 -1.344312 0.844885 警告 僅當index元素是有效的Python標識符(例如s.1,不允許使用)時,才能使用此訪問權限。有關有效標識符的說明,請參見此處。 如果屬性與現有方法名稱沖突(例如s.min不允許),則該屬性將不可用。 同樣,該屬性將不可用,如果它與下列任何名單的沖突:index, major_axis,minor_axis,items。 在任何一種情況下,標准索引仍然可以工作,例如s['1'],s['min']和s['index']將訪問相應的元素或列。 如果使用的是IPython環境,則也可以使用制表符補全來查看這些可訪問的屬性。 您還可以將分配dict給的一行DataFrame: In [24]: x = pd.DataFrame({'x': [1, 2, 3], 'y': [3, 4, 5]}) In [25]: x.iloc[1] = {'x': 9, 'y': 99} In [26]: x Out[26]: x y 0 1 3 1 9 99 2 3 5 您可以使用屬性訪問來修改Series或DataFrame列的現有元素,但要小心;如果您嘗試使用屬性訪問來創建新列,則它將創建一個新屬性而不是一個新列。在0.21.0及更高版本中,這將引發UserWarning: In [1]: df = pd.DataFrame({'one': [1., 2., 3.]}) In [2]: df.two = [4, 5, 6] UserWarning: Pandas doesn't allow Series to be assigned into nonexistent columns - see https://pandas.pydata.org/pandas-docs/stable/indexing.html#attribute_access In [3]: df Out[3]: one 0 1.0 1 2.0 2 3.0 切片范圍 在“ 按位置選擇”部分詳細介紹了該.iloc方法,介紹了沿任意軸切片范圍的最可靠,最一致的方法。現在,我們解釋使用[]運算符進行切片的語義。 使用Series時,語法與ndarray完全一樣,返回值的一部分和相應的標簽: In [27]: s[:5] Out[27]: 2000-01-01 0.469112 2000-01-02 1.212112 2000-01-03 -0.861849 2000-01-04 0.721555 2000-01-05 -0.424972 Freq: D, Name: A, dtype: float64 In [28]: s[::2] Out[28]: 2000-01-01 0.469112 2000-01-03 -0.861849 2000-01-05 -0.424972 2000-01-07 0.404705 Freq: 2D, Name: A, dtype: float64 In [29]: s[::-1] Out[29]: 2000-01-08 -0.370647 2000-01-07 0.404705 2000-01-06 -0.673690 2000-01-05 -0.424972 2000-01-04 0.721555 2000-01-03 -0.861849 2000-01-02 1.212112 2000-01-01 0.469112 Freq: -1D, Name: A, dtype: float64 請注意,設置同樣適用: In [30]: s2 = s.copy() In [31]: s2[:5] = 0 In [32]: s2 Out[32]: 2000-01-01 0.000000 2000-01-02 0.000000 2000-01-03 0.000000 2000-01-04 0.000000 2000-01-05 0.000000 2000-01-06 -0.673690 2000-01-07 0.404705 2000-01-08 -0.370647 Freq: D, Name: A, dtype: float64 使用DataFrame時,[] 在rows中對切片進行切片。由於這是一種常見的操作,因此在很大程度上是為了方便而提供的。 In [33]: df[:3] Out[33]: A B C D 2000-01-01 0.469112 -0.282863 -1.509059 -1.135632 2000-01-02 1.212112 -0.173215 0.119209 -1.044236 2000-01-03 -0.861849 -2.104569 -0.494929 1.071804 In [34]: df[::-1] Out[34]: A B C D 2000-01-08 -0.370647 -1.157892 -1.344312 0.844885 2000-01-07 0.404705 0.577046 -1.715002 -1.039268 2000-01-06 -0.673690 0.113648 -1.478427 0.524988 2000-01-05 -0.424972 0.567020 0.276232 -1.087401 2000-01-04 0.721555 -0.706771 -1.039575 0.271860 2000-01-03 -0.861849 -2.104569 -0.494929 1.071804 2000-01-02 1.212112 -0.173215 0.119209 -1.044236 2000-01-01 0.469112 -0.282863 -1.509059 -1.135632 按標簽選擇 警告 為設置操作返回副本還是參考,可能取決於上下文。這有時被稱為,應該避免。請參閱返回視圖與復制。chained assignment 警告 .loc當您提供與索引類型不兼容(或可轉換)的切片器時,它是嚴格的。例如在中使用整數DatetimeIndex。這些將引發一個TypeError。 In [35]: dfl = pd.DataFrame(np.random.randn(5, 4), ....: columns=list('ABCD'), ....: index=pd.date_range('20130101', periods=5)) ....: In [36]: dfl Out[36]: A B C D 2013-01-01 1.075770 -0.109050 1.643563 -1.469388 2013-01-02 0.357021 -0.674600 -1.776904 -0.968914 2013-01-03 -1.294524 0.413738 0.276662 -0.472035 2013-01-04 -0.013960 -0.362543 -0.006154 -0.923061 2013-01-05 0.895717 0.805244 -1.206412 2.565646 In [4]: dfl.loc[2:3] TypeError: cannot do slice indexing on <class 'pandas.tseries.index.DatetimeIndex'> with these indexers [2] of <type 'int'> 切片中的字符串喜歡可以轉換為索引的類型並導致自然切片。 In [37]: dfl.loc['20130102':'20130104'] Out[37]: A B C D 2013-01-02 0.357021 -0.674600 -1.776904 -0.968914 2013-01-03 -1.294524 0.413738 0.276662 -0.472035 2013-01-04 -0.013960 -0.362543 -0.006154 -0.923061 警告 從0.21.0開始,pandas將顯示FutureWarningif索引,其中包含缺少標簽的列表。在未來,這將引發KeyError。請參見類似列表的列表。不推薦使用在列表中缺少鍵的loc。 熊貓提供了一整套方法,以便具有純基於標簽的索引。這是一個基於嚴格包含的協議。要求的每個標簽都必須在索引中,否則KeyError將引發a。切片時,如果索引中存在起始邊界和終止邊界,則都將包括在內。整數是有效的標簽,但它們引用的是標簽,而不是position。 該.loc屬性是主要的訪問方法。以下是有效輸入: 單個標簽,例如5或'a'(請注意,它5被解釋為索引的標簽。此用法不是沿索引的整數位置。) 標簽列表或標簽數組。['a', 'b', 'c'] 帶標簽的切片對象'a':'f'(注意,相反普通的Python片,都開始和停止都包括在內,存在於索引時!見切片用標簽)。 布爾數組。 A callable,請參見按可調用選擇。 In [38]: s1 = pd.Series(np.random.randn(6), index=list('abcdef')) In [39]: s1 Out[39]: a 1.431256 b 1.340309 c -1.170299 d -0.226169 e 0.410835 f 0.813850 dtype: float64 In [40]: s1.loc['c':] Out[40]: c -1.170299 d -0.226169 e 0.410835 f 0.813850 dtype: float64 In [41]: s1.loc['b'] Out[41]: 1.3403088497993827 請注意,設置同樣適用: In [42]: s1.loc['c':] = 0 In [43]: s1 Out[43]: a 1.431256 b 1.340309 c 0.000000 d 0.000000 e 0.000000 f 0.000000 dtype: float64 使用DataFrame: In [44]: df1 = pd.DataFrame(np.random.randn(6, 4), ....: index=list('abcdef'), ....: columns=list('ABCD')) ....: In [45]: df1 Out[45]: A B C D a 0.132003 -0.827317 -0.076467 -1.187678 b 1.130127 -1.436737 -1.413681 1.607920 c 1.024180 0.569605 0.875906 -2.211372 d 0.974466 -2.006747 -0.410001 -0.078638 e 0.545952 -1.219217 -1.226825 0.769804 f -1.281247 -0.727707 -0.121306 -0.097883 In [46]: df1.loc[['a', 'b', 'd'], :] Out[46]: A B C D a 0.132003 -0.827317 -0.076467 -1.187678 b 1.130127 -1.436737 -1.413681 1.607920 d 0.974466 -2.006747 -0.410001 -0.078638 通過標簽切片訪問: In [47]: df1.loc['d':, 'A':'C'] Out[47]: A B C d 0.974466 -2.006747 -0.410001 e 0.545952 -1.219217 -1.226825 f -1.281247 -0.727707 -0.121306 要使用標簽(相當於df.xs('a'))獲取橫截面: In [48]: df1.loc['a'] Out[48]: A 0.132003 B -0.827317 C -0.076467 D -1.187678 Name: a, dtype: float64 要使用布爾數組獲取值: In [49]: df1.loc['a'] > 0 Out[49]: A True B False C False D False Name: a, dtype: bool In [50]: df1.loc[:, df1.loc['a'] > 0] Out[50]: A a 0.132003 b 1.130127 c 1.024180 d 0.974466 e 0.545952 f -1.281247 為了顯式地獲取值(等效於deprecated df.get_value('a','A')): # this is also equivalent to ``df1.at['a','A']`` In [51]: df1.loc['a', 'A'] Out[51]: 0.13200317033032932 帶標簽切片 .loc與切片一起使用時,如果索引中同時包含開始標簽和停止標簽,則返回位於兩者之間的元素(包括它們): In [52]: s = pd.Series(list('abcde'), index=[0, 3, 2, 5, 4]) In [53]: s.loc[3:5] Out[53]: 3 b 2 c 5 d dtype: object 如果這兩個中的至少一個不存在的,但該指數進行排序,並能對啟動和停止的標簽進行比較,然后切片仍然會按預期方式工作,通過選擇的標簽,其排名在兩者之間: In [54]: s.sort_index() Out[54]: 0 a 2 c 3 b 4 e 5 d dtype: object In [55]: s.sort_index().loc[1:6] Out[55]: 2 c 3 b 4 e 5 d dtype: object 但是,如果不存在兩者中的至少一個並且未對索引進行排序,則將引發錯誤(因為這樣做會導致計算量大,並且可能對混合類型索引造成歧義)。例如,在上面的示例中,s.loc[1:6]將上升KeyError。 按位置選擇 警告 為設置操作返回副本還是參考,可能取決於上下文。這有時被稱為,應該避免。請參閱返回視圖與復制。chained assignment Pandas提供了一組方法,以便獲得純粹基於整數的索引。語義嚴格遵循Python和NumPy切片。這些正在0-based索引。當切片,開始結合被包含,而上限是排除。嘗試使用非整數,即使有效標簽也將引發IndexError。 該.iloc屬性是主要的訪問方法。以下是有效輸入: 整數,例如5。 整數列表或數組。[4, 3, 0] 具有int的slice對象1:7。 布爾數組。 A callable,請參見按可調用選擇。 In [56]: s1 = pd.Series(np.random.randn(5), index=list(range(0, 10, 2))) In [57]: s1 Out[57]: 0 0.695775 2 0.341734 4 0.959726 6 -1.110336 8 -0.619976 dtype: float64 In [58]: s1.iloc[:3] Out[58]: 0 0.695775 2 0.341734 4 0.959726 dtype: float64 In [59]: s1.iloc[3] Out[59]: -1.110336102891167 請注意,設置同樣適用: In [60]: s1.iloc[:3] = 0 In [61]: s1 Out[61]: 0 0.000000 2 0.000000 4 0.000000 6 -1.110336 8 -0.619976 dtype: float64 使用DataFrame: In [62]: df1 = pd.DataFrame(np.random.randn(6, 4), ....: index=list(range(0, 12, 2)), ....: columns=list(range(0, 8, 2))) ....: In [63]: df1 Out[63]: 0 2 4 6 0 0.149748 -0.732339 0.687738 0.176444 2 0.403310 -0.154951 0.301624 -2.179861 4 -1.369849 -0.954208 1.462696 -1.743161 6 -0.826591 -0.345352 1.314232 0.690579 8 0.995761 2.396780 0.014871 3.357427 10 -0.317441 -1.236269 0.896171 -0.487602 通過整數切片選擇: In [64]: df1.iloc[:3] Out[64]: 0 2 4 6 0 0.149748 -0.732339 0.687738 0.176444 2 0.403310 -0.154951 0.301624 -2.179861 4 -1.369849 -0.954208 1.462696 -1.743161 In [65]: df1.iloc[1:5, 2:4] Out[65]: 4 6 2 0.301624 -2.179861 4 1.462696 -1.743161 6 1.314232 0.690579 8 0.014871 3.357427 通過整數列表選擇: In [66]: df1.iloc[[1, 3, 5], [1, 3]] Out[66]: 2 6 2 -0.154951 -2.179861 6 -0.345352 0.690579 10 -1.236269 -0.487602 In [67]: df1.iloc[1:3, :] Out[67]: 0 2 4 6 2 0.403310 -0.154951 0.301624 -2.179861 4 -1.369849 -0.954208 1.462696 -1.743161 In [68]: df1.iloc[:, 1:3] Out[68]: 2 4 0 -0.732339 0.687738 2 -0.154951 0.301624 4 -0.954208 1.462696 6 -0.345352 1.314232 8 2.396780 0.014871 10 -1.236269 0.896171 # this is also equivalent to ``df1.iat[1,1]`` In [69]: df1.iloc[1, 1] Out[69]: -0.1549507744249032 要使用整數位置(等於df.xs(1))獲取橫截面: In [70]: df1.iloc[1] Out[70]: 0 0.403310 2 -0.154951 4 0.301624 6 -2.179861 Name: 2, dtype: float64 超出范圍切片索引的處理方式與Python / Numpy中一樣。 # these are allowed in python/numpy. In [71]: x = list('abcdef') In [72]: x Out[72]: ['a', 'b', 'c', 'd', 'e', 'f'] In [73]: x[4:10] Out[73]: ['e', 'f'] In [74]: x[8:10] Out[74]: [] In [75]: s = pd.Series(x) In [76]: s Out[76]: 0 a 1 b 2 c 3 d 4 e 5 f dtype: object In [77]: s.iloc[4:10] Out[77]: 4 e 5 f dtype: object In [78]: s.iloc[8:10] Out[78]: Series([], dtype: object) 請注意,使用超出范圍的切片可能會導致一個空軸(例如,返回一個空的DataFrame)。 In [79]: dfl = pd.DataFrame(np.random.randn(5, 2), columns=list('AB')) In [80]: dfl Out[80]: A B 0 -0.082240 -2.182937 1 0.380396 0.084844 2 0.432390 1.519970 3 -0.493662 0.600178 4 0.274230 0.132885 In [81]: dfl.iloc[:, 2:3] Out[81]: Empty DataFrame Columns: [] Index: [0, 1, 2, 3, 4] In [82]: dfl.iloc[:, 1:3] Out[82]: B 0 -2.182937 1 0.084844 2 1.519970 3 0.600178 4 0.132885 In [83]: dfl.iloc[4:6] Out[83]: A B 4 0.27423 0.132885 超出范圍的單個索引器將引發IndexError。任何元素超出范圍的索引器列表都會引發 IndexError。 >>> dfl.iloc[[4, 5, 6]] IndexError: positional indexers are out-of-bounds >>> dfl.iloc[:, 4] IndexError: single positional indexer is out-of-bounds 通過可調用選擇 0.18.1版中的新功能。 .loc,.iloc以及[]索引也可以接受callable作為索引器。在callable必須與一個參數(呼叫系列或數據幀)返回的有效輸出索引功能。 In [84]: df1 = pd.DataFrame(np.random.randn(6, 4), ....: index=list('abcdef'), ....: columns=list('ABCD')) ....: In [85]: df1 Out[85]: A B C D a -0.023688 2.410179 1.450520 0.206053 b -0.251905 -2.213588 1.063327 1.266143 c 0.299368 -0.863838 0.408204 -1.048089 d -0.025747 -0.988387 0.094055 1.262731 e 1.289997 0.082423 -0.055758 0.536580 f -0.489682 0.369374 -0.034571 -2.484478 In [86]: df1.loc[lambda df: df.A > 0, :] Out[86]: A B C D c 0.299368 -0.863838 0.408204 -1.048089 e 1.289997 0.082423 -0.055758 0.536580 In [87]: df1.loc[:, lambda df: ['A', 'B']] Out[87]: A B a -0.023688 2.410179 b -0.251905 -2.213588 c 0.299368 -0.863838 d -0.025747 -0.988387 e 1.289997 0.082423 f -0.489682 0.369374 In [88]: df1.iloc[:, lambda df: [0, 1]] Out[88]: A B a -0.023688 2.410179 b -0.251905 -2.213588 c 0.299368 -0.863838 d -0.025747 -0.988387 e 1.289997 0.082423 f -0.489682 0.369374 In [89]: df1[lambda df: df.columns[0]] Out[89]: a -0.023688 b -0.251905 c 0.299368 d -0.025747 e 1.289997 f -0.489682 Name: A, dtype: float64 您可以在中使用可調用索引Series。 In [90]: df1.A.loc[lambda s: s > 0] Out[90]: c 0.299368 e 1.289997 Name: A, dtype: float64 使用這些方法/索引器,您可以鏈接數據選擇操作,而無需使用臨時變量。 In [91]: bb = pd.read_csv('data/baseball.csv', index_col='id') In [92]: (bb.groupby(['year', 'team']).sum() ....: .loc[lambda df: df.r > 100]) ....: Out[92]: stint g ab r h X2b ... so ibb hbp sh sf gidp year team ... 2007 CIN 6 379 745 101 203 35 ... 127.0 14.0 1.0 1.0 15.0 18.0 DET 5 301 1062 162 283 54 ... 176.0 3.0 10.0 4.0 8.0 28.0 HOU 4 311 926 109 218 47 ... 212.0 3.0 9.0 16.0 6.0 17.0 LAN 11 413 1021 153 293 61 ... 141.0 8.0 9.0 3.0 8.0 29.0 NYN 13 622 1854 240 509 101 ... 310.0 24.0 23.0 18.0 15.0 48.0 SFN 5 482 1305 198 337 67 ... 188.0 51.0 8.0 16.0 6.0 41.0 TEX 2 198 729 115 200 40 ... 140.0 4.0 5.0 2.0 8.0 16.0 TOR 4 459 1408 187 378 96 ... 265.0 16.0 12.0 4.0 16.0 38.0 [8 rows x 18 columns] IX Indexer已棄用 警告 在0.20.0開始,.ix索引器已被棄用,贊成更加嚴格.iloc 和.loc索引。 .ix在推斷用戶想要做什么方面提供了很多魔力。也就是說,.ix可以根據索引的數據類型決定是否通過標簽對位置進行索引。多年來,這引起了相當多的用戶混亂。 推薦的索引編制方法是: .loc如果要標記索引。 .iloc如果要位置索引。 In [93]: dfd = pd.DataFrame({'A': [1, 2, 3], ....: 'B': [4, 5, 6]}, ....: index=list('abc')) ....: In [94]: dfd Out[94]: A B a 1 4 b 2 5 c 3 6 以前的行為,您希望從“ A”列的索引中獲取第0個元素和第2個元素。 In [3]: dfd.ix[[0, 2], 'A'] Out[3]: a 1 c 3 Name: A, dtype: int64 使用.loc。在這里,我們將從索引中選擇適當的索引,然后使用標簽索引。 In [95]: dfd.loc[dfd.index[[0, 2]], 'A'] Out[95]: a 1 c 3 Name: A, dtype: int64 也可以使用來表達這一點.iloc,方法是明確獲取索引器上的位置,並使用 位置索引來選擇事物。 In [96]: dfd.iloc[[0, 2], dfd.columns.get_loc('A')] Out[96]: a 1 c 3 Name: A, dtype: int64 要獲取多個索引器,請使用.get_indexer: In [97]: dfd.iloc[[0, 2], dfd.columns.get_indexer(['A', 'B'])] Out[97]: A B a 1 4 c 3 6 不建議使用帶有缺少標簽的列表建立索引 警告 從0.21.0開始,不推薦使用.loc或[]帶有一個或多個缺少標簽的列表,而推薦使用.reindex。 在以前的版本中,.loc[list-of-labels]只要找到至少一個鍵,使用就可以工作(否則會引發KeyError)。不建議使用此行為,它將顯示一條警告消息,指向此部分。推薦的替代方法是使用.reindex()。 例如。 In [98]: s = pd.Series([1, 2, 3]) In [99]: s Out[99]: 0 1 1 2 2 3 dtype: int64 找到所有鍵的選擇保持不變。 In [100]: s.loc[[1, 2]] Out[100]: 1 2 2 3 dtype: int64 以前的行為 In [4]: s.loc[[1, 2, 3]] Out[4]: 1 2.0 2 3.0 3 NaN dtype: float64 當前行為 In [4]: s.loc[[1, 2, 3]] Passing list-likes to .loc with any non-matching elements will raise KeyError in the future, you can use .reindex() as an alternative. See the documentation here: http://pandas.pydata.org/pandas-docs/stable/indexing.html#deprecate-loc-reindex-listlike Out[4]: 1 2.0 2 3.0 3 NaN dtype: float64 重建索引 實現選擇潛在未找到元素的慣用方式是通過.reindex()。另請參閱“ 重新索引編制 ”部分。 In [101]: s.reindex([1, 2, 3]) Out[101]: 1 2.0 2 3.0 3 NaN dtype: float64 另外,如果您只想選擇有效的密鑰,則以下是慣用且有效的;保證保留選擇的dtype。 In [102]: labels = [1, 2, 3] In [103]: s.loc[s.index.intersection(labels)] Out[103]: 1 2 2 3 dtype: int64 索引重復會產生.reindex(): In [104]: s = pd.Series(np.arange(4), index=['a', 'a', 'b', 'c']) In [105]: labels = ['c', 'd'] In [17]: s.reindex(labels) ValueError: cannot reindex from a duplicate axis 通常,您可以將所需的標簽與當前軸相交,然后重新索引。 In [106]: s.loc[s.index.intersection(labels)].reindex(labels) Out[106]: c 3.0 d NaN dtype: float64 但是,如果您生成的索引重復,這仍然會增加。 In [41]: labels = ['a', 'd'] In [42]: s.loc[s.index.intersection(labels)].reindex(labels) ValueError: cannot reindex from a duplicate axis 選擇隨機樣本 使用該sample()方法從Series或DataFrame中隨機選擇行或列。該方法默認情況下將對行進行采樣,並接受要返回的特定數量的行/列,或一部分行。 In [107]: s = pd.Series([0, 1, 2, 3, 4, 5]) # When no arguments are passed, returns 1 row. In [108]: s.sample() Out[108]: 4 4 dtype: int64 # One may specify either a number of rows: In [109]: s.sample(n=3) Out[109]: 0 0 4 4 1 1 dtype: int64 # Or a fraction of the rows: In [110]: s.sample(frac=0.5) Out[110]: 5 5 3 3 1 1 dtype: int64 默認情況下,sample將最多返回每一行一次,但也可以使用以下replace選項進行替換采樣: In [111]: s = pd.Series([0, 1, 2, 3, 4, 5]) # Without replacement (default): In [112]: s.sample(n=6, replace=False) Out[112]: 0 0 1 1 5 5 3 3 2 2 4 4 dtype: int64 # With replacement: In [113]: s.sample(n=6, replace=True) Out[113]: 0 0 4 4 3 3 2 2 4 4 4 4 dtype: int64 默認情況下,每行被選擇的概率相同,但是如果您希望行具有不同的概率,則可以將sample函數采樣權重傳遞為 weights。這些權重可以是列表,NumPy數組或系列,但是它們的長度必須與要采樣的對象相同。缺少的值將被視為權重為零,並且不允許使用inf值。如果權重不等於1,將通過將所有權重除以權重之和來重新歸一化。例如: In [114]: s = pd.Series([0, 1, 2, 3, 4, 5]) In [115]: example_weights = [0, 0, 0.2, 0.2, 0.2, 0.4] In [116]: s.sample(n=3, weights=example_weights) Out[116]: 5 5 4 4 3 3 dtype: int64 # Weights will be re-normalized automatically In [117]: example_weights2 = [0.5, 0, 0, 0, 0, 0] In [118]: s.sample(n=1, weights=example_weights2) Out[118]: 0 0 dtype: int64 應用於DataFrame時,只需將列名作為字符串傳遞,就可以將DataFrame的一列用作采樣權重(前提是要對行而不是列進行采樣)。 In [119]: df2 = pd.DataFrame({'col1': [9, 8, 7, 6], .....: 'weight_column': [0.5, 0.4, 0.1, 0]}) .....: In [120]: df2.sample(n=3, weights='weight_column') Out[120]: col1 weight_column 1 8 0.4 0 9 0.5 2 7 0.1 sample還允許用戶使用axis參數對列而不是行進行采樣。 In [121]: df3 = pd.DataFrame({'col1': [1, 2, 3], 'col2': [2, 3, 4]}) In [122]: df3.sample(n=1, axis=1) Out[122]: col1 0 1 1 2 2 3 最后,還可以sample使用random_state參數為的隨機數生成器設置種子,該種子將接受整數(作為種子)或NumPy RandomState對象。 In [123]: df4 = pd.DataFrame({'col1': [1, 2, 3], 'col2': [2, 3, 4]}) # With a given seed, the sample will always draw the same rows. In [124]: df4.sample(n=2, random_state=2) Out[124]: col1 col2 2 3 4 1 2 3 In [125]: df4.sample(n=2, random_state=2) Out[125]: col1 col2 2 3 4 1 2 3 放大設置 .loc/[]當為該軸設置不存在的鍵時,這些操作可以執行放大操作。 在這種Series情況下,這實際上是附加操作。 In [126]: se = pd.Series([1, 2, 3]) In [127]: se Out[127]: 0 1 1 2 2 3 dtype: int64 In [128]: se[5] = 5. In [129]: se Out[129]: 0 1.0 1 2.0 2 3.0 5 5.0 dtype: float64 阿DataFrame可以在任一軸通過被放大.loc。 In [130]: dfi = pd.DataFrame(np.arange(6).reshape(3, 2), .....: columns=['A', 'B']) .....: In [131]: dfi Out[131]: A B 0 0 1 1 2 3 2 4 5 In [132]: dfi.loc[:, 'C'] = dfi.loc[:, 'A'] In [133]: dfi Out[133]: A B C 0 0 1 0 1 2 3 2 2 4 5 4 這就像對的append操作DataFrame。 In [134]: dfi.loc[3] = 5 In [135]: dfi Out[135]: A B C 0 0 1 0 1 2 3 2 2 4 5 4 3 5 5 5 快速獲取和設置標量值 由於with索引[]必須處理很多情況(單標簽訪問,切片,布爾索引等),因此要弄清楚您要的內容有一點開銷。如果只想訪問標量值,最快的方法是使用at和iat方法,它們在所有數據結構上實現。 與相似loc,at提供基於標簽的標量查找,而類似於iat提供基於整數的查找iloc In [136]: s.iat[5] Out[136]: 5 In [137]: df.at[dates[5], 'A'] Out[137]: -0.6736897080883706 In [138]: df.iat[3, 0] Out[138]: 0.7215551622443669 您也可以使用這些相同的索引器進行設置。 In [139]: df.at[dates[5], 'E'] = 7 In [140]: df.iat[3, 0] = 7 at 如果缺少索引器,可能會像上面一樣就地放大對象。 In [141]: df.at[dates[-1] + pd.Timedelta('1 day'), 0] = 7 In [142]: df Out[142]: A B C D E 0 2000-01-01 0.469112 -0.282863 -1.509059 -1.135632 NaN NaN 2000-01-02 1.212112 -0.173215 0.119209 -1.044236 NaN NaN 2000-01-03 -0.861849 -2.104569 -0.494929 1.071804 NaN NaN 2000-01-04 7.000000 -0.706771 -1.039575 0.271860 NaN NaN 2000-01-05 -0.424972 0.567020 0.276232 -1.087401 NaN NaN 2000-01-06 -0.673690 0.113648 -1.478427 0.524988 7.0 NaN 2000-01-07 0.404705 0.577046 -1.715002 -1.039268 NaN NaN 2000-01-08 -0.370647 -1.157892 -1.344312 0.844885 NaN NaN 2000-01-09 NaN NaN NaN NaN NaN 7.0 布爾索引 另一個常見的操作是使用布爾向量來過濾數據。運算符是:|for or,&for and和~for not。這些必須通過使用括號中,由於默認Python會計算表達式如被分組為 ,而所希望的評價順序是 。df.A > 2 & df.B < 3df.A > (2 & df.B) < 3(df.A > 2) & (df.B < 3) 使用布爾向量為Series編制索引的方式與NumPy ndarray完全相同: In [143]: s = pd.Series(range(-3, 4)) In [144]: s Out[144]: 0 -3 1 -2 2 -1 3 0 4 1 5 2 6 3 dtype: int64 In [145]: s[s > 0] Out[145]: 4 1 5 2 6 3 dtype: int64 In [146]: s[(s < -1) | (s > 0.5)] Out[146]: 0 -3 1 -2 4 1 5 2 6 3 dtype: int64 In [147]: s[~(s < 0)] Out[147]: 3 0 4 1 5 2 6 3 dtype: int64 您可以使用布爾向量從DataFrame中選擇行,該布爾向量的長度與DataFrame的索引相同(例如,從DataFrame的列之一派生的值): In [148]: df[df['A'] > 0] Out[148]: A B C D E 0 2000-01-01 0.469112 -0.282863 -1.509059 -1.135632 NaN NaN 2000-01-02 1.212112 -0.173215 0.119209 -1.044236 NaN NaN 2000-01-04 7.000000 -0.706771 -1.039575 0.271860 NaN NaN 2000-01-07 0.404705 0.577046 -1.715002 -1.039268 NaN NaN 列表推導和mapSeries方法也可以用於產生更復雜的條件: In [149]: df2 = pd.DataFrame({'a': ['one', 'one', 'two', 'three', 'two', 'one', 'six'], .....: 'b': ['x', 'y', 'y', 'x', 'y', 'x', 'x'], .....: 'c': np.random.randn(7)}) .....: # only want 'two' or 'three' In [150]: criterion = df2['a'].map(lambda x: x.startswith('t')) In [151]: df2[criterion] Out[151]: a b c 2 two y 0.041290 3 three x 0.361719 4 two y -0.238075 # equivalent but slower In [152]: df2[[x.startswith('t') for x in df2['a']]] Out[152]: a b c 2 two y 0.041290 3 three x 0.361719 4 two y -0.238075 # Multiple criteria In [153]: df2[criterion & (df2['b'] == 'x')] Out[153]: a b c 3 three x 0.361719 隨着選擇方法通過標簽選擇,選擇的位置,和高級索引你可能比一個軸使用布爾向量與其他索引表達式中合並一起更選擇。 In [154]: df2.loc[criterion & (df2['b'] == 'x'), 'b':'c'] Out[154]: b c 3 x 0.361719 用isin索引 考慮isin()方法Series,該方法將返回一個布爾向量,該布爾向量Series在傳遞的列表中存在的任何元素處都為真。這使您可以選擇一行或多列具有所需值的行: In [155]: s = pd.Series(np.arange(5), index=np.arange(5)[::-1], dtype='int64') In [156]: s Out[156]: 4 0 3 1 2 2 1 3 0 4 dtype: int64 In [157]: s.isin([2, 4, 6]) Out[157]: 4 False 3 False 2 True 1 False 0 True dtype: bool In [158]: s[s.isin([2, 4, 6])] Out[158]: 2 2 0 4 dtype: int64 相同的方法可用於Index對象,並且在您不知道實際上找到了哪個標簽的情況下很有用: In [159]: s[s.index.isin([2, 4, 6])] Out[159]: 4 0 2 2 dtype: int64 # compare it to the following In [160]: s.reindex([2, 4, 6]) Out[160]: 2 2.0 4 0.0 6 NaN dtype: float64 除此之外,還MultiIndex允許選擇一個單獨的級別以用於成員資格檢查: In [161]: s_mi = pd.Series(np.arange(6), .....: index=pd.MultiIndex.from_product([[0, 1], ['a', 'b', 'c']])) .....: In [162]: s_mi Out[162]: 0 a 0 b 1 c 2 1 a 3 b 4 c 5 dtype: int64 In [163]: s_mi.iloc[s_mi.index.isin([(1, 'a'), (2, 'b'), (0, 'c')])] Out[163]: 0 c 2 1 a 3 dtype: int64 In [164]: s_mi.iloc[s_mi.index.isin(['a', 'c', 'e'], level=1)] Out[164]: 0 a 0 c 2 1 a 3 c 5 dtype: int64 DataFrame也有一個isin()方法。調用時isin,將一組值作為數組或dict傳遞。如果values是一個數組,則isin返回一個與原始DataFrame形狀相同的布爾值DataFrame,無論元素在值序列中的什么位置都為True。 In [165]: df = pd.DataFrame({'vals': [1, 2, 3, 4], 'ids': ['a', 'b', 'f', 'n'], .....: 'ids2': ['a', 'n', 'c', 'n']}) .....: In [166]: values = ['a', 'b', 1, 3] In [167]: df.isin(values) Out[167]: vals ids ids2 0 True True True 1 False True False 2 True False False 3 False False False 通常,您需要將某些值與某些列匹配。只需將值設置為a即可dict,鍵是列,而值是要檢查的項目列表。 In [168]: values = {'ids': ['a', 'b'], 'vals': [1, 3]} In [169]: df.isin(values) Out[169]: vals ids ids2 0 True True False 1 False True False 2 True False False 3 False False False 將DataFrame isin與any()和all()方法結合使用,可以快速選擇滿足給定條件的數據子集。要選擇每一列均符合其條件的行: In [170]: values = {'ids': ['a', 'b'], 'ids2': ['a', 'c'], 'vals': [1, 3]} In [171]: row_mask = df.isin(values).all(1) In [172]: df[row_mask] Out[172]: vals ids ids2 0 1 a a 該where()方法和屏蔽 從具有布爾向量的Series中選擇值通常會返回數據的子集。為了確保選擇輸出具有與原始數據相同的形狀,可以where在Series和中使用方法DataFrame。 要僅返回選定的行: In [173]: s[s > 0] Out[173]: 3 1 2 2 1 3 0 4 dtype: int64 要返回與原始形狀相同的系列: In [174]: s.where(s > 0) Out[174]: 4 NaN 3 1.0 2 2.0 1 3.0 0 4.0 dtype: float64 現在,從具有布爾條件的DataFrame中選擇值還可以保留輸入數據的形狀。where在后台使用作為實現。以下代碼等效於。df.where(df < 0) In [175]: df[df < 0] Out[175]: A B C D 2000-01-01 -2.104139 -1.309525 NaN NaN 2000-01-02 -0.352480 NaN -1.192319 NaN 2000-01-03 -0.864883 NaN -0.227870 NaN 2000-01-04 NaN -1.222082 NaN -1.233203 2000-01-05 NaN -0.605656 -1.169184 NaN 2000-01-06 NaN -0.948458 NaN -0.684718 2000-01-07 -2.670153 -0.114722 NaN -0.048048 2000-01-08 NaN NaN -0.048788 -0.808838 此外,在返回的副本中,使用where一個可選other參數替換條件為False的值。 In [176]: df.where(df < 0, -df) Out[176]: A B C D 2000-01-01 -2.104139 -1.309525 -0.485855 -0.245166 2000-01-02 -0.352480 -0.390389 -1.192319 -1.655824 2000-01-03 -0.864883 -0.299674 -0.227870 -0.281059 2000-01-04 -0.846958 -1.222082 -0.600705 -1.233203 2000-01-05 -0.669692 -0.605656 -1.169184 -0.342416 2000-01-06 -0.868584 -0.948458 -2.297780 -0.684718 2000-01-07 -2.670153 -0.114722 -0.168904 -0.048048 2000-01-08 -0.801196 -1.392071 -0.048788 -0.808838 您可能希望根據某些布爾條件設置值。可以像這樣直觀地完成: In [177]: s2 = s.copy() In [178]: s2[s2 < 0] = 0 In [179]: s2 Out[179]: 4 0 3 1 2 2 1 3 0 4 dtype: int64 In [180]: df2 = df.copy() In [181]: df2[df2 < 0] = 0 In [182]: df2 Out[182]: A B C D 2000-01-01 0.000000 0.000000 0.485855 0.245166 2000-01-02 0.000000 0.390389 0.000000 1.655824 2000-01-03 0.000000 0.299674 0.000000 0.281059 2000-01-04 0.846958 0.000000 0.600705 0.000000 2000-01-05 0.669692 0.000000 0.000000 0.342416 2000-01-06 0.868584 0.000000 2.297780 0.000000 2000-01-07 0.000000 0.000000 0.168904 0.000000 2000-01-08 0.801196 1.392071 0.000000 0.000000 默認情況下,where返回數據的修改后的副本。有一個可選參數,inplace以便可以在不創建副本的情況下修改原始數據: In [183]: df_orig = df.copy() In [184]: df_orig.where(df > 0, -df, inplace=True) In [185]: df_orig Out[185]: A B C D 2000-01-01 2.104139 1.309525 0.485855 0.245166 2000-01-02 0.352480 0.390389 1.192319 1.655824 2000-01-03 0.864883 0.299674 0.227870 0.281059 2000-01-04 0.846958 1.222082 0.600705 1.233203 2000-01-05 0.669692 0.605656 1.169184 0.342416 2000-01-06 0.868584 0.948458 2.297780 0.684718 2000-01-07 2.670153 0.114722 0.168904 0.048048 2000-01-08 0.801196 1.392071 0.048788 0.808838 注意 的簽名DataFrame.where()不同於numpy.where()。大致相當於。df1.where(m, df2)np.where(m, df1, df2) In [186]: df.where(df < 0, -df) == np.where(df < 0, df, -df) Out[186]: A B C D 2000-01-01 True True True True 2000-01-02 True True True True 2000-01-03 True True True True 2000-01-04 True True True True 2000-01-05 True True True True 2000-01-06 True True True True 2000-01-07 True True True True 2000-01-08 True True True True 對准 此外,where對齊輸入的布爾條件(ndarray或DataFrame),以便可以通過設置進行部分選擇。這類似於通過進行部分設置.loc(但在內容而非軸標簽上)。 In [187]: df2 = df.copy() In [188]: df2[df2[1:4] > 0] = 3 In [189]: df2 Out[189]: A B C D 2000-01-01 -2.104139 -1.309525 0.485855 0.245166 2000-01-02 -0.352480 3.000000 -1.192319 3.000000 2000-01-03 -0.864883 3.000000 -0.227870 3.000000 2000-01-04 3.000000 -1.222082 3.000000 -1.233203 2000-01-05 0.669692 -0.605656 -1.169184 0.342416 2000-01-06 0.868584 -0.948458 2.297780 -0.684718 2000-01-07 -2.670153 -0.114722 0.168904 -0.048048 2000-01-08 0.801196 1.392071 -0.048788 -0.808838 執行時,where還可以接受axis和level參數以對齊輸入where。 In [190]: df2 = df.copy() In [191]: df2.where(df2 > 0, df2['A'], axis='index') Out[191]: A B C D 2000-01-01 -2.104139 -2.104139 0.485855 0.245166 2000-01-02 -0.352480 0.390389 -0.352480 1.655824 2000-01-03 -0.864883 0.299674 -0.864883 0.281059 2000-01-04 0.846958 0.846958 0.600705 0.846958 2000-01-05 0.669692 0.669692 0.669692 0.342416 2000-01-06 0.868584 0.868584 2.297780 0.868584 2000-01-07 -2.670153 -2.670153 0.168904 -2.670153 2000-01-08 0.801196 1.392071 0.801196 0.801196 這等效於(但比以下速度更快)。 In [192]: df2 = df.copy() In [193]: df.apply(lambda x, y: x.where(x > 0, y), y=df['A']) Out[193]: A B C D 2000-01-01 -2.104139 -2.104139 0.485855 0.245166 2000-01-02 -0.352480 0.390389 -0.352480 1.655824 2000-01-03 -0.864883 0.299674 -0.864883 0.281059 2000-01-04 0.846958 0.846958 0.600705 0.846958 2000-01-05 0.669692 0.669692 0.669692 0.342416 2000-01-06 0.868584 0.868584 2.297780 0.868584 2000-01-07 -2.670153 -2.670153 0.168904 -2.670153 2000-01-08 0.801196 1.392071 0.801196 0.801196 0.18.1版中的新功能。 在哪里可以接受一個callable作為條件和other參數。該函數必須帶有一個參數(調用Series或DataFrame),並且返回有效輸出作為條件和other參數。 In [194]: df3 = pd.DataFrame({'A': [1, 2, 3], .....: 'B': [4, 5, 6], .....: 'C': [7, 8, 9]}) .....: In [195]: df3.where(lambda x: x > 4, lambda x: x + 10) Out[195]: A B C 0 11 14 7 1 12 5 8 2 13 6 9 遮罩 mask()是的逆布爾運算where。 In [196]: s.mask(s >= 0) Out[196]: 4 NaN 3 NaN 2 NaN 1 NaN 0 NaN dtype: float64 In [197]: df.mask(df >= 0) Out[197]: A B C D 2000-01-01 -2.104139 -1.309525 NaN NaN 2000-01-02 -0.352480 NaN -1.192319 NaN 2000-01-03 -0.864883 NaN -0.227870 NaN 2000-01-04 NaN -1.222082 NaN -1.233203 2000-01-05 NaN -0.605656 -1.169184 NaN 2000-01-06 NaN -0.948458 NaN -0.684718 2000-01-07 -2.670153 -0.114722 NaN -0.048048 2000-01-08 NaN NaN -0.048788 -0.808838 該query()方法 DataFrame對象具有query() 允許使用表達式進行選擇的方法。 您可以獲取框架的值,其中column b的值在column a和的值之間c。例如: In [198]: n = 10 In [199]: df = pd.DataFrame(np.random.rand(n, 3), columns=list('abc')) In [200]: df Out[200]: a b c 0 0.438921 0.118680 0.863670 1 0.138138 0.577363 0.686602 2 0.595307 0.564592 0.520630 3 0.913052 0.926075 0.616184 4 0.078718 0.854477 0.898725 5 0.076404 0.523211 0.591538 6 0.792342 0.216974 0.564056 7 0.397890 0.454131 0.915716 8 0.074315 0.437913 0.019794 9 0.559209 0.502065 0.026437 # pure python In [201]: df[(df.a < df.b) & (df.b < df.c)] Out[201]: a b c 1 0.138138 0.577363 0.686602 4 0.078718 0.854477 0.898725 5 0.076404 0.523211 0.591538 7 0.397890 0.454131 0.915716 # query In [202]: df.query('(a < b) & (b < c)') Out[202]: a b c 1 0.138138 0.577363 0.686602 4 0.078718 0.854477 0.898725 5 0.076404 0.523211 0.591538 7 0.397890 0.454131 0.915716 做同樣的事情,但是如果沒有名稱為的列,則使用命名索引a。 In [203]: df = pd.DataFrame(np.random.randint(n / 2, size=(n, 2)), columns=list('bc')) In [204]: df.index.name = 'a' In [205]: df Out[205]: b c a 0 0 4 1 0 1 2 3 4 3 4 3 4 1 4 5 0 3 6 0 1 7 3 4 8 2 3 9 1 1 In [206]: df.query('a < b and b < c') Out[206]: b c a 2 3 4 相反,如果您不想或無法命名索引,則可以index在查詢表達式中使用該名稱 : In [207]: df = pd.DataFrame(np.random.randint(n, size=(n, 2)), columns=list('bc')) In [208]: df Out[208]: b c 0 3 1 1 3 0 2 5 6 3 5 2 4 7 4 5 0 1 6 2 5 7 0 1 8 6 0 9 7 9 In [209]: df.query('index < b < c') Out[209]: b c 2 5 6 注意 如果索引名與列名重疊,則列名優先。例如, In [210]: df = pd.DataFrame({'a': np.random.randint(5, size=5)}) In [211]: df.index.name = 'a' In [212]: df.query('a > 2') # uses the column 'a', not the index Out[212]: a a 1 3 3 3 您仍然可以通過使用特殊標識符'index'在查詢表達式中使用索引: In [213]: df.query('index > 2') Out[213]: a a 3 3 4 2 如果由於某種原因您有一個名為的列index,那么您也可以引用該索引ilevel_0,但是在這一點上,您應該考慮將列重命名為不太模糊的名稱。 MultiIndex query()語法 您也可以將a的級別與a DataFrame一起使用 MultiIndex,就好像它們是框架中的列一樣: In [214]: n = 10 In [215]: colors = np.random.choice(['red', 'green'], size=n) In [216]: foods = np.random.choice(['eggs', 'ham'], size=n) In [217]: colors Out[217]: array(['red', 'red', 'red', 'green', 'green', 'green', 'green', 'green', 'green', 'green'], dtype='<U5') In [218]: foods Out[218]: array(['ham', 'ham', 'eggs', 'eggs', 'eggs', 'ham', 'ham', 'eggs', 'eggs', 'eggs'], dtype='<U4') In [219]: index = pd.MultiIndex.from_arrays([colors, foods], names=['color', 'food']) In [220]: df = pd.DataFrame(np.random.randn(n, 2), index=index) In [221]: df Out[221]: 0 1 color food red ham 0.194889 -0.381994 ham 0.318587 2.089075 eggs -0.728293 -0.090255 green eggs -0.748199 1.318931 eggs -2.029766 0.792652 ham 0.461007 -0.542749 ham -0.305384 -0.479195 eggs 0.095031 -0.270099 eggs -0.707140 -0.773882 eggs 0.229453 0.304418 In [222]: df.query('color == "red"') Out[222]: 0 1 color food red ham 0.194889 -0.381994 ham 0.318587 2.089075 eggs -0.728293 -0.090255 如果的級別MultiIndex未命名,則可以使用特殊名稱來引用它們: In [223]: df.index.names = [None, None] In [224]: df Out[224]: 0 1 red ham 0.194889 -0.381994 ham 0.318587 2.089075 eggs -0.728293 -0.090255 green eggs -0.748199 1.318931 eggs -2.029766 0.792652 ham 0.461007 -0.542749 ham -0.305384 -0.479195 eggs 0.095031 -0.270099 eggs -0.707140 -0.773882 eggs 0.229453 0.304418 In [225]: df.query('ilevel_0 == "red"') Out[225]: 0 1 red ham 0.194889 -0.381994 ham 0.318587 2.089075 eggs -0.728293 -0.090255 約定為ilevel_0,表示的第0級為“索引級別0” index。 query()用例 一個用例query()是當您有一組 DataFrame對象,這些對象具有共同的列名稱(或索引級別/名稱)的子集。您可以將相同的查詢傳遞給兩個框架,而 不必指定要查詢的框架 In [226]: df = pd.DataFrame(np.random.rand(n, 3), columns=list('abc')) In [227]: df Out[227]: a b c 0 0.224283 0.736107 0.139168 1 0.302827 0.657803 0.713897 2 0.611185 0.136624 0.984960 3 0.195246 0.123436 0.627712 4 0.618673 0.371660 0.047902 5 0.480088 0.062993 0.185760 6 0.568018 0.483467 0.445289 7 0.309040 0.274580 0.587101 8 0.258993 0.477769 0.370255 9 0.550459 0.840870 0.304611 In [228]: df2 = pd.DataFrame(np.random.rand(n + 2, 3), columns=df.columns) In [229]: df2 Out[229]: a b c 0 0.357579 0.229800 0.596001 1 0.309059 0.957923 0.965663 2 0.123102 0.336914 0.318616 3 0.526506 0.323321 0.860813 4 0.518736 0.486514 0.384724 5 0.190804 0.505723 0.614533 6 0.891939 0.623977 0.676639 7 0.480559 0.378528 0.460858 8 0.420223 0.136404 0.141295 9 0.732206 0.419540 0.604675 10 0.604466 0.848974 0.896165 11 0.589168 0.920046 0.732716 In [230]: expr = '0.0 <= a <= c <= 0.5' In [231]: map(lambda frame: frame.query(expr), [df, df2]) Out[231]: <map at 0x7fb06bd71cf8> query()Python與Pandas語法比較 完整的類似numpy的語法: In [232]: df = pd.DataFrame(np.random.randint(n, size=(n, 3)), columns=list('abc')) In [233]: df Out[233]: a b c 0 7 8 9 1 1 0 7 2 2 7 2 3 6 2 2 4 2 6 3 5 3 8 2 6 1 7 2 7 5 1 5 8 9 8 0 9 1 5 0 In [234]: df.query('(a < b) & (b < c)') Out[234]: a b c 0 7 8 9 In [235]: df[(df.a < df.b) & (df.b < df.c)] Out[235]: a b c 0 7 8 9 刪除括號會稍微好一點(通過綁定使比較運算符比&和更緊密地綁定|)。 In [236]: df.query('a < b & b < c') Out[236]: a b c 0 7 8 9 使用英語代替符號: In [237]: df.query('a < b and b < c') Out[237]: a b c 0 7 8 9 非常接近您在紙上書寫的方式: In [238]: df.query('a < b < c') Out[238]: a b c 0 7 8 9 在in與運營商not in query()還支持Python in和 比較運算符的特殊用法,為調用a 或方法提供了簡潔的語法 。not inisinSeriesDataFrame # get all rows where columns "a" and "b" have overlapping values In [239]: df = pd.DataFrame({'a': list('aabbccddeeff'), 'b': list('aaaabbbbcccc'), .....: 'c': np.random.randint(5, size=12), .....: 'd': np.random.randint(9, size=12)}) .....: In [240]: df Out[240]: a b c d 0 a a 2 6 1 a a 4 7 2 b a 1 6 3 b a 2 1 4 c b 3 6 5 c b 0 2 6 d b 3 3 7 d b 2 1 8 e c 4 3 9 e c 2 0 10 f c 0 6 11 f c 1 2 In [241]: df.query('a in b') Out[241]: a b c d 0 a a 2 6 1 a a 4 7 2 b a 1 6 3 b a 2 1 4 c b 3 6 5 c b 0 2 # How you'd do it in pure Python In [242]: df[df.a.isin(df.b)] Out[242]: a b c d 0 a a 2 6 1 a a 4 7 2 b a 1 6 3 b a 2 1 4 c b 3 6 5 c b 0 2 In [243]: df.query('a not in b') Out[243]: a b c d 6 d b 3 3 7 d b 2 1 8 e c 4 3 9 e c 2 0 10 f c 0 6 11 f c 1 2 # pure Python In [244]: df[~df.a.isin(df.b)] Out[244]: a b c d 6 d b 3 3 7 d b 2 1 8 e c 4 3 9 e c 2 0 10 f c 0 6 11 f c 1 2 您可以將其與其他表達式結合使用以進行非常簡潔的查詢: # rows where cols a and b have overlapping values # and col c's values are less than col d's In [245]: df.query('a in b and c < d') Out[245]: a b c d 0 a a 2 6 1 a a 4 7 2 b a 1 6 4 c b 3 6 5 c b 0 2 # pure Python In [246]: df[df.b.isin(df.a) & (df.c < df.d)] Out[246]: a b c d 0 a a 2 6 1 a a 4 7 2 b a 1 6 4 c b 3 6 5 c b 0 2 10 f c 0 6 11 f c 1 2 注意 請注意,在Python中對in和進行了評估,因為 該操作不等效。但是,在香草Python中僅對 / 表達式本身進行求值。例如,在表達式中not innumexpr innot in df.query('a in b + c + d') (b + c + d)通過評估numexpr和然后的in 操作在普通的Python評價。通常,將使用可以評估的任何操作numexpr。 ==運算符與list對象的特殊用法 list使用==/ 將值a與列進行比較!=類似於in/ 。not in In [247]: df.query('b == ["a", "b", "c"]') Out[247]: a b c d 0 a a 2 6 1 a a 4 7 2 b a 1 6 3 b a 2 1 4 c b 3 6 5 c b 0 2 6 d b 3 3 7 d b 2 1 8 e c 4 3 9 e c 2 0 10 f c 0 6 11 f c 1 2 # pure Python In [248]: df[df.b.isin(["a", "b", "c"])] Out[248]: a b c d 0 a a 2 6 1 a a 4 7 2 b a 1 6 3 b a 2 1 4 c b 3 6 5 c b 0 2 6 d b 3 3 7 d b 2 1 8 e c 4 3 9 e c 2 0 10 f c 0 6 11 f c 1 2 In [249]: df.query('c == [1, 2]') Out[249]: a b c d 0 a a 2 6 2 b a 1 6 3 b a 2 1 7 d b 2 1 9 e c 2 0 11 f c 1 2 In [250]: df.query('c != [1, 2]') Out[250]: a b c d 1 a a 4 7 4 c b 3 6 5 c b 0 2 6 d b 3 3 8 e c 4 3 10 f c 0 6 # using in/not in In [251]: df.query('[1, 2] in c') Out[251]: a b c d 0 a a 2 6 2 b a 1 6 3 b a 2 1 7 d b 2 1 9 e c 2 0 11 f c 1 2 In [252]: df.query('[1, 2] not in c') Out[252]: a b c d 1 a a 4 7 4 c b 3 6 5 c b 0 2 6 d b 3 3 8 e c 4 3 10 f c 0 6 # pure Python In [253]: df[df.c.isin([1, 2])] Out[253]: a b c d 0 a a 2 6 2 b a 1 6 3 b a 2 1 7 d b 2 1 9 e c 2 0 11 f c 1 2 布爾運算符 您可以使用單詞not或~運算符取反布爾表達式。 In [254]: df = pd.DataFrame(np.random.rand(n, 3), columns=list('abc')) In [255]: df['bools'] = np.random.rand(len(df)) > 0.5 In [256]: df.query('~bools') Out[256]: a b c bools 2 0.697753 0.212799 0.329209 False 7 0.275396 0.691034 0.826619 False 8 0.190649 0.558748 0.262467 False In [257]: df.query('not bools') Out[257]: a b c bools 2 0.697753 0.212799 0.329209 False 7 0.275396 0.691034 0.826619 False 8 0.190649 0.558748 0.262467 False In [258]: df.query('not bools') == df[~df.bools] Out[258]: a b c bools 2 True True True True 7 True True True True 8 True True True True 當然,表達式也可以任意復雜: # short query syntax In [259]: shorter = df.query('a < b < c and (not bools) or bools > 2') # equivalent in pure Python In [260]: longer = df[(df.a < df.b) & (df.b < df.c) & (~df.bools) | (df.bools > 2)] In [261]: shorter Out[261]: a b c bools 7 0.275396 0.691034 0.826619 False In [262]: longer Out[262]: a b c bools 7 0.275396 0.691034 0.826619 False In [263]: shorter == longer Out[263]: a b c bools 7 True True True True 性能query() DataFrame.query()numexpr對於大型框架,使用速度比Python快。 ../_images/query-perf.png 注意 僅當您的框架中有大約200,000行以上時,才可以看到使用numexpr引擎的性能優勢DataFrame.query()。 ../_images/query-perf-small.png 此圖是使用組成的DataFrame,其中包含3列,每個列包含使用生成的浮點值numpy.random.randn()。 重復數據 如果要標識和刪除DataFrame中的重復行,有兩種方法會有所幫助:duplicated和drop_duplicates。每個參數都以用於標識重復行的列作為參數。 duplicated 返回一個布爾矢量,其長度為行數,並指示是否重復一行。 drop_duplicates 刪除重復的行。 默認情況下,觀察到的重復集的第一行被認為是唯一的,但是每種方法都有一個keep參數來指定要保留的目標。 keep='first' (默認):標記/刪除重復項,但第一次出現除外。 keep='last':標記/刪除重復項(最后一次除外)。 keep=False:標記/刪除所有重復項。 In [264]: df2 = pd.DataFrame({'a': ['one', 'one', 'two', 'two', 'two', 'three', 'four'], .....: 'b': ['x', 'y', 'x', 'y', 'x', 'x', 'x'], .....: 'c': np.random.randn(7)}) .....: In [265]: df2 Out[265]: a b c 0 one x -1.067137 1 one y 0.309500 2 two x -0.211056 3 two y -1.842023 4 two x -0.390820 5 three x -1.964475 6 four x 1.298329 In [266]: df2.duplicated('a') Out[266]: 0 False 1 True 2 False 3 True 4 True 5 False 6 False dtype: bool In [267]: df2.duplicated('a', keep='last') Out[267]: 0 True 1 False 2 True 3 True 4 False 5 False 6 False dtype: bool In [268]: df2.duplicated('a', keep=False) Out[268]: 0 True 1 True 2 True 3 True 4 True 5 False 6 False dtype: bool In [269]: df2.drop_duplicates('a') Out[269]: a b c 0 one x -1.067137 2 two x -0.211056 5 three x -1.964475 6 four x 1.298329 In [270]: df2.drop_duplicates('a', keep='last') Out[270]: a b c 1 one y 0.309500 4 two x -0.390820 5 three x -1.964475 6 four x 1.298329 In [271]: df2.drop_duplicates('a', keep=False) Out[271]: a b c 5 three x -1.964475 6 four x 1.298329 另外,您可以傳遞列列表以標識重復項。 In [272]: df2.duplicated(['a', 'b']) Out[272]: 0 False 1 False 2 False 3 False 4 True 5 False 6 False dtype: bool In [273]: df2.drop_duplicates(['a', 'b']) Out[273]: a b c 0 one x -1.067137 1 one y 0.309500 2 two x -0.211056 3 two y -1.842023 5 three x -1.964475 6 four x 1.298329 要按索引值刪除重復項,請使用,Index.duplicated然后執行切片。該keep參數具有相同的選項集。 In [274]: df3 = pd.DataFrame({'a': np.arange(6), .....: 'b': np.random.randn(6)}, .....: index=['a', 'a', 'b', 'c', 'b', 'a']) .....: In [275]: df3 Out[275]: a b a 0 1.440455 a 1 2.456086 b 2 1.038402 c 3 -0.894409 b 4 0.683536 a 5 3.082764 In [276]: df3.index.duplicated() Out[276]: array([False, True, False, False, True, True]) In [277]: df3[~df3.index.duplicated()] Out[277]: a b a 0 1.440455 b 2 1.038402 c 3 -0.894409 In [278]: df3[~df3.index.duplicated(keep='last')] Out[278]: a b c 3 -0.894409 b 4 0.683536 a 5 3.082764 In [279]: df3[~df3.index.duplicated(keep=False)] Out[279]: a b c 3 -0.894409 類似字典的get()方法 每個Series或DataFrame都有一個get可以返回默認值的方法。 In [280]: s = pd.Series([1, 2, 3], index=['a', 'b', 'c']) In [281]: s.get('a') # equivalent to s['a'] Out[281]: 1 In [282]: s.get('x', default=-1) Out[282]: -1 該lookup()方法 有時,您需要提取給定一系列行標簽和列標簽的一組值,並且該lookup方法允許這樣做並返回NumPy數組。例如: In [283]: dflookup = pd.DataFrame(np.random.rand(20, 4), columns = ['A', 'B', 'C', 'D']) In [284]: dflookup.lookup(list(range(0, 10, 2)), ['B', 'C', 'A', 'B', 'D']) Out[284]: array([0.3506, 0.4779, 0.4825, 0.9197, 0.5019]) 索引對象 pandas Index類及其子類可以看作實現了有序的多集。允許重復。但是,如果您嘗試將Index具有重復條目的對象轉換為 set,則會引發異常。 Index還提供了查找,數據對齊和重新索引所需的基礎結構。Index直接創建一個最簡單的方法 是將a list或其他序列傳遞給 Index: In [285]: index = pd.Index(['e', 'd', 'a', 'b']) In [286]: index Out[286]: Index(['e', 'd', 'a', 'b'], dtype='object') In [287]: 'd' in index Out[287]: True 您還可以傳遞name要存儲在索引中的: In [288]: index = pd.Index(['e', 'd', 'a', 'b'], name='something') In [289]: index.name Out[289]: 'something' 名稱(如果已設置)將顯示在控制台顯示屏中: In [290]: index = pd.Index(list(range(5)), name='rows') In [291]: columns = pd.Index(['A', 'B', 'C'], name='cols') In [292]: df = pd.DataFrame(np.random.randn(5, 3), index=index, columns=columns) In [293]: df Out[293]: cols A B C rows 0 1.295989 0.185778 0.436259 1 0.678101 0.311369 -0.528378 2 -0.674808 -1.103529 -0.656157 3 1.889957 2.076651 -1.102192 4 -1.211795 -0.791746 0.634724 In [294]: df['A'] Out[294]: rows 0 1.295989 1 0.678101 2 -0.674808 3 1.889957 4 -1.211795 Name: A, dtype: float64 設置的元數據 索引是“不可改變的大多是”,但它可以設置和改變它們的元數據,如指數name(或為MultiIndex,levels和 codes)。 您可以使用rename,set_names,set_levels,和set_codes 直接設置這些屬性。他們默認返回一個副本。但是,您可以指定inplace=True將數據更改到位。 有關MultiIndexes的用法,請參閱高級索引。 In [295]: ind = pd.Index([1, 2, 3]) In [296]: ind.rename("apple") Out[296]: Int64Index([1, 2, 3], dtype='int64', name='apple') In [297]: ind Out[297]: Int64Index([1, 2, 3], dtype='int64') In [298]: ind.set_names(["apple"], inplace=True) In [299]: ind.name = "bob" In [300]: ind Out[300]: Int64Index([1, 2, 3], dtype='int64', name='bob') set_names,set_levels以及set_codes還需要一個可選的 level參數 In [301]: index = pd.MultiIndex.from_product([range(3), ['one', 'two']], names=['first', 'second']) In [302]: index Out[302]: MultiIndex(levels=[[0, 1, 2], ['one', 'two']], codes=[[0, 0, 1, 1, 2, 2], [0, 1, 0, 1, 0, 1]], names=['first', 'second']) In [303]: index.levels[1] Out[303]: Index(['one', 'two'], dtype='object', name='second') In [304]: index.set_levels(["a", "b"], level=1) Out[304]: MultiIndex(levels=[[0, 1, 2], ['a', 'b']], codes=[[0, 0, 1, 1, 2, 2], [0, 1, 0, 1, 0, 1]], names=['first', 'second']) 在索引對象設置操作 兩個主要操作是和。這些可以直接稱為實例方法,也可以通過重載運算符使用。通過該方法提供差異。union (|)intersection (&).difference() In [305]: a = pd.Index(['c', 'b', 'a']) In [306]: b = pd.Index(['c', 'e', 'd']) In [307]: a | b Out[307]: Index(['a', 'b', 'c', 'd', 'e'], dtype='object') In [308]: a & b Out[308]: Index(['c'], dtype='object') In [309]: a.difference(b) Out[309]: Index(['a', 'b'], dtype='object') 該操作也可用,該操作返回出現在或中的元素,但不同時出現在這兩個元素中。這等效於所創建的索引,其中刪除了重復項。symmetric_difference (^)idx1idx2idx1.difference(idx2).union(idx2.difference(idx1)) In [310]: idx1 = pd.Index([1, 2, 3, 4]) In [311]: idx2 = pd.Index([2, 3, 4, 5]) In [312]: idx1.symmetric_difference(idx2) Out[312]: Int64Index([1, 5], dtype='int64') In [313]: idx1 ^ idx2 Out[313]: Int64Index([1, 5], dtype='int64') 注意 設置操作產生的索引將按升序排序。 缺失值 重要 即使Index可以保留缺少的值(NaN),如果您不希望有任何意外的結果,也應避免使用。例如,某些操作會隱式排除缺失值。 Index.fillna 用指定的標量值填充缺少的值。 In [314]: idx1 = pd.Index([1, np.nan, 3, 4]) In [315]: idx1 Out[315]: Float64Index([1.0, nan, 3.0, 4.0], dtype='float64') In [316]: idx1.fillna(2) Out[316]: Float64Index([1.0, 2.0, 3.0, 4.0], dtype='float64') In [317]: idx2 = pd.DatetimeIndex([pd.Timestamp('2011-01-01'), .....: pd.NaT, .....: pd.Timestamp('2011-01-03')]) .....: In [318]: idx2 Out[318]: DatetimeIndex(['2011-01-01', 'NaT', '2011-01-03'], dtype='datetime64[ns]', freq=None) In [319]: idx2.fillna(pd.Timestamp('2011-01-02')) Out[319]: DatetimeIndex(['2011-01-01', '2011-01-02', '2011-01-03'], dtype='datetime64[ns]', freq=None) 設置/重置索引 有時候,您會在DataFrame中加載或創建數據集,並希望在完成后添加索引。有幾種不同的方法。 設置索引 DataFrame有一個set_index()方法,該方法采用列名(對於常規Index)或列名列表(對於MultiIndex)。要創建一個新的,重新索引的DataFrame: In [320]: data Out[320]: a b c d 0 bar one z 1.0 1 bar two y 2.0 2 foo one x 3.0 3 foo two w 4.0 In [321]: indexed1 = data.set_index('c') In [322]: indexed1 Out[322]: a b d c z bar one 1.0 y bar two 2.0 x foo one 3.0 w foo two 4.0 In [323]: indexed2 = data.set_index(['a', 'b']) In [324]: indexed2 Out[324]: c d a b bar one z 1.0 two y 2.0 foo one x 3.0 two w 4.0 該append關鍵字選項讓你保持現有索引並追加給列一個多指標: In [325]: frame = data.set_index('c', drop=False) In [326]: frame = frame.set_index(['a', 'b'], append=True) In [327]: frame Out[327]: c d c a b z bar one z 1.0 y bar two y 2.0 x foo one x 3.0 w foo two w 4.0 中的其他選項set_index允許您不要刪除索引列或就地添加索引(無需創建新對象): In [328]: data.set_index('c', drop=False) Out[328]: a b c d c z bar one z 1.0 y bar two y 2.0 x foo one x 3.0 w foo two w 4.0 In [329]: data.set_index(['a', 'b'], inplace=True) In [330]: data Out[330]: c d a b bar one z 1.0 two y 2.0 foo one x 3.0 two w 4.0 重置指數 為方便起見,DataFrame上有一個新函數,reset_index()該函數 將索引值傳輸到DataFrame的列中並設置一個簡單的整數索引。這是的逆運算set_index()。 In [331]: data Out[331]: c d a b bar one z 1.0 two y 2.0 foo one x 3.0 two w 4.0 In [332]: data.reset_index() Out[332]: a b c d 0 bar one z 1.0 1 bar two y 2.0 2 foo one x 3.0 3 foo two w 4.0 輸出與SQL表或記錄數組更相似。從索引派生的列的名稱是存儲在names屬性中的名稱。 您可以使用level關鍵字僅刪除部分索引: In [333]: frame Out[333]: c d c a b z bar one z 1.0 y bar two y 2.0 x foo one x 3.0 w foo two w 4.0 In [334]: frame.reset_index(level=1) Out[334]: a c d c b z one bar z 1.0 y two bar y 2.0 x one foo x 3.0 w two foo w 4.0 reset_index接受一個可選參數drop,如果為true,則該參數將簡單地丟棄索引,而不是將索引值放在DataFrame的列中。 添加臨時索引 如果您自己創建索引,則可以將其分配給該index字段: data.index = index 返回視圖與副本 在熊貓對象中設置值時,必須注意避免所謂的 。這是一個例子。chained indexing In [335]: dfmi = pd.DataFrame([list('abcd'), .....: list('efgh'), .....: list('ijkl'), .....: list('mnop')], .....: columns=pd.MultiIndex.from_product([['one', 'two'], .....: ['first', 'second']])) .....: In [336]: dfmi Out[336]: one two first second first second 0 a b c d 1 e f g h 2 i j k l 3 m n o p 比較這兩種訪問方法: In [337]: dfmi['one']['second'] Out[337]: 0 b 1 f 2 j 3 n Name: second, dtype: object In [338]: dfmi.loc[:, ('one', 'second')] Out[338]: 0 b 1 f 2 j 3 n Name: (one, second), dtype: object 兩者都會產生相同的結果,那么您應該使用哪個呢?了解這些操作的順序以及為什么方法2(.loc)比方法1(鏈接[])更可取是很有啟發性的。 dfmi['one']選擇列的第一級並返回一個單獨索引的DataFrame。然后另一個Python操作dfmi_with_one['second']選擇由索引的系列'second'。這由變量指示,dfmi_with_one因為熊貓將這些操作視為單獨的事件。例如,對的單獨調用__getitem__,因此必須將它們視為線性操作,它們接連發生。 與之形成對照的是df.loc[:,('one','second')],將嵌套的元組傳遞(slice(None),('one','second'))給的單個調用 __getitem__。這使大熊貓可以將其作為一個整體來處理。此外,這種操作順序可以明顯更快,並且如果需要的話,可以使兩個軸分度。 為什么使用鏈接索引時分配失敗? 上一節中的問題僅僅是性能問題。有什么用的了SettingWithCopy警告?當您執行可能需要花費幾毫秒的時間時,我們通常不會發出警告! 但是事實證明,分配給鏈式索引的產品具有固有的不可預測的結果。要查看此內容,請考慮Python解釋器如何執行此代碼: dfmi.loc[:, ('one', 'second')] = value # becomes dfmi.loc.__setitem__((slice(None), ('one', 'second')), value) 但是此代碼的處理方式不同: dfmi['one']['second'] = value # becomes dfmi.__getitem__('one').__setitem__('second', value) 看到__getitem__那里嗎?在簡單情況之外,很難預測它是否將返回視圖或副本(這取決於數組的內存布局,有關大熊貓對此不做任何保證),因此很難確定將__setitem__要修改dfmi還是返回一個臨時對象。之后立即扔出去。那什么SettingWithCopy是警告你! 注意 您可能想知道loc 在第一個示例中我們是否應該關注該屬性。但dfmi.loc要保證dfmi 自身具有修改的索引行為,因此dfmi.loc.__getitem__/ 直接dfmi.loc.__setitem__進行操作dfmi。當然, dfmi.loc.__getitem__(idx)可以是的視圖或副本dfmi。 有時SettingWithCopy在沒有明顯的鏈接索引進行時,有時會發出警告。這些SettingWithCopy是旨在捕獲的錯誤 !熊貓可能正在嘗試警告您,您已經這樣做了: def do_something(df): foo = df[['bar', 'baz']] # Is foo a view? A copy? Nobody knows! # ... many lines here ... # We don't know whether this will modify df or not! foo['quux'] = value return foo kes! 評估順序很重要 使用鏈式索引時,索引操作的順序和類型將部分確定結果是原始對象的切片還是該切片的副本。 Pandas之所以這樣,是SettingWithCopyWarning因為分配分片的副本通常不是故意的,而是由鏈式索引導致的錯誤,該錯誤將原本應有分片的副本返回。 如果您希望熊貓在某種程度上信任鏈式索引表達式的分配,可以將選項 設置mode.chained_assignment為以下值之一: 'warn',即默認值,表示SettingWithCopyWarning已打印a。 'raise'意味着大熊貓會籌集一個SettingWithCopyException 你必須處理的。 None 將完全消除警告。 In [339]: dfb = pd.DataFrame({'a': ['one', 'one', 'two', .....: 'three', 'two', 'one', 'six'], .....: 'c': np.arange(7)}) .....: # This will show the SettingWithCopyWarning # but the frame values will be set In [340]: dfb['c'][dfb.a.str.startswith('o')] = 42 但是,此操作正在副本上,將無法使用。 >>> pd.set_option('mode.chained_assignment','warn') >>> dfb[dfb.a.str.startswith('o')]['c'] = 42 Traceback (most recent call last) ... SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_index,col_indexer] = value instead 鏈接的分配也可以在混合dtype框架中進行設置。 注意 這些設置規則適用於.loc/.iloc。 這是正確的訪問方法: In [341]: dfc = pd.DataFrame({'A': ['aaa', 'bbb', 'ccc'], 'B': [1, 2, 3]}) In [342]: dfc.loc[0, 'A'] = 11 In [343]: dfc Out[343]: A B 0 11 1 1 bbb 2 2 ccc 3 這可以在次工作,但它不能保證,因此應避免: In [344]: dfc = dfc.copy() In [345]: dfc['A'][0] = 111 In [346]: dfc Out[346]: A B 0 111 1 1 bbb 2 2 ccc 3 這根本不起作用,因此應避免: >>> pd.set_option('mode.chained_assignment','raise') >>> dfc.loc[0]['A'] = 1111 Traceback (most recent call last) ... SettingWithCopyException: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_index,col_indexer] = value instead 警告 鏈接的作業警告/異常旨在通知用戶可能無效的作業。可能存在誤報;意外報告鏈接分配的情況