Pandas數(shù)據(jù)索引核心:loc與iloc的深度解析與實戰(zhàn)避坑指南
1. 項目概述為什么loc和iloc是Pandas的靈魂如果你用過Pandas處理數(shù)據(jù)那對loc和iloc這兩個方法一定不陌生。它們就像是打開數(shù)據(jù)寶庫的兩把鑰匙一把叫“標(biāo)簽”一把叫“位置”。但很多朋友包括我剛開始用的時候都容易把它們搞混或者只停留在“l(fā)oc用標(biāo)簽iloc用整數(shù)”這個淺層理解上。結(jié)果就是寫出來的代碼要么運行報錯要么選出來的數(shù)據(jù)不是自己想要的調(diào)試半天效率極低。我見過不少同事在處理一個簡單的數(shù)據(jù)篩選任務(wù)時因為對這兩個方法的邊界條件理解不透寫出的df.loc[0:5]本意是想選前6行結(jié)果在索引不是默認(rèn)整數(shù)時選出來的數(shù)據(jù)完全不對導(dǎo)致后續(xù)分析全盤皆錯。這不僅僅是浪費了時間更可能因為數(shù)據(jù)錯誤得出誤導(dǎo)性的結(jié)論。所以今天我就想結(jié)合我這些年踩過的坑和積累的經(jīng)驗把loc和iloc掰開了、揉碎了講清楚。這不僅僅是兩個函數(shù)的用法更是理解Pandas數(shù)據(jù)索引底層邏輯的基石。掌握了它們你才能說真正會“定位”Pandas里的數(shù)據(jù)無論是處理幾十行的測試數(shù)據(jù)還是操縱百萬行級別的商業(yè)數(shù)據(jù)都能得心應(yīng)手。簡單來說loc和iloc的核心區(qū)別在于索引的參照系不同。loc是基于軸標(biāo)簽index和columns的“名字”進(jìn)行選擇的而iloc是基于軸位置從0開始的整數(shù)位置進(jìn)行選擇的。這個根本性的差異衍生出了它們在切片、布爾索引、函數(shù)應(yīng)用等幾乎所有場景下的不同行為。接下來我們就從最基礎(chǔ)的場景開始一步步深入到高級用法和那些容易踩坑的細(xì)節(jié)里。2. 核心概念辨析標(biāo)簽與位置的本質(zhì)差異在深入代碼之前我們必須先建立正確的心理模型。你可以把DataFrame想象成一張Excel表格。這張表格有行和列Pandas為它們分別設(shè)置了“坐標(biāo)系統(tǒng)”。2.1 標(biāo)簽索引loc按“名字”找人loc使用的坐標(biāo)系統(tǒng)是標(biāo)簽。行的標(biāo)簽就是索引index列的標(biāo)簽就是列名columns。這就像你用“姓名”和“部門”來定位一個同事一樣。關(guān)鍵特性包含端點在使用切片時loc是包含起始和結(jié)束標(biāo)簽的。這是與Python原生列表切片以及iloc最顯著的區(qū)別之一。靈活的數(shù)據(jù)類型索引和列名可以是整數(shù)、字符串、甚至日期時間類型。loc不關(guān)心它們的實際值是什么類型只把它們當(dāng)作唯一的標(biāo)識符。與索引順序強相關(guān)loc的查找效率與索引的排序和唯一性有很大關(guān)系。如果索引是排序且唯一的Pandas會用更快的哈希查找否則可能需要遍歷。舉個例子假設(shè)我們有一個員工信息表import pandas as pd data { ‘姓名‘: [‘張三‘, ‘李四‘, ‘王五‘, ‘趙六‘], ‘部門‘: [‘技術(shù)部‘, ‘市場部‘, ‘技術(shù)部‘, ‘人事部‘], ‘年齡‘: [28, 32, 25, 35], ‘入職年份‘: [2019, 2017, 2020, 2015] } df pd.DataFrame(data) df.set_index(‘姓名‘, inplaceTrue) # 將‘姓名‘列設(shè)為索引 print(df)輸出部門 年齡 入職年份 姓名 張三 技術(shù)部 28 2019 李四 市場部 32 2017 王五 技術(shù)部 25 2020 趙六 人事部 35 2015現(xiàn)在我想獲取“李四”的信息并只看他的“部門”和“年齡”。用loc就是這樣# 選取單個標(biāo)簽行 print(df.loc[‘李四‘]) # 輸出一個Series部門-市場部 年齡-32 入職年份-2017 # 選取單個標(biāo)簽行和單個標(biāo)簽列 print(df.loc[‘李四‘, ‘部門‘]) # 輸出標(biāo)量‘市場部‘ # 選取單個標(biāo)簽行和多個標(biāo)簽列 print(df.loc[‘李四‘, [‘部門‘, ‘年齡‘]]) # 輸出一個Series2.2 位置索引iloc按“座位號”找人iloc使用的坐標(biāo)系統(tǒng)是整數(shù)位置。無論你的索引和列名是什么它只認(rèn)從0開始計數(shù)的第幾行、第幾列。這就像電影院里的座位第1排第3座不管坐的是誰位置是固定的。關(guān)鍵特性不包含端點在使用切片時iloc遵循Python的“左閉右開”規(guī)則。df.iloc[0:3]選取的是第0, 1, 2行不包括第3行。只接受整數(shù)iloc的索引器必須是整數(shù)、整數(shù)列表、整數(shù)切片或布爾數(shù)組。傳入字符串會直接報錯。與數(shù)據(jù)順序強相關(guān)iloc的性能非常穩(wěn)定且高效因為它直接根據(jù)內(nèi)存偏移量計算位置與索引內(nèi)容無關(guān)。繼續(xù)用上面的df# 選取第2行位置1因為從0開始 print(df.iloc[1]) # 輸出李四的信息 # 選取第2行第1列位置[1, 0] print(df.iloc[1, 0]) # 輸出‘市場部‘ # 選取前兩行所有列 print(df.iloc[0:2, :]) # 等價于 df.iloc[:2] # 輸出張三和李四的信息注意這里有一個新手超級易錯點df.iloc[0:2]選取的是位置0和1的行而df.loc[0:2]如果索引是整數(shù)0,1,2,3選取的是標(biāo)簽為0,1,2的行。如果索引不是連續(xù)的整數(shù)或者有其他類型df.loc[0:2]的行為會完全不同。務(wù)必時刻清楚你用的是哪把“鑰匙”。2.3 何時該用loc何時該用iloc這個選擇沒有絕對的對錯但有一些最佳實踐用loc當(dāng)你的索引有意義時如果你的行索引是ID、日期、姓名等有業(yè)務(wù)含義的標(biāo)簽?zāi)敲磍oc是更直觀、更安全的選擇。你的代碼讀起來就像在說“給我找‘張三’的數(shù)據(jù)”。用iloc當(dāng)你只關(guān)心順序位置時當(dāng)你需要“前100個樣本”、“每隔5行取一個”、“最后10行”時iloc是更直接的選擇。它不依賴于索引的具體內(nèi)容行為可預(yù)測。在循環(huán)或性能敏感代碼中考慮ilociloc的純整數(shù)索引通常比loc的標(biāo)簽查找更快尤其是在索引未排序或非唯一的情況下。修改數(shù)據(jù)時慎用鏈?zhǔn)劫x值無論是loc還是iloc都盡量避免df[‘a(chǎn)‘].loc[0] 1這種鏈?zhǔn)剿饕x值因為它可能觸發(fā)SettingWithCopyWarning。正確的做法是使用df.loc[0, ‘a(chǎn)‘] 1。3. 單維度與多維度的數(shù)據(jù)選取實戰(zhàn)理解了基本概念后我們來看看它們在實際選取數(shù)據(jù)時的各種花樣。選取可以分為單點選取、多點選取和區(qū)間切片選取。3.1 選取單個元素標(biāo)量這是最簡單的操作目的是獲取一個具體的值。使用loc:# 語法df.loc[行標(biāo)簽 列標(biāo)簽] value df.loc[‘李四‘, ‘年齡‘] print(value) # 輸出32如果只傳入行標(biāo)簽會返回該行的Series。如果行、列標(biāo)簽都傳入則返回該位置的標(biāo)量值。使用iloc:# 語法df.iloc[行位置 列位置] value df.iloc[1, 1] # 第2行第2列‘年齡‘列 print(value) # 輸出32實操心得在Jupyter Notebook或交互式環(huán)境中當(dāng)你用df.loc[‘某個標(biāo)簽‘]獲取一個Series時顯示可能很長。如果你只想快速看一眼某個特定列的值使用df.loc[‘某個標(biāo)簽‘, ‘特定列名‘]會更高效。另外當(dāng)索引是日期時間類型時loc可以直接用字符串查詢?nèi)鏳f.loc[‘2023-01-01‘]非常方便。3.2 選取單行或單列Series選取整行或整列會返回一個Pandas Series對象。選取單行# loc 按標(biāo)簽選行 row_by_name df.loc[‘王五‘] # 返回‘王五‘這一行的Series # iloc 按位置選行 row_by_position df.iloc[2] # 返回第3行的Series (位置2)選取單列雖然更常見的列選取方式是df[‘列名‘]但loc/iloc也能做而且在與行選擇結(jié)合時更統(tǒng)一。# loc 按標(biāo)簽選列 col_by_name df.loc[:, ‘年齡‘] # 選取‘年齡‘這一整列返回Series # 注意前面的冒號‘:‘表示選取所有行 # iloc 按位置選列 col_by_position df.iloc[:, 1] # 選取第2列位置1返回Series注意事項df[‘年齡‘]和df.loc[:, ‘年齡‘]在大多數(shù)情況下結(jié)果一樣但后者是更明確的“標(biāo)簽索引”操作。當(dāng)列名恰好是整數(shù)時df[1]會報錯因為會被解釋為選取列名為1的列而df.iloc[:, 1]則能正確選取第二列。為了代碼清晰我個人的習(xí)慣是選取列時簡單的用df[‘col‘]復(fù)雜的、需要行列組合的統(tǒng)一用loc/iloc。3.3 選取多行多列DataFrame子集這是數(shù)據(jù)分析中最常見的操作之一用于從原數(shù)據(jù)中裁剪出感興趣的部分。使用列表進(jìn)行多點選取# loc選取指定的多個行和列 sub_df df.loc[[‘張三‘, ‘趙六‘], [‘部門‘, ‘入職年份‘]] # 得到一個只包含張三和趙六的‘部門‘和‘入職年份‘的DataFrame # iloc選取指定的多個位置 sub_df df.iloc[[0, 3], [0, 2]] # 選取第1、4行第1、3列使用切片進(jìn)行區(qū)間選取這里是核心差異點# 假設(shè)df的索引是默認(rèn)的0,1,2,3 df_default_index df.reset_index() # 重置索引為0,1,2,3 # loc 切片包含結(jié)束點 slice_loc df_default_index.loc[1:3] # 選取標(biāo)簽為1,2,3的行共3行 print(slice_loc.shape) # 可能是 (3, 4) # iloc 切片不包含結(jié)束點 slice_iloc df_default_index.iloc[1:3] # 選取位置為1,2的行共2行 print(slice_iloc.shape) # (2, 4)高級切片與布爾索引結(jié)合布爾索引是過濾數(shù)據(jù)的利器loc與之結(jié)合是天作之合。# 選取‘技術(shù)部‘的所有員工 tech_employees df.loc[df[‘部門‘] ‘技術(shù)部‘] # df[‘部門‘] ‘技術(shù)部‘ 產(chǎn)生一個布爾Seriesloc用它來篩選行 # 選取‘技術(shù)部‘且年齡大于26的員工 tech_senior df.loc[(df[‘部門‘] ‘技術(shù)部‘) (df[‘年齡‘] 26)] # 注意多個條件要用括號括起來并用 與、|或、~非連接 # 在篩選的基礎(chǔ)上再選取特定列 tech_senior_info df.loc[(df[‘部門‘] ‘技術(shù)部‘) (df[‘年齡‘] 26), [‘年齡‘, ‘入職年份‘]]iloc也可以結(jié)合布爾索引但通常需要先通過條件計算出布爾數(shù)組列表。# 獲取‘年齡‘大于30的布爾序列 condition df[‘年齡‘] 30 # 將這個布爾序列轉(zhuǎn)換為列表用于iloc不常用更推薦用loc做布爾篩選 positions condition[condition].index.tolist() # 獲取為True的索引標(biāo)簽列表 # 但此時我們已經(jīng)有了標(biāo)簽直接用loc更簡單df.loc[condition]踩坑記錄布爾索引中的條件運算符,|,~的優(yōu)先級高于,等比較運算符。因此務(wù)必給每個條件加上括號否則會引發(fā)不可預(yù)知的錯誤或報錯。(df[‘A‘] 1) (df[‘B‘] 2)是正確的df[‘A‘] 1 df[‘B‘] 2是錯誤的。4. 高級技巧與性能優(yōu)化指南當(dāng)你熟練掌握了基本選取后一些高級技巧可以讓你代碼更簡潔、運行更高效。4.1 使用at和iat進(jìn)行快速標(biāo)量訪問如果你百分之百確定只是要獲取或設(shè)置一個單一單元格的值那么at標(biāo)簽和iat位置比loc和iloc更快。# 獲取單個值 fast_value_loc df.at[‘李四‘, ‘年齡‘] # 類比 df.loc[‘李四‘, ‘年齡‘] fast_value_iloc df.iat[1, 1] # 類比 df.iloc[1, 1] # 設(shè)置單個值 df.at[‘李四‘, ‘年齡‘] 33 # 比 df.loc[‘李四‘, ‘年齡‘] 33 稍快 df.iat[1, 1] 33它們的語法更簡潔并且在底層做了優(yōu)化對于在循環(huán)中頻繁訪問單個元素的情況性能提升明顯。但在可讀性上loc/iloc更勝一籌因為大家更熟悉。我個人的建議是在明確需要性能優(yōu)化的熱點代碼中使用at/iat在一般業(yè)務(wù)邏輯中使用loc/iloc以保持清晰。4.2 使用isin()進(jìn)行多值篩選當(dāng)需要篩選某列值屬于一個特定集合的記錄時isin()方法非常有用它比寫多個OR條件簡潔得多。# 篩選部門為‘技術(shù)部‘或‘市場部‘的員工 target_departments [‘技術(shù)部‘, ‘市場部‘] employees_in_target df.loc[df[‘部門‘].isin(target_departments)]4.3 利用query()方法進(jìn)行表達(dá)式查詢對于復(fù)雜的多條件篩選query()方法提供了一種更接近自然語言的寫法尤其適合條件很多的時候。# 使用query篩選 result df.query(‘部門 “技術(shù)部“ and 年齡 25‘) # 等價于 df.loc[(df[‘部門‘] ‘技術(shù)部‘) (df[‘年齡‘] 25)]query()的優(yōu)點是字符串表達(dá)式更清晰特別是列名包含空格或特殊字符時需要用反引號包裹。但它的性能在簡單條件下可能略遜于直接的布爾索引且表達(dá)式中的變量引用需要注意使用符號。在可讀性和簡單性要求高時推薦使用。4.4 性能考量與最佳實踐避免在循環(huán)中使用loc/iloc逐行處理這是Pandas性能的“頭號殺手”。Pandas是向量化計算的庫應(yīng)該盡量用整個Series或DataFrame的操作代替循環(huán)。例如不要用for i in range(len(df)): df.loc[i, ‘new_col‘] ...而應(yīng)該用df[‘new_col‘] df[‘old_col‘].apply(func)或向量化運算。索引的重要性對于loc一個排序且唯一的索引能極大提升查詢速度。如果你的數(shù)據(jù)經(jīng)常需要按某個鍵查詢考慮使用set_index()將其設(shè)為索引。使用df.sort_index()對索引排序也能提升loc范圍查詢的性能。ilocvsloc性能在索引是簡單整數(shù)且已排序的情況下兩者性能差異不大。但如果索引是復(fù)雜的字符串或未排序iloc通常更快因為它是直接的位置尋址。使用.copy()避免鏈?zhǔn)劫x值警告當(dāng)你通過篩選得到一個子DataFrame并想修改它時Pandas可能會分不清你是想修改視圖還是副本。最安全的做法是顯式拷貝sub_df df.loc[condition].copy()。這樣后續(xù)對sub_df的修改就不會觸發(fā)SettingWithCopyWarning。5. 常見問題排查與避坑實錄即使理解了原理在實際編碼中還是會遇到各種奇怪的問題。下面是我總結(jié)的幾個高頻“坑點”及其解決方案。5.1 KeyError: ‘[label] not found in index‘這是使用loc時最常見的錯誤。原因你試圖用loc訪問一個不存在的行或列標(biāo)簽。排查檢查標(biāo)簽拼寫是否正確包括大小寫和空格。使用df.index和df.columns查看當(dāng)前確切的索引和列名。如果標(biāo)簽是動態(tài)生成的先使用label in df.index或label in df.columns進(jìn)行判斷。解決label_to_find ‘某個名字‘ if label_to_find in df.index: data df.loc[label_to_find] else: print(f“標(biāo)簽 ‘{label_to_find}‘ 不存在“) # 或者進(jìn)行其他處理如使用默認(rèn)值 data None5.2 使用切片時結(jié)果與預(yù)期不符問題df.loc[0:5]我以為選了6行為什么結(jié)果不對原因混淆了loc和iloc的切片語義或者索引不是連續(xù)的整數(shù)。loc[0:5]選取索引標(biāo)簽從0到5包含5的所有行。如果索引是[0,1,3,5,7]那么它會選取標(biāo)簽0,1,3,5。iloc[0:5]選取位置0到4不包含5的行即前5行。解決明確你的意圖是按標(biāo)簽選還是按位置選如果索引是整數(shù)但不是連續(xù)的想按位置選前N行務(wù)必使用iloc[:N]。打印df.index查看索引的實際值。5.3 SettingWithCopyWarning 警告問題在對數(shù)據(jù)進(jìn)行賦值時看到令人困惑的SettingWithCopyWarning。原因Pandas無法確定你的操作是在原始數(shù)據(jù)的視圖view上還是副本copy上進(jìn)行修改。在視圖上修改可能會影響原始數(shù)據(jù)這是不明確且危險的行為。典型鏈?zhǔn)剿饕龍鼍? 危險可能觸發(fā)警告 df[df[‘年齡‘] 30][‘新列‘] ‘高級‘ # 或 df.loc[df[‘年齡‘] 30][‘新列‘] ‘高級‘ # 注意這里有兩個‘[ ]‘解決使用單次loc賦值這是最推薦、最清晰的方式。df.loc[df[‘年齡‘] 30, ‘新列‘] ‘高級‘這條語句明確地通過loc在原始df上對滿足條件的行進(jìn)行賦值。需要副本時顯式拷貝如果你確實想在一個篩選后的副本上操作并保留原始數(shù)據(jù)不變請顯式使用.copy()。df_old df.copy() sub_df df_old.loc[df_old[‘年齡‘] 30].copy() # 顯式創(chuàng)建副本 sub_df[‘新列‘] ‘高級‘ # 安全地在副本上修改5.4 布爾索引條件組合錯誤問題多個條件組合時結(jié)果不對或直接報錯ValueError: The truth value of a Series is ambiguous...。原因使用了Python原生的and,or,not而不是Pandas的位運算符,|,~并且沒有給條件加括號。錯誤示例# 錯誤1使用and/or df.loc[df[‘A‘] 1 and df[‘B‘] 2] # 報錯 # 錯誤2條件未加括號 df.loc[df[‘A‘] 1 df[‘B‘] 2] # 邏輯錯誤先計算 1 df[‘B‘]正確示例# 正確使用 每個條件用括號包裹 df.loc[(df[‘A‘] 1) (df[‘B‘] 2)] # 復(fù)雜條件組合 df.loc[(df[‘部門‘] ‘技術(shù)部‘) ((df[‘年齡‘] 25) | (df[‘年齡‘] 35))]5.5 處理多層索引MultiIndex當(dāng)DataFrame有行和列的多層索引時loc的用法需要擴展。示例# 創(chuàng)建一個簡單的多層索引DataFrame arrays [[‘A‘, ‘A‘, ‘B‘, ‘B‘], [1, 2, 1, 2]] index pd.MultiIndex.from_arrays(arrays, names(‘first‘, ‘second‘)) df_multi pd.DataFrame({‘value‘: [10, 20, 30, 40]}, indexindex) # 使用loc選取 print(df_multi.loc[‘A‘]) # 選取第一層索引為‘A‘的所有行 print(df_multi.loc[(‘A‘, 1)]) # 選取第一層為‘A‘第二層為1的行 print(df_multi.loc[‘A‘, :]) # 同上選取所有列 print(df_multi.loc[(‘A‘, 1), :]) # 選取特定組合對于多層索引loc的索引器可以是一個元組(level1_key, level2_key, ...)。你也可以使用slice(None)來指定某一層全選或者使用pd.IndexSlice進(jìn)行更復(fù)雜的切片。6. 綜合案例一個完整的數(shù)據(jù)清洗與篩選流程讓我們通過一個模擬的真實場景把loc和iloc的各種用法串起來。假設(shè)我們有一個銷售數(shù)據(jù)表sales_df。import pandas as pd import numpy as np # 創(chuàng)建示例數(shù)據(jù) np.random.seed(42) dates pd.date_range(‘20230101‘, periods100, freq‘D‘) products [‘Product_A‘, ‘Product_B‘, ‘Product_C‘] regions [‘North‘, ‘South‘, ‘East‘, ‘West‘] data { ‘Date‘: np.random.choice(dates, 200), ‘Product‘: np.random.choice(products, 200), ‘Region‘: np.random.choice(regions, 200), ‘Sales‘: np.random.randint(50, 500, 200), ‘Customer_ID‘: range(1000, 1200) # 假設(shè)有200個訂單 } sales_df pd.DataFrame(data) # 為了演示我們故意制造一些缺失值和異常值 sales_df.loc[10:15, ‘Sales‘] np.nan sales_df.loc[50, ‘Sales‘] 10000 # 一個異常高值 print(“原始數(shù)據(jù)概覽“) print(sales_df.head()) print(sales_df.info())任務(wù)清洗數(shù)據(jù)并分析“Product_A”在“North”地區(qū)2023年第一季度1-3月的銷售情況。步驟1設(shè)置合適的索引由于我們要按日期和產(chǎn)品查詢將Date和Product設(shè)為多層索引可能更高效。# 先按Date排序這對基于時間的切片很重要 sales_df.sort_values(‘Date‘, inplaceTrue) # 設(shè)置索引 sales_df.set_index([‘Date‘, ‘Product‘], inplaceTrue) print(“設(shè)置索引后的數(shù)據(jù)“) print(sales_df.head())步驟2處理缺失值和異常值# 1. 識別缺失值使用loc配合isna() missing_sales sales_df.loc[sales_df[‘Sales‘].isna()] print(f“有 {len(missing_sales)} 條銷售記錄缺失?!? # 用該產(chǎn)品在該地區(qū)的平均銷售額填充缺失值假設(shè)策略如此 # 先臨時重置索引方便分組計算 temp_df sales_df.reset_index() # 計算每個產(chǎn)品-地區(qū)的平均銷售額忽略NaN mean_sales temp_df.groupby([‘Product‘, ‘Region‘])[‘Sales‘].mean() # 定義一個填充函數(shù) def fill_na(row): if pd.isna(row[‘Sales‘]): key (row[‘Product‘], row[‘Region‘]) return mean_sales.get(key, row[‘Sales‘]) # 如果找不到對應(yīng)均值返回原值NaN return row[‘Sales‘] # 應(yīng)用填充這里為了演示我們創(chuàng)建一個新列。實際中可能直接修改 temp_df[‘Sales_Filled‘] temp_df.apply(fill_na, axis1) # 再設(shè)回索引 sales_df_filled temp_df.set_index([‘Date‘, ‘Product‘]) sales_df_filled.drop(columns‘Sales‘, inplaceTrue) sales_df_filled.rename(columns{‘Sales_Filled‘: ‘Sales‘}, inplaceTrue) # 2. 處理異常值假設(shè)我們認(rèn)為銷售額大于3000的是異常值 # 使用布爾索引定位異常值 outliers sales_df_filled.loc[sales_df_filled[‘Sales‘] 3000] print(f“識別到 {len(outliers)} 條異常銷售記錄“) print(outliers) # 策略將異常值截斷為99%分位數(shù) percentile_99 sales_df_filled[‘Sales‘].quantile(0.99) sales_df_filled.loc[sales_df_filled[‘Sales‘] 3000, ‘Sales‘] percentile_99 print(f“已將大于3000的銷售額替換為99%分位數(shù): {percentile_99:.2f}“)步驟3執(zhí)行核心篩選任務(wù)# 目標(biāo)篩選 Product_A 在 North 地區(qū)2023年第一季度的數(shù)據(jù) # 注意索引現(xiàn)在是 (Date, Product) # 方法A使用loc的多層索引查詢 # 我們需要篩選行Date在Q1且Product為‘Product_A‘列需要Region為‘North‘ # 對于行我們需要對第一層(Date)切片第二層(Product)精確匹配 start_date ‘2023-01-01‘ end_date ‘2023-03-31‘ # 由于索引是DatetimeIndexloc可以直接用字符串切片 # 但是我們的索引是MultiIndex需要用到pd.IndexSlice idx pd.IndexSlice target_data sales_df_filled.loc[idx[start_date:end_date, ‘Product_A‘], :] # 現(xiàn)在target_data包含了Q1所有Product_A的記錄 # 再從這些記錄中篩選Region為‘North‘的 target_data_north target_data.loc[target_data[‘Region‘] ‘North‘] print(f“Product_A在North地區(qū)Q1的銷售記錄有 {len(target_data_north)} 條。“) print(target_data_north.head()) # 方法B重置索引使用更直觀的布爾索引當(dāng)查詢條件復(fù)雜時可能更清晰 # sales_df_reset sales_df_filled.reset_index() # target_data_b sales_df_reset[ # (sales_df_reset[‘Product‘] ‘Product_A‘) # (sales_df_reset[‘Region‘] ‘North‘) # (sales_df_reset[‘Date‘] ‘2023-01-01‘) # (sales_df_reset[‘Date‘] ‘2023-03-31‘) # ] # 兩種方法結(jié)果一致選擇哪種取決于個人習(xí)慣和索引結(jié)構(gòu)。步驟4對篩選結(jié)果進(jìn)行分析if not target_data_north.empty: # 計算基本統(tǒng)計量 total_sales target_data_north[‘Sales‘].sum() avg_sales target_data_north[‘Sales‘].mean() max_sale target_data_north[‘Sales‘].max() min_sale target_data_north[‘Sales‘].min() print(f“\n分析結(jié)果“) print(f“總銷售額: {total_sales:.2f}“) print(f“平均每單銷售額: {avg_sales:.2f}“) print(f“最高單筆銷售額: {max_sale:.2f}“) print(f“最低單筆銷售額: {min_sale:.2f}“) # 也許我們還想看銷售額的分布使用iloc快速選取前幾行查看 print(f“\n銷售額前5的訂單“) # 先按銷售額降序排序 top_sales target_data_north.sort_values(by‘Sales‘, ascendingFalse) # 用iloc選取前5行 print(top_sales.iloc[:5]) else: print(“沒有找到符合條件的數(shù)據(jù)?!?通過這個案例你可以看到loc和iloc如何與Pandas的其他功能如缺失值處理、分組聚合、時間序列切片協(xié)同工作完成一個從數(shù)據(jù)準(zhǔn)備到分析的全流程。關(guān)鍵在于根據(jù)數(shù)據(jù)的結(jié)構(gòu)索引和你的查詢意圖靈活選擇最合適的“鑰匙”。當(dāng)索引設(shè)計得當(dāng)時loc能讓查詢語句非常直觀而當(dāng)需要進(jìn)行基于順序或位置的操作時iloc則無可替代。

