據(jù)處理全攻略:從數(shù)據(jù)結(jié)構(gòu)到清洗實(shí)戰(zhàn))
但凡用Python做數(shù)據(jù)分析pandas是你繞不開的一個(gè)庫(kù)。我見過(guò)不少新手下載了一堆教程結(jié)果連數(shù)據(jù)結(jié)構(gòu)都沒(méi)搞明白就上手跑代碼最后被各種報(bào)錯(cuò)勸退。也有朋友在頭歌Educoder平臺(tái)上做pandas作業(yè)題目看著簡(jiǎn)單但提交評(píng)測(cè)就是過(guò)不了問(wèn)我能不能一次性把pandas基礎(chǔ)講清楚。這篇文章我就以實(shí)際使用經(jīng)驗(yàn)為主線把pandas從安裝、數(shù)據(jù)結(jié)構(gòu)創(chuàng)建、讀寫Excel和文本文件、數(shù)據(jù)類型轉(zhuǎn)換、正則表達(dá)式配合、數(shù)據(jù)清洗一直到ewm函數(shù)參數(shù)這些高頻考點(diǎn)全部串一遍。文中的代碼示例都是我平時(shí)工作里直接能用的寫法每個(gè)關(guān)鍵參數(shù)我都盡量解釋“為什么這么設(shè)”你照著敲一遍基本就能應(yīng)付日常數(shù)據(jù)處理和頭歌上的基礎(chǔ)關(guān)卡了。適合剛學(xué)Python數(shù)據(jù)分析的初學(xué)者也適合那些用過(guò)pandas但遇到報(bào)錯(cuò)還是一頭霧水的朋友。1. 環(huán)境準(zhǔn)備與安裝別讓環(huán)境問(wèn)題擋住第一步1.1 PyCharm里安裝pandas包的兩種方式先說(shuō)安裝。很多人在PyCharm里裝pandas第一反應(yīng)是打開File菜單去找Settings再逐個(gè)點(diǎn)開Project下的Python Interpreter點(diǎn)右上角的加號(hào)搜索pandas等它轉(zhuǎn)圈下載。這種方式本身沒(méi)錯(cuò)但有一個(gè)問(wèn)題下載源默認(rèn)是官方PyPI在國(guó)內(nèi)網(wǎng)絡(luò)環(huán)境下經(jīng)常跑到一半就超時(shí)失敗。我的建議是先把pip的下載源換成國(guó)內(nèi)鏡像比如清華的源再來(lái)裝。第二種方式是直接在PyCharm底部的Terminal終端里執(zhí)行pip install pandas如果當(dāng)前Python環(huán)境不是系統(tǒng)自帶的而是項(xiàng)目里單獨(dú)創(chuàng)建的虛擬環(huán)境要確認(rèn)這個(gè)終端確實(shí)激活了對(duì)應(yīng)的虛擬環(huán)境。判斷方法很簡(jiǎn)單終端命令行的前面如果出現(xiàn)了項(xiàng)目名比如(venv) C:\Users\...這樣說(shuō)明是在虛擬環(huán)境里如果看不到項(xiàng)目名只是C:\Users\...那很可能裝到全局Python里去了PyCharm的項(xiàng)目解釋器里還是找不到pandas。如果你是剛裝了Anaconda那pandas早就內(nèi)置了打開PyCharm新建項(xiàng)目時(shí)解釋器記得選conda環(huán)境而不是默認(rèn)的Project Venv否則又會(huì)重復(fù)裝一遍。這里給一個(gè)檢查是否安裝成功的標(biāo)準(zhǔn)方法在終端或Python控制臺(tái)執(zhí)行import pandas as pd print(pd.__version__)能正常輸出版本號(hào)比如2.0.3就說(shuō)明環(huán)境OK。沒(méi)輸出或直接報(bào)ModuleNotFoundError那就說(shuō)明pandas沒(méi)裝對(duì)位置回到上面檢查解釋器。1.2 安裝后仍然報(bào)錯(cuò)的常見原因有一種情況特別坑明明在PyCharm的設(shè)置里看到pandas已經(jīng)安裝成功但運(yùn)行代碼還是提示找不到模塊。八成是因?yàn)镻yCharm的項(xiàng)目解釋器和你使用pip安裝時(shí)的Python是兩套環(huán)境。PyCharm里點(diǎn)擊右下角的解釋器名稱彈出的列表里可以看到當(dāng)前項(xiàng)目到底用的是哪一個(gè)Python解釋器然后在終端里執(zhí)行python -c import sys; print(sys.executable)看一下自己用的是哪一個(gè)。兩者一致才靠譜。還有兼容性問(wèn)題需要注意。pandas對(duì)Python版本有要求如果你還在用古老的Python 3.6甚至Python 2.7市面上新版pandas2.x系列裝不上去。這種情況下pip會(huì)嘗試下載一個(gè)對(duì)應(yīng)當(dāng)前Python版本的舊版pandas而舊版pandas在部分功能上和新代碼有差異。遇到這種情況建議升級(jí)Python環(huán)境起碼3.9以上否則做數(shù)據(jù)清洗時(shí)部分新參數(shù)會(huì)不生效排查起來(lái)很費(fèi)勁。2. 數(shù)據(jù)結(jié)構(gòu)創(chuàng)建先搞懂Series和DataFrame再動(dòng)手2.1 Series是一列帶標(biāo)簽的數(shù)據(jù)很多教程喜歡一上來(lái)就堆概念我換一種說(shuō)法Series在pandas里本質(zhì)上就是帶有索引的一維數(shù)組可以把它理解成一張單列的Excel表格。創(chuàng)建Series最常用的方式是從列表創(chuàng)建import pandas as pd s pd.Series([10, 20, 30, 40]) print(s)輸出結(jié)果里左邊是索引默認(rèn)0、1、2、3右邊是具體的值。如果你想讓索引有實(shí)際意義比如按日期排列可以顯式指定index參數(shù)s pd.Series([10, 20, 30, 40], index[周一, 周二, 周三, 周四])這里要注意一個(gè)細(xì)節(jié)index的長(zhǎng)度必須和數(shù)據(jù)的長(zhǎng)度一致否則會(huì)直接報(bào)ValueError: Length of values does not match length of index這是新手經(jīng)常觸發(fā)的錯(cuò)誤。創(chuàng)建一個(gè)Series只需要記住它是一維的、帶索引的、可以存任意類型的數(shù)據(jù)。在頭歌的pandas數(shù)據(jù)結(jié)構(gòu)創(chuàng)建題里常見的考法就是用字典去創(chuàng)建Seriess pd.Series({蘋果: 5.5, 香蕉: 3.2, 橘子: 4.8})字典的key自動(dòng)變成索引value變成數(shù)據(jù)這比自己手動(dòng)指定index更方便推薦優(yōu)先使用。2.2 DataFrame是二維表格的核心DataFrame可以理解成Excel里的一個(gè)工作表有行索引也有列索引。日常處理數(shù)據(jù)時(shí)99%的操作都在DataFrame上。最常見的創(chuàng)建方式是從字典創(chuàng)建字典的key變成列名value一般是列表列表的長(zhǎng)度必須一致df pd.DataFrame({ 姓名: [張三, 李四, 王五], 年齡: [25, 30, 22], 城市: [北京, 上海, 深圳] })還有幾個(gè)高頻創(chuàng)建方式需要掌握。第一種是從嵌套列表創(chuàng)建適合你手里是一行行數(shù)據(jù)的情況data [[張三, 25, 北京], [李四, 30, 上海], [王五, 22, 深圳]] df pd.DataFrame(data, columns[姓名, 年齡, 城市])第二種是從numpy數(shù)組創(chuàng)建適合用科學(xué)計(jì)算時(shí)把矩陣包裝成表格。第三種是從列表套字典的更復(fù)雜結(jié)構(gòu)中創(chuàng)建每條記錄一個(gè)字典columns會(huì)自動(dòng)統(tǒng)一。創(chuàng)建一個(gè)dataframe時(shí)一定要想清楚你是以“列為主”還是“行為主”這決定了應(yīng)該用字典套列表、列表套字典還是嵌套列表。為了方便起見我整理了一個(gè)Series和DataFrame的關(guān)鍵對(duì)比理解了這張表基礎(chǔ)題基本就穩(wěn)了數(shù)據(jù)結(jié)構(gòu)維度索引概念默認(rèn)索引創(chuàng)建方式Series一維單一索引0到n-1pd.Series(列表或字典)DataFrame二維行索引列索引0到n-1pd.DataFrame(字典或列表嵌套)Index對(duì)象一維特化的索引數(shù)組無(wú)默認(rèn)由DataFrame或Series自動(dòng)生成3. 數(shù)據(jù)讀寫Excel和文本文件是日常主力3.1 讀取Excel文件的幾個(gè)關(guān)鍵參數(shù)pandas讀寫Excel文件是數(shù)據(jù)分析里最常碰到的場(chǎng)景之一畢竟業(yè)務(wù)側(cè)的數(shù)據(jù)多數(shù)以Excel表格歸檔。讀取函數(shù)pd.read_excel()有幾個(gè)參數(shù)你必須要熟練第一個(gè)是sheet_name比如一個(gè)工作簿里有多個(gè)Sheet需要按名稱讀取df pd.read_excel(銷售數(shù)據(jù).xlsx, sheet_name2024年7月)如果不指定sheet_name默認(rèn)只會(huì)讀取第一個(gè)Sheet。sheet_name也可以傳入整數(shù)0表示第一個(gè)Sheet傳入列表還能一次讀取多個(gè)Sheet返回一個(gè)字典結(jié)構(gòu)不過(guò)新手期先掌握名稱讀取就夠了。第二個(gè)是header參數(shù)默認(rèn)值為0表示把第一行當(dāng)作列名。如果Excel表格上面有兩行大標(biāo)題真正的表頭在第三行那就需要設(shè)置header2pandas會(huì)自動(dòng)跳過(guò)上面兩行。反過(guò)來(lái)如果某個(gè)表格沒(méi)有表頭全是純數(shù)據(jù)就傳headerNone并用names[列1, 列2]手動(dòng)指定列名否則pandas會(huì)用0、1、2這樣的數(shù)字當(dāng)列名后續(xù)操作非常別扭。第三個(gè)高頻參數(shù)是usecols只讀取指定列以節(jié)省內(nèi)存比如usecols[姓名, 年齡]。寫出Excel文件的函數(shù)是to_excel()有一個(gè)參數(shù)官方默認(rèn)True但實(shí)踐中建議一定要設(shè)成False就是index參數(shù)df.to_excel(輸出結(jié)果.xlsx, indexFalse)如果不設(shè)indexFalse輸出文件里會(huì)多出一列從0開始的行索引這在交付給同事或交給老師評(píng)測(cè)時(shí)經(jīng)常算錯(cuò)誤格式。此外多Sheet寫出需要借助pd.ExcelWriter比如同時(shí)輸出兩個(gè)表格到同一個(gè)文件的不同Sheet里。3.2 文本文件讀取的核心參數(shù)這里說(shuō)的文本文件主要指CSV和TSV這類用分隔符劃分列的文件。read_csv()是讀取函數(shù)需要注意的坑比Excel多一些。第一個(gè)坑是編碼問(wèn)題。df pd.read_csv(訂單.csv, encodingutf-8)國(guó)內(nèi)Excel另存的CSV文件默認(rèn)是GBK編碼直接用utf-8讀取會(huì)報(bào)UnicodeDecodeError解決辦法是把encoding參數(shù)改成gbk。這里我說(shuō)一個(gè)經(jīng)驗(yàn)值讀Excel生成的文件報(bào)編碼錯(cuò)誤優(yōu)先試gbk讀程序生成的CSV優(yōu)先試utf-8兩種都不行再試gb18030這個(gè)編碼兼容性更強(qiáng)能覆蓋絕大多數(shù)中文場(chǎng)景。第二個(gè)坑是分隔符。默認(rèn)情況下read_csv默認(rèn)分隔符是逗號(hào)如果遇到制表符分隔的TSV文件就要指定sep\t。有些特殊文件用的是分號(hào)或豎線分隔同樣要用sep去匹配。第三個(gè)坑是skiprows和nrows。skiprows可以跳過(guò)文件前面若干行注釋或無(wú)效信息nrows則限制只讀取前N行適合在大文件上先快速預(yù)覽df_preview pd.read_csv(超大文件.csv, nrows100) # 先讀前100行看結(jié)構(gòu)寫出文本文件時(shí)有一個(gè)比Excel更容易踩的坑直接用to_csv(結(jié)果.csv)然后拿Excel打開這個(gè)文件中文全部變成亂碼。這是因?yàn)槟J(rèn)編碼是utf-8Excel默認(rèn)不認(rèn)。解決辦法很簡(jiǎn)單df.to_csv(結(jié)果.csv, indexFalse, encodingutf-8-sig)utf-8-sig編碼會(huì)在文件開頭加入一個(gè)BOM標(biāo)記Excel讀取時(shí)就能正確識(shí)別是utf-8編碼。這個(gè)小細(xì)節(jié)頭歌作業(yè)評(píng)測(cè)里也經(jīng)常用到輸出格式不規(guī)范會(huì)導(dǎo)致判題失敗。4. 數(shù)據(jù)類型轉(zhuǎn)換與正則表達(dá)式預(yù)處理的兩把利器4.1 用dtypes定位類型問(wèn)題和astype轉(zhuǎn)換pandas每一列都有數(shù)據(jù)類型常見的有int64、float64、object字符串為主、datetime64[ns]。查看所有列類型用df.dtypes屬性查看單列用df[列名].dtype。數(shù)據(jù)處理中最常見的類型問(wèn)題是讀進(jìn)來(lái)的數(shù)字列變成了object類型。例如Excel里某列有個(gè)別單元格是“-”或者“N/A”pandas就會(huì)把整列推斷成字符串后續(xù)做數(shù)值計(jì)算直接報(bào)錯(cuò)。遇到這種情況我慣用的方法是pd.to_numeric配合errors參數(shù)df[金額] pd.to_numeric(df[金額], errorscoerce)errorscoerce會(huì)把無(wú)法轉(zhuǎn)換的內(nèi)容強(qiáng)制變成NaN能轉(zhuǎn)的數(shù)字保留下來(lái)。這一步處理完后再去看那列到底有哪些非數(shù)字內(nèi)容用df[金額].isna()去定位。直接使用astype(int)在這種場(chǎng)景下往往直接拋異常因?yàn)樗谵D(zhuǎn)換時(shí)遇到非法值不會(huì)跳過(guò)所以我不建議對(duì)臟數(shù)據(jù)使用astype做類型轉(zhuǎn)換。但是如果手頭的數(shù)據(jù)是干凈的期望把浮點(diǎn)列轉(zhuǎn)成整數(shù)列astype就非常好用df[銷量] df[銷量].astype(int)這里順帶提一個(gè)常見坑某列明明顯示的是日期形式但用astype轉(zhuǎn)成日期類型會(huì)報(bào)錯(cuò)。正確做法是用pd.to_datetime()df[下單時(shí)間] pd.to_datetime(df[下單時(shí)間], format%Y-%m-%d)format參數(shù)加上最穩(wěn)雖然pandas會(huì)自動(dòng)推斷但遇到混合格式時(shí)會(huì)識(shí)別出錯(cuò)。日期格式字符串里%Y是四位年份%m是兩位月份%d是兩位日這些可以對(duì)照文檔查閱mac和Windows環(huán)境下表現(xiàn)一致。4.2 正則表達(dá)式在pandas中的應(yīng)用技巧熱搜詞里有人把“正則表達(dá)式”誤打成了“正在表達(dá)式”心想既然是高頻搜索詞那應(yīng)該不少人在pandas里用正則時(shí)遇到困難。正則表達(dá)式在pandas里的應(yīng)用核心是配合str訪問(wèn)器完成三類操作。第一類是篩選匹配模式的行用str.contains()加上正則# 篩選出所有包含手機(jī)號(hào)聯(lián)系人 df_mobile df[df[聯(lián)系方式].str.contains(r^1[3-9]\d{9}$, naFalse)]naFalse的作用是把缺失值當(dāng)作不匹配來(lái)處理否則遇到NaN會(huì)直接報(bào)錯(cuò)。第二類是提取關(guān)鍵信息用str.extract()把字符串里的部分內(nèi)容提取為新列# 從訂單號(hào)中提取兩位的年份信息 df[年份] df[訂單號(hào)].str.extract(r(\d{4}))圓括號(hào)部分就是想提取的組。第三類是批量替換用str.replace()注意默認(rèn)情況下它會(huì)按正則去匹配而不是普通的字符串替換所以如果只是想替換逗號(hào)這類普通字符最好把正則表達(dá)式寫成r,而不是裸逗號(hào)避免歧義。df[金額] df[金額].str.replace(r[,], , regexTrue)這條命令可以把千分位分隔符和中文逗號(hào)一次性清掉是清洗金額字段的好幫手。正則這塊我強(qiáng)調(diào)一個(gè)經(jīng)驗(yàn)在pandas里寫正則時(shí)字符串前面務(wù)必加r例如r\d這樣Python不會(huì)把\d解析成轉(zhuǎn)義字符正則規(guī)則才能原樣傳給底層引擎。5. 數(shù)據(jù)清洗實(shí)操?gòu)娜笔е档街貜?fù)值一步步處理5.1 缺失值的定位與三種填充思路數(shù)據(jù)清洗是pandas的看家本領(lǐng)頭歌作業(yè)里也專門有pandas數(shù)據(jù)清洗的關(guān)卡。第一步永遠(yuǎn)是定位缺失值df.isnull().sum()isnull()返回一個(gè)布爾型DataFramesum()按列統(tǒng)計(jì)True的個(gè)數(shù)一眼就能看出每列缺失多少。isna()和它完全等價(jià)哪個(gè)順手用哪個(gè)就行。第二步是決定怎么處理。如果你的數(shù)據(jù)集較大缺失行占比不高直接丟棄df_clean df.dropna()dropna()默認(rèn)是只要某一行存在任意缺失值就刪除整行。如果只關(guān)注某些關(guān)鍵列是否存在缺失值要用subset參數(shù)指定df_clean df.dropna(subset[姓名, 電話])如果你不想刪行而是想把缺失值補(bǔ)上fillna()是主力。常見的三種填法都很實(shí)用# 用常數(shù)填充 df[備注] df[備注].fillna(無(wú)) # 數(shù)值列用均值填充 df[年齡] df[年齡].fillna(df[年齡].mean()) # 時(shí)間序列用前向填充 df[價(jià)格] df[價(jià)格].fillna(methodffill)前向填充就是拿上一行的值來(lái)填空適合股票價(jià)格、庫(kù)存這類連續(xù)變量的場(chǎng)景。填完以后最好重新執(zhí)行一次df_clean.isnull().sum().sum()確保缺失值清零了再進(jìn)入下一步。5.2 重復(fù)值和異常值的處理套路重復(fù)值處理是另一個(gè)必考項(xiàng)。通常用duplicated()標(biāo)記重復(fù)行配合drop_duplicates()去重df_no_dup df.drop_duplicates(subset[訂單號(hào)], keepfirst)這里subset指定判斷重復(fù)的字段子集只按訂單號(hào)判斷只要訂單號(hào)相同就視為重復(fù)記錄。keepfirst表示保留重復(fù)行中的第一條這是最常用的配置。如果不指定subset則是必須所有列完全一致才算重復(fù)這種要求比較嚴(yán)格實(shí)際中用處相對(duì)有限。異常值排查我個(gè)人習(xí)慣先用df.describe()看數(shù)值列的分布重點(diǎn)看min、max和均值之間是否有明顯不合理的地方。比如人均購(gòu)買金額的最大值如果顯示是999999999那基本可以斷定是臟數(shù)據(jù)。定位到異常值之后最簡(jiǎn)單的處理方式是用布爾條件把它過(guò)濾掉df df[(df[訂單金額] 0) (df[訂單金額] 100000)]這里注意pandas的邏輯與、邏輯或要用和|不要用Python的and和or這是一個(gè)高頻報(bào)錯(cuò)點(diǎn)。還有一種替換的寫法把異常值替換成缺失值再走fillna流程df.loc[df[訂單金額] 100000, 訂單金額] pd.NA這條命令用的.loc定位加列賦值熟練之后你會(huì)發(fā)現(xiàn)寫復(fù)雜邏輯離不開它。6. ewm函數(shù)參數(shù)詳解別只會(huì)算平均6.1 什么是指數(shù)加權(quán)移動(dòng)平均ewmExponentially Weighted Moving Average函數(shù)在pandas官方文檔里是有獨(dú)立條目的熱度不低。如果只看字面意思它和rolling().mean()很像都是計(jì)算移動(dòng)平均但區(qū)別在于rolling窗口內(nèi)的每個(gè)數(shù)據(jù)權(quán)重相同而ewm會(huì)給近期數(shù)據(jù)更大的權(quán)重權(quán)重隨距離當(dāng)前時(shí)間的遠(yuǎn)近按指數(shù)衰減。簡(jiǎn)單理解就是“越近的數(shù)據(jù)越重要”。為什么實(shí)際業(yè)務(wù)里經(jīng)常用ewm而不是簡(jiǎn)單移動(dòng)平均因?yàn)樽罱鼛滋斓淖兓厔?shì)往往比一個(gè)月前的數(shù)據(jù)更能反映當(dāng)前狀態(tài)股票均線、銷量趨勢(shì)預(yù)測(cè)、異常監(jiān)控這些場(chǎng)景都需要對(duì)近期數(shù)據(jù)更敏感。我舉個(gè)例子如果有一組連續(xù)數(shù)值直接用ewm計(jì)算不需要像rolling那樣設(shè)定窗口大小而是通過(guò)衰減參數(shù)來(lái)控制權(quán)重分布import pandas as pd s pd.Series([100, 102, 101, 105, 110]) ewm_result s.ewm(span3).mean() print(ewm_result)6.2 ewm核心參數(shù)與換算關(guān)系ewm函數(shù)里最核心的參數(shù)是com、span、halflife和alpha它們本質(zhì)上是同一種東西的四種等價(jià)表達(dá)方式。alpha是權(quán)重衰減因子取值在0到1之間。四個(gè)參數(shù)的換算關(guān)系如下參數(shù)傳入方式與alpha的換算關(guān)系alpha直接指定衰減因子alpha alphaspan指定跨度alpha 2 / (span 1)com指定質(zhì)心center of massalpha 1 / (1 com)halflife指定半衰期alpha 1 - exp(-ln(2) / halflife)平時(shí)用得最多的是span因?yàn)樗暮x比較好理解跨度越大對(duì)歷史數(shù)據(jù)越“寬容”曲線越平滑。比如設(shè)置span5相當(dāng)于在計(jì)算近5個(gè)周期左右的加權(quán)均值。下面這段代碼可以把換算過(guò)程驗(yàn)證一遍s pd.Series([1, 2, 3, 4, 5]) result_span s.ewm(span3).mean() result_alpha s.ewm(alpha0.5).mean() print(result_span) print(result_alpha)算出來(lái)結(jié)果完全一致因?yàn)閟pan3對(duì)應(yīng)alpha0.5。我自己在實(shí)際復(fù)盤時(shí)習(xí)慣用span寫起來(lái)直觀調(diào)參時(shí)如果發(fā)現(xiàn)曲線太跳就把span調(diào)大比如從3調(diào)到5如果曲線反應(yīng)太慢就把span調(diào)小。另外還有一個(gè)容易忽視的參數(shù)adjust。adjustTrue默認(rèn)時(shí)ewm在計(jì)算時(shí)會(huì)考慮每個(gè)元素的權(quán)重修正adjustFalse時(shí)直接用遞歸公式y(tǒng)_t (1 - alpha) * y_{t-1} alpha * x_t。兩者的差異在數(shù)據(jù)序列較短時(shí)比較明顯長(zhǎng)序列下會(huì)趨于一致。做算法題時(shí)如果結(jié)果和平臺(tái)預(yù)期對(duì)不上試著切換一下adjust的參數(shù)往往就是這里的問(wèn)題。7. 常見問(wèn)題與排查技巧實(shí)錄7.1 高頻報(bào)錯(cuò)速查表這一節(jié)直接把實(shí)際項(xiàng)目里踩過(guò)的坑整理成表格遇到問(wèn)題可以先來(lái)這里對(duì)號(hào)入座報(bào)錯(cuò)信息常見原因解決思路ModuleNotFoundError: No module named pandas當(dāng)前解釋器環(huán)境沒(méi)安裝pandas檢查PyCharm解釋器在Terminal中確認(rèn)環(huán)境是否激活安裝pandasFileNotFoundError文件路徑不對(duì)或文件不在當(dāng)前目錄使用os.getcwd()查看當(dāng)前工作目錄用絕對(duì)路徑傳入read_csv或read_excelUnicodeDecodeError編碼不一致多半是GBK文件用了utf-8讀取把encoding切換到gbk或gb18030KeyError: 列名DataFrame里沒(méi)有這個(gè)列先執(zhí)行df.columns打印所有列名注意全角空格和大小寫差異ValueError: Length of values does not match length of index新列的數(shù)據(jù)長(zhǎng)度和DataFrame行數(shù)不一致檢查創(chuàng)建新列時(shí)后面的列表長(zhǎng)度如果需要對(duì)齊改用df[列] Series類型數(shù)據(jù)或使用loc定位SettingWithCopyWarning對(duì)切片副本做賦值操作在賦值前使用.copy()創(chuàng)建顯式副本或改用.loc切片進(jìn)行賦值MemoryError文件過(guò)大一次性載入內(nèi)存不足用usecols只讀必要列或設(shè)置nrows分批讀取再或者用chunksize分塊處理單獨(dú)說(shuō)一下SettingWithCopyWarning這個(gè)警告特別常見但又不影響程序運(yùn)行很多人直接忽略。結(jié)果某天發(fā)現(xiàn)數(shù)據(jù)根本沒(méi)改成功回頭查才發(fā)現(xiàn)是警告在提醒你你操作的可能是DataFrame的臨時(shí)副本而不是原數(shù)據(jù)。我的習(xí)慣是在做任何子集篩選后立刻加.copy()df_subset df[df[城市] 北京].copy() df_subset[區(qū)域] 華北這樣一來(lái)df_subset就是獨(dú)立的新DataFrame后續(xù)操作完全可控不會(huì)再出現(xiàn)修改不生效的詭異問(wèn)題。7.2 在頭歌平臺(tái)做題時(shí)的三個(gè)實(shí)用提醒很多人在頭歌平臺(tái)上刷pandas基礎(chǔ)題有一些平臺(tái)特有的注意事項(xiàng)值得提一下。第一頭歌評(píng)測(cè)環(huán)境里通常已經(jīng)預(yù)裝了pandas不需要在代碼里寫安裝命令也不建議寫。你只需要關(guān)心你的代碼邏輯評(píng)測(cè)時(shí)它會(huì)在一個(gè)干凈環(huán)境里重新執(zhí)行。第二題目給定的是一個(gè)模板文件文件名和路徑以題目的說(shuō)明為準(zhǔn)不要直接用本地路徑。比如題目要求讀取test.csv本地文件也放在項(xiàng)目根目錄那直接寫pd.read_csv(test.csv)就行前面不要拼C:\Users\...這種絕對(duì)路徑評(píng)測(cè)環(huán)境里根本不存在那個(gè)路徑。第三如果題目要求輸出特定的打印格式比如“輸出df的行數(shù)和列數(shù)格式為(行數(shù), 列數(shù))”那就老老實(shí)實(shí)用print(df.shape)不要自己加無(wú)關(guān)的說(shuō)明文字或中文引號(hào)。評(píng)測(cè)系統(tǒng)經(jīng)常是逐字符比對(duì)輸出多一個(gè)空格都算錯(cuò)。我一般在本地模擬測(cè)試時(shí)會(huì)把自己代碼運(yùn)行后的輸出和題目示例輸出并排擺在一起按字符逐字檢查。df.shape返回的是一個(gè)元組格式比如(10, 4)正好符合“行數(shù), 列數(shù)”的題設(shè)。頭歌作業(yè)里還經(jīng)常出現(xiàn)要求“使用pandas讀取成績(jī).xlsx中指定Sheet并輸出前幾行”這類題此時(shí)read_excel的sheet_name和nrows配合使用就很關(guān)鍵。8. 一個(gè)綜合小練習(xí)把上面的內(nèi)容串起來(lái)用光看不練假把式。我在這里用一個(gè)綜合案例把全流程走一遍場(chǎng)景是有一份CSV文件里面有客戶的訂單記錄包含“訂單號(hào)”、“客戶名”、“金額”、“下單日期”但數(shù)據(jù)里有缺失值、有重復(fù)記錄、金額列混入了逗號(hào)。需要清洗后按日期排序再輸出到Excel文件。import pandas as pd # 1. 讀取原始文件 df pd.read_csv(訂單列表.csv, encodinggbk) # 2. 查看基本信息和缺失情況 print(df.info()) print(df.isnull().sum()) # 3. 清理金額列去掉逗號(hào)并轉(zhuǎn)成數(shù)值 df[金額] df[金額].astype(str).str.replace(r,, , regexTrue) df[金額] pd.to_numeric(df[金額], errorscoerce) # 4. 解析日期 df[下單日期] pd.to_datetime(df[下單日期]) # 5. 刪除重復(fù)訂單號(hào) df df.drop_duplicates(subset[訂單號(hào)], keepfirst) # 6. 刪除關(guān)鍵列缺失的行 df df.dropna(subset[訂單號(hào), 客戶名, 金額]) # 7. 按日期排序 df df.sort_values(下單日期) # 8. 寫出Excel去掉行索引 df.to_excel(訂單清洗結(jié)果.xlsx, indexFalse)這個(gè)流程就是我平時(shí)處理訂單數(shù)據(jù)的簡(jiǎn)化版。要先看結(jié)構(gòu)再定位問(wèn)題再逐項(xiàng)清洗最后輸出結(jié)果。每一步執(zhí)行后我都建議打印df.shape確認(rèn)行數(shù)變化比如刪完重復(fù)項(xiàng)行數(shù)從1000變成了980這種變化是預(yù)期的心里就有數(shù)了。9. 最后再分享一點(diǎn)我的使用習(xí)慣pandas的基礎(chǔ)內(nèi)容到這里該講的都講了從安裝環(huán)境、數(shù)據(jù)結(jié)構(gòu)、文件讀寫、類型轉(zhuǎn)換、正則配合、數(shù)據(jù)清洗到ewm參數(shù)整條線走下來(lái)日常大部分?jǐn)?shù)據(jù)處理任務(wù)都能應(yīng)付。我說(shuō)說(shuō)自己的習(xí)慣吧每次拿到一個(gè)新的DataFrame第一件事永遠(yuǎn)是df.head()配合df.info()先把數(shù)據(jù)長(zhǎng)什么樣、每列是什么類型看清楚再?zèng)Q定后面怎么處理。很多人上來(lái)就處理結(jié)果處理半天發(fā)現(xiàn)數(shù)據(jù)讀進(jìn)來(lái)就已經(jīng)錯(cuò)了。用df.info()還能順便看到Dtypes和Non-Null Count缺失情況一目了然。另外動(dòng)手寫清洗代碼之前我會(huì)單獨(dú)弄一個(gè)Excel樣例文件在PyCharm里先跑通再轉(zhuǎn)移到大文件上。小樣本測(cè)試的成本極低但排查問(wèn)題的效率非常高。如果你有自己常用的數(shù)據(jù)處理模板慢慢積累下來(lái)會(huì)發(fā)現(xiàn)pandas真正的威力是讓你把臟活累活標(biāo)準(zhǔn)化。下次你再看head歌作業(yè)或者實(shí)際項(xiàng)目的復(fù)雜表格就不會(huì)再害怕了。