回復(fù) 紅包 可以領(lǐng)程序員專屬紅包封面
Pandas簡介Pandas是一個強大的分析結(jié)構(gòu)化數(shù)據(jù)的工具集;它的使用基礎(chǔ)是Numpy(提供高性能的矩陣運算); 用于數(shù)據(jù)挖掘和數(shù)據(jù)分析,同時也提供數(shù)據(jù)清洗功能。 1. Series它是一種類似于一維數(shù)組的對象,是由一組數(shù)據(jù)(各種NumPy數(shù)據(jù)類型)以及一組與之相關(guān)的數(shù)據(jù)標(biāo)簽(即索引)組成。 僅由一組數(shù)據(jù)也可產(chǎn)生簡單的Series對象
1.1. 使用list構(gòu)建Series默認(rèn)index是數(shù)字
import pandas as pd import numpy as np # 自定義打印的函數(shù),方便后面調(diào)試 def _print(s: str, *args, pad=20): print('\n', s.center(pad, '-')) for i in args: print(i) infoLi = ['jack', 18, '180CM'] serLi = pd.Series(data=infoLi) _print('list構(gòu)建Series', serLi) serLi = pd.Series(data=infoLi, index=list('abc')) _print('list構(gòu)建Series,并指定index', serLi)
1.2. 使用字典構(gòu)建Seriesindex為字典的key
infoDic = {'name': 'jack', 'age': 18, 'height': '180CM'} serDic = pd.Series(data=infoDic) _print('字典構(gòu)建Series', serDic)
1.3. Series轉(zhuǎn)換為listinfoLi = serLi.tolist() _print('Series轉(zhuǎn)換為list', infoLi)
1.4. Series轉(zhuǎn)換為dictinfoDic = serDic.to_dict() _print('Series轉(zhuǎn)換為dict', infoDic)
1.5. Series轉(zhuǎn)換為DataFramdf = pd.DataFrame(data=serDic) _print('Series轉(zhuǎn)換為DataFram', df) df = pd.DataFrame(data=serDic, columns=['信息']) _print('Series轉(zhuǎn)換為DataFram,并指定列名', df, pad=30)
1.6. 修改Series的數(shù)據(jù)類型s = pd.Series(data=['001', '002'], index=list('ab')) _print('構(gòu)建Series', s)
1.6.1. astypesastype = s.astype(int) _print('使用astype函數(shù)修改數(shù)據(jù)類型', sastype)
1.6.2. mapmap函數(shù)可以將一個匿名函數(shù)作用于所有的數(shù)據(jù)上 相當(dāng)于遍歷了一遍Series,對每一個值執(zhí)行了float()方法
smap = s.map(lambda x: float(x)) smap = s.map(float) _print('使用map修改數(shù)據(jù)類型', smap)
1.7. 使用concat給Series添加新的元素使用concat將一個Series追加原Series后面
sCon = pd.Series(data=['003', '004'], index=['c', 'd']) s = pd.concat([s, sCon]) _print('concat追加新元素', s)
> 指定axis=1,橫向追加,兩個Series橫向追加會變成DataFrame df = pd.concat([s, sCon], axis=1) _print('concat追加新元素,并指定axis=1', df)
2. 構(gòu)建DataFrameDataFrame是Pandas中的一個表格型的數(shù)據(jù)結(jié)構(gòu),包含有一組有序的列,每列可以是不同的值類型(數(shù)值、字符串、布爾型等),DataFrame即有行索引也有列索引,可以被看做是由Series組成的字典。
2.1 字典轉(zhuǎn)換為DataFram2.1.1. 字典的value不是列表> 如果字典的key不是列表,需要指定index,或者使用items()取出k,v infoDic = {'name': 'jack', 'age': 18, 'height': '180CM'} df = pd.DataFrame(data=infoDic, index=[0]) _print('指定index=[0]', df) # 使用items()取出k,v df = pd.DataFrame(data=list(infoDic.items())) _print('使用items()取出k,v', df)
2.1.2. 字典的value是列表infoDic = {'id': [1, 2], 'name': ['jack', 'rose'], 'age': [18, 18], 'height': ['180CM', '170CM']}
df = pd.DataFrame(data=infoDic) _print('v是列表', df)
2.2. 使用列表創(chuàng)建DataFramecolumns也可以不指定
df = pd.DataFrame([[1, 2], [11, 12]], columns=['c1', 'c2'], index=['i1', 'i2'])
_print('使用list創(chuàng)建DataFrame', df)
2.3. 使用numpy創(chuàng)建DataFrame創(chuàng)建一個np.arange()可以創(chuàng)建一維ndarray,reshape是修改形狀,這里修改成了3行4列的二維ndarray 同樣,直接使用list創(chuàng)建也行
df = pd.DataFrame(np.arange(12).reshape(3, 4)) _print('使用numpy創(chuàng)建DataFrame', df)
2.4 構(gòu)建一個稍復(fù)雜DataFrameindex為100個日期,字段內(nèi)容為正態(tài)分布和均勻分布隨機(jī)數(shù)
date_range = pd.date_range(start='2022-01-01', periods=100) # date_rage可以生成各種類型的日期 data = { 'normal': np.random.normal(loc=0, scale=1, size=100), # 正態(tài)分布 'uniform': np.random.uniform(low=0, high=1, size=100) # 均勻分布 } df = pd.DataFrame(data=data, index=date_range) _print('復(fù)雜DataFrame', df)
3. 查看DataFramedf = pd.read_csv('./IMDB-Movie-Data.csv')
3.1. info查看dataframe的描述信息
_print('info', df.info)
3.2. dtypes查看數(shù)據(jù)類型
_print('dtypes:', df.dtypes) df['Title'].astype('string')
3.3. tail查看后面幾行
_print('tail', df.tail(10))
3.4. head查看數(shù)據(jù)前幾行
_print('head', df.head(10))
3.5. 按列查看3.5.1 取單列_print('取單列', df['Rank'])
3.5.2. 取多列注意是兩個中括號
_print('取多列', df[['Rank', 'Title', 'Metascore']])
3.6. 按行查看可以將列表的切片思想直接拿過來用
_print('按行取', df[0:2])
3.7. loc可同時按照行和列進(jìn)行取值
_print('loc', df.loc[0:2, 'Rank':'Metascore'])
3.8. iloc可同時按照行和列進(jìn)行取值,使用數(shù)字下標(biāo)
_print('iloc', df.iloc[0:2, 1:3])
3.9. 字符串操作所有字符串操作均可以,這里只列舉幾個
_print('字符串操作', df['Title'].head()) _print('str.upper', df['Title'].str.upper()) _print('str.replace', df['Title'].str.replace(' ', '/')) _print('str.split', df['Title'].str.split(' '))
3.10. 布爾值過濾如果多個條件,每個條件用()括起來,并且用& 或者用|
3.10.1. 取出Rank為偶數(shù)的行print(df[(df['Rank'] % 2 == 0)])
3.10.2. 取出Rank小于10,并且Metascore大于70的行print(df[(df['Rank'] < 10) & (df['Metascore'] > 70)])
4. 修改4.1. 修改DataFrame的列df = pd.DataFrame(data=[[1, 2]]) df.columns = ['col1', 'col2'] _print('columns修改所有列名:', df) df.rename(columns={'col1': 'c1'}, inplace=True) _print('rename修改指定列名:', df)
4.2. 修改指定值df.loc[0, 'c1'] = 11 _print('修改指定值:', df)
5. Null值處理df = pd.DataFrame(data=np.full((3, 4), np.nan), columns=list('abcd'), index=list('xyz')) df.loc['x', 'a'], df.loc['y', 'a'], df.loc['x', 'b'] = 1, 2, 3 print(df)
5.1. 判斷是否為NAN_print('判斷是否為NaN', df.isnull()) _print('判斷是否為NaN', df.isna()) _print('判斷是否不為NaN', df['a'].notnull())
5.2. fillna修改NaN的值df_f_1 = df.fillna(0) df_f_2 = df.fillna(method='ffill') _print('原樣:', df) _print('使用前一個填充', df_f_2) print('-----NaN填充為列平均值-----') for i in df: if df[i].isna().any(): df[i].fillna(value=df[i].mean(), inplace=True) print(df)
6. 排序df = pd.read_csv('./IMDB-Movie-Data.csv')
_print('df', df)
6.1. 按索引排序sort_indexascending:指定排序方式,na_position:NaN值放在頭還是尾
df.sort_index(inplace=True, ascending=False, na_position='first') _print('sort_index', df)
6.2. 按值排序 sort_valuesby:按照哪個字段排序
df.sort_values(by=['Revenue (Millions)', 'Metascore'], inplace=True, ascending=True, na_position='last') _print('sort_values', df[['Revenue (Millions)', 'Metascore']].head(20))
7. 索引7.1 設(shè)置DataFrame的索引列_print('info:', df) df.set_index(keys=['Rank', 'Title'], inplace=True) _print('使用set_index修改索引列:', df)
7.2 重置DataFrame的索引列df.reset_index(inplace=True) _print('使用reset_index重置索引列:', df)
8. 表連接left = pd.DataFrame(np.arange(6).reshape(3, 2), columns=['a', 'b'], index=['i1', 'i2', 'i3']) right = pd.DataFrame(np.arange(4, 10).reshape(3, 2), columns=['c', 'd'], index=['i1', 'i2', 'i23']) _print('_left', left) _print('right', right)
8.1. join將n個datafram進(jìn)行合并,和SQL的邏輯一模一樣 注意:兩個Dataframe的字段名不能相同
# inner 內(nèi)連接,取行索引的交集,不匹配的不展示 inner = left.join(right, how='inner') _print('inner', inner) # outer 外連接,取行索引的并集,不匹配的顯示NaN outer = left.join(right, how='outer') _print('outer', inner) # left 左連接,使用左邊df的行索引,左側(cè)全展示,右側(cè)不匹配的顯示NaN outer_l = left.join(right, how='left') _print('outer_l', outer_l) # right 右連接,使用右邊df的行索引,右側(cè)全展示,左側(cè)不匹配的顯示NaN outer_r = left.join(right, how='right') _print('outer_r', outer_r)
8.2. mergeleft左表,right右表,left_on,right_on兩個表的關(guān)聯(lián)字段
merge = pd.merge(left=left, right=right, left_on='b', right_on='d', how='left') _print('merge', merge)
9. 聚合SQL的聚合函數(shù)都可以使用
df = pd.read_csv('./IMDB-Movie-Data.csv') _print('df', df) _print('sum', df.sum()) _print('mean', df.mean()) _print('count', df.count()) _print('min', df.min()) _print('max', df.max())
9.1. agg一次性使用多個聚合函數(shù)
agg = df.agg(['mean', 'sum', 'max']) _print('agg', agg)
9.2. agg不同字段不同函數(shù)
agg = df.agg({'Rank': ['sum', 'min'], 'Metascore': ['max', 'min']}) _print('agg不同字段不同函數(shù)', agg)
10. 窗口函數(shù)10.1. rollingdf = pd.DataFrame(np.random.randint(1, 10, size=32).reshape(8, 4), index=pd.date_range('12/1/2020', periods=8), columns=['A', 'B', 'C', 'D']) _print('開窗', df)
# 每3個數(shù)求一次均值 df['A_rolling'] = df['A'].rolling(window=3).mean() _print('rolling', df)
10.2. expandingexpanding 又叫擴(kuò)展窗口函數(shù),擴(kuò)展是指由序列的第一個元素開始,逐個向后計算元素的聚合值
# 從1個開始,每次都累加上之前的值 df['A_expanding'] = df['A'].expanding(min_periods=2).sum() _print('expanding', df)
10.3. shift移動函數(shù),可以獲得某列前后n行的值,可以計算同比環(huán)比
# 獲得A列后面一個的值 df['A_shift+1'] = df['A'].shift(periods=1) _print('shift', df) # 獲得A列前面一個的值 df['A_shift-1'] = df['A'].shift(periods=-1) _print('shift', df)
11. 列轉(zhuǎn)行列轉(zhuǎn)行就是把列名提到行里面去
df = pd.DataFrame([['張三', 10, 20], ['李四', 30, 40]], columns=['姓名', '語文', '數(shù)學(xué)']) print(df)
11.1. stack需要將不變的列設(shè)置為索引(原始字段為姓名,語文,數(shù)學(xué),轉(zhuǎn)換后為姓名,科目,成績。姓名字段不變)
df_stack = df.set_index('姓名').stack() _print('df_stack', df_stack) df_stack = df_stack.reset_index() # 重置索引 _print('df_stack重置索引', df_stack) df_stack.columns = ['姓名', '科目', '成績'] _print('df_stack,設(shè)置列名', df_stack)
11.2. meltid_vars:列轉(zhuǎn)行后,不變的那一列 value_vars:列轉(zhuǎn)行后,需要變動的那些列的列名 var_name:列轉(zhuǎn)為行后,value_vars所屬的字段名 http://qn./202211181539833.png value_name:列轉(zhuǎn)為行后,新表的值那一列的列明
df_melt = df.melt(id_vars='姓名', value_vars=['語文', '數(shù)學(xué)'], var_name='科目', value_name='成績') _print('df_melt', df_melt)
12. 行轉(zhuǎn)列行轉(zhuǎn)列就是把行里的值提成列名
tmp = pd.DataFrame({'姓名': ['張三', '李四', '王五', '張三', '李四', '王五', '張三', '李四', '王五'], '科目': ['英語', '英語', '英語', '數(shù)學(xué)', '數(shù)學(xué)', '數(shù)學(xué)', '語文', '語文', '語文'], '分?jǐn)?shù)': [90, 60, 70, 80, 98, 80, 85, 90, 75]})
_print('行轉(zhuǎn)列原始數(shù)據(jù)', tmp)
12.1. unstacktmp2 = tmp.set_index(['姓名', '科目'])['分?jǐn)?shù)'].unstack().reset_index() _print('行轉(zhuǎn)列unstack', tmp2) df = tmp2.rename_axis(columns=None) # 消除科目兩個字 _print('行轉(zhuǎn)列unstack', df)
12.2. pivotdf = tmp.pivot(index='姓名', columns='科目', values='分?jǐn)?shù)').reset_index().rename_axis(columns=None) print(df)
13. 小案例13.1. 新增一個字段,內(nèi)容為所有父級ID,例:1.0->3.0->8df = pd.DataFrame([(1, '總裁室', np.NaN), (2, '研發(fā)部', 1), (3, '市場部', 1), (4, '后端', 2), (5, '前端', 2), (6, '大數(shù)據(jù)', 2), (7, '數(shù)倉開發(fā)', 6), (8, '數(shù)據(jù)分析', 6) ], columns=['ID', 'PRODUCTNAME', 'PARENTID']) print('*' * 100)
def get_order(argid, df): # 通過ID獲取PARENTID pid = df.loc[df['ID'] == argid, 'PARENTID'] # print(type(pid), pid) # Series類型 pid = pid.values[0] # 獲取PARENTID的具體值 if pd.isna(pid): return str(argid) else: return get_order(pid, df) + '->' + str(argid)
for i in df.values: df.loc[df['ID'] == i[0], ['ORDERID']] = get_order(i[0], df) print(df)
13.2 計算以下列表中的字母出現(xiàn)次數(shù)data = [{'word': ['a', 'q', 'a']}, {'word': ['qwe', 'qwe', 'a', 'asd']}, {'word': ['sd']}]
lst = [] for dic in data: lst.extend(dic['word']) res = pd.Series(lst) # 轉(zhuǎn)Dataframe也行 res = res.value_counts().to_dict() print(res)
|