相關(guān)新聞

國產(chǎn)算力再迎突破!國產(chǎn)硬件順利適配超大參數(shù) MoE 大模型

國產(chǎn)算力再迎突破!國產(chǎn)硬件順利適配超大參數(shù) MoE 大模型

最近這段時間,國內(nèi)人工智能算力方面有了一定的技術(shù)進(jìn)步。我們國內(nèi)自主研發(fā)的算力硬件設(shè)備,已經(jīng)成功適配了參數(shù)規(guī)模很大的MoE混合專家大模型。這次的技術(shù)落地彌補了國產(chǎn)算力之前存在的一些不足,讓國內(nèi)自主算力體系變得更加完整,也給…

2026/8/1 10:10:03 閱讀更多
拋帳完成是什么意思

拋帳完成是什么意思

“拋賬完成”是企業(yè)管理軟件(尤其是ERP系統(tǒng))里的一個專業(yè)術(shù)語,簡單來說,就是指業(yè)務(wù)數(shù)據(jù)已經(jīng)成功地從業(yè)務(wù)部門流轉(zhuǎn)到了財務(wù)部門,并生成了相應(yīng)的會計憑證-3-5。 這個過程就像業(yè)務(wù)部門把工作成果“移交”給財務(wù)&#xff…

2026/8/1 10:10:03 閱讀更多
MATLAB bwconncomp連通分量分析:從算法原理到工程實踐

