pandas實(shí)現(xiàn)數(shù)據(jù)讀取&清洗&分析的項(xiàng)目實(shí)踐
近期因工作需要,需對幾十萬條商品和訂單數(shù)據(jù)進(jìn)行初步的數(shù)據(jù)分析,本來嘗試過用Excel,但是數(shù)據(jù)量一旦超過10萬條,Excel和電腦的性能瓶頸就捉襟見肘了,為了后續(xù)遇到類似問題提升處理效率,抽空系統(tǒng)性的研究學(xué)習(xí)了pandas這個庫,初步上手之后,感覺以后再處理千萬級的數(shù)據(jù)量的時候,也會游刃有余了,話不多講,直接進(jìn)入正題。
本文主要沿著在日常使用pandas處理數(shù)據(jù)時的步驟,講解pandas對應(yīng)的知識點(diǎn)和常見操作,分析工具使用jupyter-notebook,強(qiáng)烈推薦。
本文假設(shè)已經(jīng)對pandas有基礎(chǔ)性的了解,核心是Series和DataFrame概念(numpy庫可不了解)
一、數(shù)據(jù)讀取和寫入
第一步,先從存量數(shù)據(jù)源,將數(shù)據(jù)讀取過來,然后再將分析得出的數(shù)據(jù)寫入并永久保存,這是數(shù)據(jù)分析的開始和結(jié)束,在此一并說明,主要只講解常用的讀取和寫入方式,其他的可以自行學(xué)習(xí)和了解
1.1 CSV和txt文件:
import pandas as pd file_path_read='' file_path_write='' #讀入csv或txt文件內(nèi)數(shù)據(jù),以下只羅列了常用的參數(shù) df=pd.read_csv( file_path_read , #指定需讀入或?qū)懭氲奈募穆窂剑蔀橄鄬β窂?,也可為絕對路徑 sep= ',' , #指定分隔符 encoding= utf-8 , #指定字符編碼格式 usecols=None , #指定需讀入的列,列表格式,可為索引[1,2,3]或列明['A','B','C'] names=['A','B','C'] , #可自定義讀入數(shù)據(jù)的列標(biāo)簽 skip_blank_lines=True, #設(shè)置是否跳過內(nèi)容全空的行 nrows=1000, #指定讀入的行數(shù) skiprows=[2,5],#指定需跳過的行數(shù) dtype={0:str,'B':'float64'}) #指定列數(shù)據(jù)讀入的格式,可分別對每一列指定讀入的數(shù)據(jù)格式 #將分析好的數(shù)據(jù)寫入csv或txt文件 df.to_csv( file_path_write )
1.2 Excel文件:
import pandas as pd file_path_read='' file_path_write='' #從數(shù)據(jù)源讀取數(shù)據(jù),并同時指定讀入數(shù)據(jù)的格式,也可不指定,讀入后就是一個標(biāo)準(zhǔn)的DataFrame #其他常用的參數(shù),與read_csv一致,不再贅述 df=pd.read_excel(file_path_read ,encoding= utf-8 , usecols=None , names=['A','B','C'] , skip_blank_lines=True, nrows=1000, skiprows=[2,5],dtype={0:str,2:'float64'}) #將分析好的數(shù)據(jù)寫入Excel,并同時指定寫入數(shù)據(jù)的格式,也可不指定 df.to_excel(file_path_write , dtype=str)
1.3 MYSQL數(shù)據(jù)庫:
import pandas as pd from sqlalchemy import create_engine #1、連接數(shù)據(jù)庫 #其中username為賬戶名,比如root,password為密碼,ip為數(shù)據(jù)庫的ip,如果是本地的一般是localhost,port為端口,database為數(shù)據(jù)庫名 engine = create_engine('mysql+pymysql://username:password@ip:port/database') #2、定義查詢sql語句 sql = '''select * from tablename where colname in (,) ''' #3、讀取數(shù)據(jù),使用以上數(shù)據(jù)庫引擎和sql語句查詢數(shù)據(jù),直接讀入,為DataFrame格式 #coerce_float,很有用,為true時會將字符串格式的數(shù)據(jù)直接讀取為float數(shù)字格式,columns,列表格式,指定讀入的行,一般沒用,因?yàn)榛緯趕ql語句中指定 #sql也可以直接為表名,即讀入整張表,但一般使用sql語句 df=pd.read_sql(sql, engine, coerce_float=True, columns=None) #4、寫入數(shù)據(jù),將分析好的數(shù)據(jù)落庫 #tablename為需要寫入的表名,if_exists,默認(rèn)為false,即表存在則不寫入,也可設(shè)置為'append',即將數(shù)據(jù)追加到該表內(nèi),dtype可指定各個列的數(shù)據(jù)格式,一般無需指定 df.to_sql('tablename', engine , if_exists='append' ,dtype={})
二、數(shù)據(jù)清洗
2.1 清除不需要的行數(shù)據(jù)
一般數(shù)據(jù)源都是csv、txt 或者excel,此時可能源數(shù)據(jù)內(nèi)就包含大量異?;虿幌胍男袛?shù)據(jù),如果不進(jìn)行清除,則會嚴(yán)重影響后續(xù)數(shù)據(jù)分析的準(zhǔn)確性
當(dāng)然,如果數(shù)據(jù)源是mysql等數(shù)據(jù)庫,則可在讀取數(shù)據(jù)的時候,即通過slq命令,將異?;虿幌胍臄?shù)據(jù)給過濾掉。
2.1.1 清除滿足指定條件的行數(shù)據(jù)
#清除滿足指定條件的行數(shù)據(jù)的表達(dá)式 df = df.drop(df[<some boolean condition>].index) #比如希望清除x列小于0.01或大于10的指定行數(shù)據(jù),返回一個清除后的DataFrame #其中的布爾表達(dá)式可以有多個,可以用與(&)或(|)非(~)進(jìn)行連接 df_clear = df.drop(df[(df['x']<0.01) | (df['x']>10)].index) #刪除x小于0.01或大于10的行 #或者,比如希望清除A列值為空,或者B列中值小于0的行,然后返回清除后的新的DataFrame df_clear = df.drop(df[(df['A']==‘') | (df['B']<0)].index)
2.1.2 清除指定的行數(shù)據(jù)
如果數(shù)據(jù)源是mysql等數(shù)據(jù)庫,可直接在sql語句中添加篩選條件,不過在分析過程中,可能也需要清除指定的行數(shù)據(jù)。
#清除指定的行 #drop(list),函數(shù)接受一個列表,列表內(nèi)是指定需刪除的行索引 df.drop([index]) #即刪除指定行 df.drop([0,1,2,3,4]) #清除前5行 df.drop(range(20)) #清除前20行,
2.2 清除不需要的列
如果數(shù)據(jù)源是mysql等數(shù)據(jù)庫,則其實(shí)可以在sql語句中,只拉取自己需要的列,如果是從csv或Excel讀取,也可在讀取數(shù)據(jù)時,就指定對應(yīng)需要的列
不過在實(shí)際數(shù)據(jù)分析時,可能在分析過程中產(chǎn)生了新的DataFrame,此時可能需要清除不需要的列。
#執(zhí)行刪除操作時,原df不會變化,一般是返回一個新的DataFra df.drop(['列索引或標(biāo)簽',axis=1]) #刪除索引為2,即第三列 df.drop([2],axis=1) #刪除索引為0,1,2即第一、第二、第三列 df.drop([0,1,2],axis=1) #刪除列標(biāo)簽為A的列 df.drop(['A'],axis=1) #刪除列標(biāo)簽為A、B、C的多列 df.drop(['A','B','C'],axis=1)
2.3 調(diào)整列的展示順序或列標(biāo)簽名
這個步驟一般是為了方便自己觀察數(shù)據(jù),或者在數(shù)據(jù)分析接近尾聲時,為增強(qiáng)數(shù)據(jù)可讀性,對列的順序進(jìn)行調(diào)整
#語句如下,使用reindex函數(shù) new_col_list=['B','C','A'] #假設(shè)希望將列的展示順序由A、B、C,調(diào)整為B、C、A df.reindex(columns = new_col_list) #調(diào)整存量DataFrame的列標(biāo)簽名稱,一般用于將默認(rèn)的列標(biāo)簽修改的更加直觀易懂 new_col_name=['age','name',gender'] df.columns=new_col_name
2.4 對行數(shù)據(jù)進(jìn)行排序
此處也是為了在進(jìn)行數(shù)據(jù)分析時觀察數(shù)據(jù),或者增強(qiáng)輸出的數(shù)據(jù)的可讀性
2.4.1 sort_values()
即按照實(shí)際的數(shù)據(jù)值進(jìn)行排序
#df.sort_values()函數(shù) #既可以根據(jù)列數(shù)據(jù),也可根據(jù)行數(shù)據(jù)排序,最為常用 #axis,默認(rèn)為0,即縱向排序,可指定按照哪列的值進(jìn)行排序,最終會改變數(shù)據(jù)縱向的順序 #axis,為1時,即橫向排序,可指定按照哪行(根據(jù)行索引)進(jìn)行排序,最終會改變數(shù)據(jù)的橫向順序 #inplace, #ascending,可為數(shù)組格式,即指定按照多行或列,不同行或列的升序降序規(guī)則 #na_position,指定缺省值排在最前還是最后,一般是last,即最后 df.sort_values(by=, axis=0, ascending=True, inplace=False, kind='quicksort', na_position='last') #假設(shè)數(shù)據(jù)如下: b a c 2 1 4 1 0 2 3 3 3 2 1 2 1 3 2 8 #先按照b降序,再按照a升序排序 df.sort_values(by=['b','a'],axis=0,ascending=[False,True]) #先按照3行升序排序,再按照0行降序排序 df.sort_values(by=[3,0],axis=1,ascending=[True,False])
2.4.2 sort_index()
#df.sort_index()函數(shù) #默認(rèn)根據(jù)行標(biāo)簽對所有行排序,或根據(jù)列標(biāo)簽對所有列排序,或根據(jù)指定某列或某幾列對行排序。 #axis,默認(rèn)為0,即按行標(biāo)簽進(jìn)行排序,最終會改變數(shù)據(jù)在縱向的順序 #axis,為1時,即按列標(biāo)簽排序,最終會改變數(shù)據(jù)在橫向的順序 #na_position,指定缺省值排在最前還是最后,一般是last,即最后 df.sort_index(axis=0, ascending=True , na_position='last') #假設(shè)數(shù)據(jù)如下: b a c 2 1 4 1 0 2 3 3 3 2 1 2 1 3 2 8 #按照行標(biāo)簽升序排序,最后會變成0、1、2、3 df.sort_index(axis=0,ascending=True) #按照列標(biāo)簽升序排序,最后會變成a、b、c df.sort_index(axis=1,ascending=True)
2.5 空值的處理
一般導(dǎo)入的數(shù)據(jù),會存在空值的情況,為了避免此類數(shù)值影響后續(xù)的數(shù)據(jù)分析,一般需要進(jìn)行相應(yīng)的處理
#1、對空值直接清除 df.dropna( axis=0, # 0: 對行進(jìn)行操作; 1: 對列進(jìn)行操作 默認(rèn)為0 how='any' # 'any': 只要存在 NaN 就 drop 掉; 'all': 必須全部是 NaN 才 drop 默認(rèn)為'any' ) #2、對空值填補(bǔ) df.fillna(value=0) #用0填補(bǔ)所有的空值 df.fillna({'B': 3,'C': 4}) #使用常量填補(bǔ)對應(yīng)列的空值,比如針對B列,用3填補(bǔ)空值,針對C列,用4填補(bǔ)空值 #3、用前項(xiàng)填充或者后項(xiàng)填充 df.fillna(method = 'ffill') #用前一個觀測值填充 df.fillna(method = 'bfill') #用后一個觀測值填充 #4、用均值或中位數(shù)填充各自的列 df.fillna(df.median()) df.fillna(df.mean()) #注:使用fillna,dropna時,需要添加參數(shù) inplace = True,如df.fillna(df.median(),inplace = True),以確認(rèn)修改,否則實(shí)際的數(shù)據(jù)并不會有改動。
2.6 數(shù)據(jù)去重處理
一般源數(shù)據(jù)可能會在某列存在重復(fù)數(shù)據(jù)的問題,為方便后續(xù)處理等,可能需要進(jìn)行去重
#刪除重復(fù)行時,需要用到drop_duplicates函數(shù) df.drop_duplicates( ['A','B'], #指定按照某列,判斷數(shù)據(jù)重復(fù),參數(shù)非必填,可以單列、多列 keep='first' #指定如果發(fā)現(xiàn)重復(fù),保留哪行數(shù)據(jù),枚舉有first(保留第一行)、last(保留最后一行),F(xiàn)alse(刪除所有重復(fù)行) ) df.drop_duplicates() #刪除完全重復(fù)的行數(shù)據(jù)
2.7 對指定列數(shù)據(jù)進(jìn)行初步加工
#1、map()函數(shù) #可對一列數(shù)據(jù),統(tǒng)一給一列(Series)中的每一個元素應(yīng)用指定函數(shù) def myfunc(x): if x>40: return '中年人' elif x<30: return '青年人' else: return '尷尬的年紀(jì)' df['age'].map(myfunc) #2、apply()函數(shù) #也可對一列數(shù)據(jù),統(tǒng)一應(yīng)用指定函數(shù),但功能更強(qiáng)大,可傳入除列元素的其他參數(shù) #其他參數(shù)可以關(guān)鍵詞的方式傳入,也可以直接傳入其他值 def myfunc(x,*args,**args_dict): if x<10000: return x+args_dict['high'] else: return x+args_dict['low'] df1['salary']=df1['salary'].apply(myfunc,low=100,high=300)#對工資列,低于1萬的加一個值,高于1萬的,加另外一個值
2.8 對DataFrame內(nèi)所有數(shù)據(jù)進(jìn)行初步加工處理
此種方法不太常用,或者可以作為填充默認(rèn)值的方式,比如將NAN的值填充為0
#以下會對DataFrame每個元素應(yīng)用一次指定的函數(shù),并將返回值作為新的值 #一般會產(chǎn)生一個新的df #以下函數(shù)將空值全部填充為0 df_new=df.apply(lambda x: 0 if str(x)=='' else x)
2.9 設(shè)置數(shù)據(jù)格式
一般在后續(xù)數(shù)據(jù)處理時,或者在數(shù)據(jù)處理基本宣告尾聲時,為增強(qiáng)數(shù)據(jù)可讀性或者分析的方便,需要對數(shù)據(jù)設(shè)置格式
#以下主要演示對某df內(nèi)某列數(shù)據(jù)進(jìn)行常見的數(shù)字格式設(shè)置 #四舍五入 df['salary'].round([decimals=2]) #將工資列,數(shù)字進(jìn)行四舍五入并保留小數(shù)點(diǎn)后2位 #將小數(shù)設(shè)置為百分?jǐn)?shù),以下設(shè)置為精確到小數(shù)點(diǎn)后2位,返回一個設(shè)置好格式的series df['percent'].map( lambda x: format(x,'.2%') ) #設(shè)置千分位分隔符,返回一個設(shè)置好格式的series df['percent'].map( lambda x: format(x,',') ) #更多設(shè)置格式的方式,可自行了解
三、數(shù)據(jù)切片和篩選查詢
一般需要對清洗后的數(shù)據(jù),按照具體數(shù)據(jù)分析的需求,提取部分?jǐn)?shù)據(jù)并進(jìn)行進(jìn)一步的分析,這個時候就需要對數(shù)據(jù)進(jìn)行進(jìn)一步切片或查詢篩選,找出自己想要的具體數(shù)據(jù)集
3.1 行切片
提取指定的行,一般是由行索引組成的列表,即提取指定的某行或某幾行
#1、直接使用索引 df[index:index+1] #注意,一定要用切片的形式,如果希望直接使用index,則可用iloc[index] #2、使用行標(biāo)簽,行標(biāo)簽為再創(chuàng)建DataFrame或Series時自定義的行標(biāo)簽 df['row_tag'] #提起的方法,可以直接使用標(biāo)準(zhǔn)的列表訪問方式[],也可使用loc()和iloc(函數(shù)) #[]方式,可使用標(biāo)簽或索引,如果傳入的是 #loc()函數(shù),一般用于使用行或列標(biāo)簽進(jìn)行訪問 #iloc()函數(shù),一般使用行或列index索引進(jìn)行訪問 df[2:5] #提取第3到5行 df['2020-10-20'] #提取行標(biāo)簽為2020-10-20的行數(shù)據(jù) df.loc['2020-10-20':'2020-10-31',:] #提取指定3到5行,全列,后面的 : 也可不寫 df.loc[2:4,:] #提取指定3到5行,全列,后面的 : 也可不寫
3.2 列切片
提取指定的一列或多列,一般使用列標(biāo)簽或列索引進(jìn)行提取
df['colname'] #直接提取指定單列標(biāo)簽的列數(shù)據(jù) df[['A','D','E']] #指定直接提取指定多列數(shù)據(jù),這種方法只能使用列標(biāo)簽進(jìn)行提取 df.loc[:,'A':'C'] #使用loc方法提取A列到C列 df.iloc[:,0:2] #使用iloc方法提取第1到3列
3.3 數(shù)據(jù)篩選和查詢
按照一定的條件,對數(shù)據(jù)進(jìn)行篩選和查詢,找出自己想要的數(shù)據(jù)記錄(行)
3.3.1 快速篩選
一般在導(dǎo)入數(shù)據(jù)或數(shù)據(jù)分析時,如果數(shù)據(jù)量過大,希望能摘出幾行,看下數(shù)據(jù)表現(xiàn)是否正常
df.head(n) #展示前n行,默認(rèn)5 df.tail(n) #展示后n行,默認(rèn)5
3.3.2 條件篩選和查詢
本質(zhì)和sql查詢較為相似
#通過邏輯運(yùn)算來取數(shù)據(jù)子集,查詢和篩選出列值滿足指定條件的行數(shù)據(jù) #可使用 & (AND)、 ~ (NOT) 和 | (OR) 連接多個條件表達(dá)式 df[df[ ‘country' ]== 'french' ] df[(df[ ‘country' ]== 'french' ) & (df[ 'year_born' ]=='1990')] df[(df[‘country' ]== 'french' ) & (df[ 'year_born' ]=='1990') & ~(df[ 'city' ]== 'London' )] df[(df[‘country' ]== french ) & (df[ 'year_born' ]==1990) & ~(df[ 'city' ].isin([ ['London' , 'beijing']) )]
3.3.3 正則過濾
使用正則表達(dá)式,過濾某指定列的值
df.filter(regex='string')#其中string為正則表達(dá)式
3.4 遍歷
不建議使用,因?yàn)樾时容^低,一般使用pandas內(nèi)置的一些函數(shù)滿足類似需求
3.4.1 行遍歷
用于分析每一行的數(shù)據(jù)并進(jìn)行遍歷,比如發(fā)現(xiàn)某一行數(shù)據(jù)的對應(yīng)列值是否滿足條件
#逐行打印數(shù)據(jù),使用iloc for i in range(len(df.index)): print(df.iloc[i]) #逐行打印數(shù)據(jù),使用loc for i in df.index: print(df.loc[i])
3.4.2 列遍歷
#逐個打印df中的每一列,使用df for i in df.columns: print(df[i]) #逐個打印df中的每一列,使用loc for i in df.columns: print(df.loc[:,i]) #逐個打印df中的每一列,使用iloc for i in range(len(df.columns)): print(df.iloc[:,i])
3.4.3 DataFrame所有數(shù)據(jù)遍歷
#使用loc for i in df.index: for j in df.columns: if df.loc[i][j]=='': print('發(fā)現(xiàn)空值') #使用iloc for i in range(len(df.index)): for j in range(len(df.columns)): if df.iloc[i][j]=='': print('發(fā)現(xiàn)空值')
四、數(shù)據(jù)簡單統(tǒng)計(jì)和聚合
4.1 數(shù)據(jù)統(tǒng)計(jì)
4.1.1 指定列數(shù)據(jù)統(tǒng)計(jì)分析
#常見統(tǒng)計(jì)數(shù)據(jù)值 #某列的個數(shù)、合、平均值、最大值、最小值 df['colname'].count() df['colname'].sum() df['colname'].mean() df['colname'].max() df['colname'].min() #快速統(tǒng)計(jì) #會快速展示每一列的最大、最小、平均、均方差等統(tǒng)計(jì)數(shù)據(jù) df.describe()
4.1.2 各列相關(guān)度分析
#協(xié)方差--相關(guān)度系數(shù) df.corr() #會輸出相關(guān)性矩陣,展示每一列的相關(guān)度系
4.2 數(shù)據(jù)分組和聚合
4.2.1 指定列快速分組和聚合
一般情況下,希望對某列,比如國家等,對數(shù)據(jù)進(jìn)行分組并快速知道每個國家對應(yīng)數(shù)據(jù)記錄的數(shù)量,然后進(jìn)行快速預(yù)覽
#先按照A列的值,對數(shù)據(jù)進(jìn)行分組,然后計(jì)算出每個分組的數(shù)據(jù)記錄數(shù)量 df['A'].value_counts()
4.2.2 分組
常見的數(shù)據(jù)分析中,一般是對數(shù)據(jù)按照行或列進(jìn)行分組,然后進(jìn)一步對分組數(shù)據(jù),按照分組進(jìn)行求和、計(jì)數(shù)、求平均值、均方差等聚合,或者用自定義的函數(shù)進(jìn)行進(jìn)一步的分析
#分組使用groupby函數(shù),分組之后,得到一個DataFrameGroupBy對象,后續(xù)可對該對象進(jìn)行聚合 #1、按單列分組,縱向分組 df.groupby('colname') df.groupby('country') #指按國家列分組 #2、按多列分組,縱向分組 df.groupby(['cloA','colB']) #先按照A列,再按照B列分組 #3、按單行分組,橫向分組 df.groupby(level=index) #4、按多行分組,橫向分組 df.groupby(level=[0,1]) #5、通過字典或者Series分組 #可將行或者列標(biāo)簽,通過子字典映射成對應(yīng)的值,然后進(jìn)行分組 mapping = {'a':'one','b':'one','c':'two','d':'two','e':'three'} df.groupby(mapping) #6、自定義函數(shù)分組 #會將行或者列標(biāo)簽作為參數(shù)傳入自定義函數(shù),并以函數(shù)返回值作為分組的名進(jìn)行分組 def myfunc(x): if x =='a' or x=='b' return 'one' else: return 'two' df.groupby(myfunc,axis=0)
4.2.3 聚合
4.2.3.1 常見聚合函數(shù)
gp=df.groupby('A') gp.count() #計(jì)數(shù) gp.sum()#求和 gp.max(),gp.min()#最大值、最小值 gp.mean()#算數(shù)平均數(shù) gp.first(),gp.last()#第一個和最后一個非空 gp.prod()#非空數(shù)值的乘積 gp.median()#非空的算數(shù)中位數(shù) gp.std(),gp.var()#非空數(shù)據(jù)的標(biāo)準(zhǔn)差和均方差 gp.describe()#快速生成以上所有統(tǒng)計(jì)數(shù)據(jù)
4.2.3.2 自定義聚合函數(shù)
#對某分組后的對象使用自定義的聚合函數(shù),需要用到agg()函數(shù) #具體實(shí)現(xiàn),分組后的數(shù)據(jù)為一個數(shù)組,然后會分別將每組對應(yīng)的數(shù)組作為參數(shù)傳入自定義函數(shù)內(nèi),最終以函數(shù)返回值作為該分組數(shù)據(jù)聚合后的值 def myfunc(x): return (x.max()-x.min()) df.groupby('A').agg(myfunc)
4.2.3.3 應(yīng)用多個聚合函數(shù)
#對某次分組對象,一次性應(yīng)用多個聚合函數(shù) #可以集合的格式傳入不同的聚合函數(shù),如果不寫名稱,只傳入函數(shù),則默認(rèn)以函數(shù)名為列標(biāo)簽 df.groupby('A').agg([('求和',sum),('標(biāo)準(zhǔn)差',std),'mean',('range',myfunc)]) #對某次分組對象,不同列使用不同的聚合函數(shù) df.groupby('sku_type').agg({ 'sku_sale_price':'max', 'profit_rate':'mean' })
4.2.3.4 將聚合結(jié)果與原始數(shù)據(jù)合并
#1、使用merge函數(shù)進(jìn)行連接合并 agg=df1.groupby('card_cate_name').sum().add_prefix('sum_') pd.merge(df1,agg,on='card_cate_name',how='right') #2、使用transform(),,將聚合結(jié)果按照原始數(shù)據(jù)排序成一個DataFrame對象,然后再合并 tf = df.groupby('A').transform(sum) df[tf.columns]=tf
4.2.3.5 數(shù)據(jù)透視圖
了解了數(shù)據(jù)的分組和聚合之后,再了解pandas的數(shù)據(jù)透視圖,會更加直觀易懂,并且當(dāng)使用習(xí)慣了透視圖之后,會發(fā)現(xiàn),可能大多數(shù)情況下,就不再需要groupby了,而是直接使用pivot_table函數(shù),因?yàn)楦又庇^、高效
下圖是數(shù)據(jù)透視圖函數(shù)工作示意:
#類似Excel的數(shù)據(jù)透視圖,pandas可對數(shù)據(jù)快速生成你想要的數(shù)據(jù)透視圖,以快速發(fā)現(xiàn)數(shù)據(jù)相關(guān)有趣的特征 #1、數(shù)據(jù)透視表的使用 pd.pivot_table( df,#要生成透視圖的數(shù)據(jù)源 index=['colA','colB','colC'],#設(shè)置透視圖的行索引,類似指定需要以源數(shù)據(jù)的哪些列值進(jìn)行分組,可指定多個,自左向右依次多級分組 values=['colD','colE'],#指定分組后,需要透視的數(shù)據(jù)列,可對數(shù)據(jù)列應(yīng)用不同的聚合函數(shù)來透視,也可不指定,不指定則會展示出除了index指定的列外所有其他列的聚合透視 columns=['colF','colG'],#指定透視表的列,即會使用指定列的值,對指定的values列進(jìn)行分組,該概念是相較于index,注意,columns指定的列和index指定的列及values指定的列不能有重復(fù) aggfunc=[np.mean,len],#指定聚合函數(shù),可以指定多個,如果指定多個,則會分別對指定的values列應(yīng)用對應(yīng)的聚合函數(shù) fill_value=0,#將Nan空值設(shè)置為0,為了便于后面應(yīng)用聚合函數(shù)造成異常,也可不設(shè) margins=True,#主要是對已經(jīng)分組透視好的數(shù)據(jù)values,最后進(jìn)行縱向求和,得出一個匯總值 ) #2、對每一個values列應(yīng)用不同的聚合函數(shù) pd.pivot_table( df,#要生成透視圖的數(shù)據(jù)源 index=['colA','colB','colC'], values=['colD','colE'], aggfunc={'colD':np.mean,'colE':len},#指定colD列使用mean聚合函數(shù),colE列使用len聚合函數(shù),字典格式 #或者 aggfunc={'colD':np.mean,'colE':[np.mean,np.sum,len]},#對colE列使用多個聚合函數(shù) ) #3、使用自定義的聚合函數(shù) #與分組與聚合一樣,也可以指定使用自定義的聚合函數(shù),此時同理,也會將分組后每列的值作為參數(shù)傳入自定義函數(shù) #以下實(shí)現(xiàn)了count的功能,即根據(jù)A分組,計(jì)算B列值對應(yīng)各分組的記錄個數(shù) def count(x): c=0 for i in x: c+=1 return c pd.pivot_table(df,index=["A"],values=["B"],aggfunc=[count]) #4、數(shù)據(jù)透視表的篩選 tb=pd.pivot_table(df,index=['colA']) tb.query('name == ["jacky"]') #或 tb.query('name == ["jacky","dennis"]')
后續(xù)文章再詳細(xì)展開數(shù)據(jù)的合并及可視化,數(shù)據(jù)的合并類似sql中的原理
到此這篇關(guān)于pandas實(shí)現(xiàn)數(shù)據(jù)讀取&清洗&分析的項(xiàng)目實(shí)踐的文章就介紹到這了,更多相關(guān)pandas 數(shù)據(jù)讀取&清洗&分析內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- pandas數(shù)據(jù)清洗實(shí)現(xiàn)刪除的項(xiàng)目實(shí)踐
- 詳解Python如何利用Pandas與NumPy進(jìn)行數(shù)據(jù)清洗
- 利用pandas進(jìn)行數(shù)據(jù)清洗的方法
- pandas數(shù)據(jù)處理清洗實(shí)現(xiàn)中文地址拆分案例
- Pandas 數(shù)據(jù)處理,數(shù)據(jù)清洗詳解
- pandas數(shù)據(jù)清洗,排序,索引設(shè)置,數(shù)據(jù)選取方法
- pandas如何統(tǒng)計(jì)某一列或某一行的缺失值數(shù)目
- pandas返回缺失值位置的方法實(shí)例教程
- pandas中DataFrame檢測重復(fù)值的實(shí)現(xiàn)
- pandas數(shù)據(jù)清洗(缺失值和重復(fù)值的處理)
相關(guān)文章
Python基礎(chǔ)語法之變量與數(shù)據(jù)類型詳解
這篇文章主要為大家詳細(xì)介紹了Python基礎(chǔ)語法中變量與數(shù)據(jù)類型的用法,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)Python有一定的幫助,感興趣的可以了解一下2022-07-07基于Python實(shí)現(xiàn)的百度貼吧網(wǎng)絡(luò)爬蟲實(shí)例
這篇文章主要介紹了基于Python實(shí)現(xiàn)的百度貼吧網(wǎng)絡(luò)爬蟲,實(shí)例分析了Python實(shí)現(xiàn)網(wǎng)絡(luò)爬蟲的相關(guān)技巧,非常具有實(shí)用價值,需要的朋友可以參考下2015-04-04python調(diào)用百度REST API實(shí)現(xiàn)語音識別
這篇文章主要為大家詳細(xì)介紹了python調(diào)用百度REST API實(shí)現(xiàn)語音識別,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-08-08Transformer導(dǎo)論之Bert預(yù)訓(xùn)練語言解析
這篇文章主要為大家介紹了Transformer導(dǎo)論之Bert預(yù)訓(xùn)練語言解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03Appium Python自動化測試之環(huán)境搭建的步驟
這篇文章主要介紹了Appium Python自動化測試之環(huán)境搭建的步驟,以32位的Windows 7操作系統(tǒng)為例介紹Appium+Python的環(huán)境搭建步驟,感興趣的小伙伴們可以參考一下2019-01-01Python調(diào)用API接口實(shí)現(xiàn)人臉識別
本文主要介紹了Python調(diào)用API接口實(shí)現(xiàn)人臉識別,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-02-02Python HTML解析器BeautifulSoup用法實(shí)例詳解【爬蟲解析器】
這篇文章主要介紹了Python HTML解析器BeautifulSoup用法,結(jié)合實(shí)例形式詳細(xì)分析了第三方庫BeautifulSoup實(shí)現(xiàn)的爬蟲解析器功能具體操作技巧,需要的朋友可以參考下2019-04-04python過濾字符串中不屬于指定集合中字符的類實(shí)例
這篇文章主要介紹了python過濾字符串中不屬于指定集合中字符的類,涉及Python針對字符串與集合的相關(guān)操作技巧,需要的朋友可以參考下2015-06-06