MATLAB bwconncomp連通分量分析:從算法原理到工程實踐

1. 從“數(shù)白點”到連通分量:bwconncomp的工程價值在圖像處理,尤其是二值圖像分析領(lǐng)域,我們經(jīng)常遇到一個看似簡單卻至關(guān)重要的任務(wù):數(shù)清楚圖像里有多少個獨立的“物體”。比如,在一張細(xì)胞顯微圖像中,我們需要…

2026/8/1 11:00:36 閱讀更多
C語言二維數(shù)組傳參:四種方式詳解與實戰(zhàn)選型指南

C語言二維數(shù)組傳參:四種方式詳解與實戰(zhàn)選型指南

1. 二維數(shù)組傳參:一個老C程序員繞不開的坎 干了十幾年C語言開發(fā),從單片機到服務(wù)器后臺,二維數(shù)組作為函數(shù)參數(shù)這個問題,幾乎在每次代碼評審或帶新人時都會碰到。新手容易懵,老手也偶爾會在這里踩坑。為什么它這么“麻煩…

2026/8/1 11:00:36 閱讀更多
Opus 5大模型技術(shù)解析:性能瓶頸、成本優(yōu)化與工程實踐指南

Opus 5大模型技術(shù)解析:性能瓶頸、成本優(yōu)化與工程實踐指南

最近不少開發(fā)者都在討論一個現(xiàn)象:期待已久的Opus 5模型發(fā)布后,實際體驗卻與預(yù)期有差距。這不僅僅是"又一個AI模型不好用"的簡單吐槽,背后反映的是大模型技術(shù)發(fā)展到一個新階段后,開發(fā)者面臨的實際挑戰(zhàn)。 如果你正在考慮…

2026/8/1 10:50:36 閱讀更多
AMAT 0100-02186 I/O 分配 PCB

AMAT 0100-02186 I/O 分配 PCB

AMAT 0100-02186 I/O分配PCB板是應(yīng)用材料(Applied Materials)公司生產(chǎn)的一款用于半導(dǎo)體設(shè)備的I/O信號分配電路板。該型號(0100-02186)的核心特點如下:專用于Endura等半導(dǎo)體工藝腔室。集成信號路由與分配功能。連接控制…

2026/8/1 0:09:33 閱讀更多
Nissei Corp FFMN-32L-10-T0 40AX 三相異步電動機

Nissei Corp FFMN-32L-10-T0 40AX 三相異步電動機

Nissei Corp FFMN-32L-10-T0 40AX 三相異步電動機是日本日清(Nissei)品牌的一款工業(yè)用三相異步電機,適用于自動化設(shè)備及通用機械驅(qū)動。該型號(FFMN-32L-10-T0 40AX)的核心特點如下:三相交流異步電動機。額定…

2026/8/1 0:09:33 閱讀更多
AMAT 0100-02186 I/O 分配 PCB

AMAT 0100-02186 I/O 分配 PCB

AMAT 0100-02186 I/O分配PCB板是應(yīng)用材料(Applied Materials)公司生產(chǎn)的一款用于半導(dǎo)體設(shè)備的I/O信號分配電路板。該型號(0100-02186)的核心特點如下:專用于Endura等半導(dǎo)體工藝腔室。集成信號路由與分配功能。連接控制…

2026/8/1 0:09:33 閱讀更多
Nissei Corp FFMN-32L-10-T0 40AX 三相異步電動機

Nissei Corp FFMN-32L-10-T0 40AX 三相異步電動機

Nissei Corp FFMN-32L-10-T0 40AX 三相異步電動機是日本日清(Nissei)品牌的一款工業(yè)用三相異步電機,適用于自動化設(shè)備及通用機械驅(qū)動。該型號(FFMN-32L-10-T0 40AX)的核心特點如下:三相交流異步電動機。額定…

2026/8/1 0:09:33 閱讀更多