回复 红包 可以领程序员专属红包封面
Pandas简介Pandas是一个强大的分析结构化数据的工具集;它的使用基础是Numpy(提供高性能的矩阵运算); 用于数据挖掘和数据分析,同时也提供数据清洗功能。 1. Series它是一种类似于一维数组的对象,是由一组数据(各种NumPy数据类型)以及一组与之相关的数据标签(即索引)组成。 仅由一组数据也可产生简单的Series对象
1.1. 使用list构建Series默认index是数字
import pandas as pd import numpy as np # 自定义打印的函数,方便后面调试 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构建Series', serLi) serLi = pd.Series(data=infoLi, index=list('abc')) _print('list构建Series,并指定index', serLi)
1.2. 使用字典构建Seriesindex为字典的key
infoDic = {'name': 'jack', 'age': 18, 'height': '180CM'} serDic = pd.Series(data=infoDic) _print('字典构建Series', serDic)
1.3. Series转换为listinfoLi = serLi.tolist() _print('Series转换为list', infoLi)
1.4. Series转换为dictinfoDic = serDic.to_dict() _print('Series转换为dict', infoDic)
1.5. Series转换为DataFramdf = pd.DataFrame(data=serDic) _print('Series转换为DataFram', df) df = pd.DataFrame(data=serDic, columns=['信息']) _print('Series转换为DataFram,并指定列名', df, pad=30)
1.6. 修改Series的数据类型s = pd.Series(data=['001', '002'], index=list('ab')) _print('构建Series', s)
1.6.1. astypesastype = s.astype(int) _print('使用astype函数修改数据类型', sastype)
1.6.2. mapmap函数可以将一个匿名函数作用于所有的数据上 相当于遍历了一遍Series,对每一个值执行了float()方法
smap = s.map(lambda x: float(x)) smap = s.map(float) _print('使用map修改数据类型', 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. 构建DataFrameDataFrame是Pandas中的一个表格型的数据结构,包含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔型等),DataFrame即有行索引也有列索引,可以被看做是由Series组成的字典。
2.1 字典转换为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. 使用列表创建DataFramecolumns也可以不指定
df = pd.DataFrame([[1, 2], [11, 12]], columns=['c1', 'c2'], index=['i1', 'i2'])
_print('使用list创建DataFrame', df)
2.3. 使用numpy创建DataFrame创建一个np.arange()可以创建一维ndarray,reshape是修改形状,这里修改成了3行4列的二维ndarray 同样,直接使用list创建也行
df = pd.DataFrame(np.arange(12).reshape(3, 4)) _print('使用numpy创建DataFrame', df)
2.4 构建一个稍复杂DataFrameindex为100个日期,字段内容为正态分布和均匀分布随机数
date_range = pd.date_range(start='2022-01-01', periods=100) # date_rage可以生成各种类型的日期 data = { 'normal': np.random.normal(loc=0, scale=1, size=100), # 正态分布 'uniform': np.random.uniform(low=0, high=1, size=100) # 均匀分布 } df = pd.DataFrame(data=data, index=date_range) _print('复杂DataFrame', df)
3. 查看DataFramedf = pd.read_csv('./IMDB-Movie-Data.csv')
3.1. info查看dataframe的描述信息
_print('info', df.info)
3.2. dtypes查看数据类型
_print('dtypes:', df.dtypes) df['Title'].astype('string')
3.3. tail查看后面几行
_print('tail', df.tail(10))
3.4. head查看数据前几行
_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可同时按照行和列进行取值
_print('loc', df.loc[0:2, 'Rank':'Metascore'])
3.8. iloc可同时按照行和列进行取值,使用数字下标
_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为偶数的行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 设置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进行合并,和SQL的逻辑一模一样 注意:两个Dataframe的字段名不能相同
# inner 内连接,取行索引的交集,不匹配的不展示 inner = left.join(right, how='inner') _print('inner', inner) # outer 外连接,取行索引的并集,不匹配的显示NaN outer = left.join(right, how='outer') _print('outer', inner) # left 左连接,使用左边df的行索引,左侧全展示,右侧不匹配的显示NaN outer_l = left.join(right, how='left') _print('outer_l', outer_l) # right 右连接,使用右边df的行索引,右侧全展示,左侧不匹配的显示NaN outer_r = left.join(right, how='right') _print('outer_r', outer_r)
8.2. mergeleft左表,right右表,left_on,right_on两个表的关联字段
merge = pd.merge(left=left, right=right, left_on='b', right_on='d', how='left') _print('merge', merge)
9. 聚合SQL的聚合函数都可以使用
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一次性使用多个聚合函数
agg = df.agg(['mean', 'sum', 'max']) _print('agg', agg)
9.2. agg不同字段不同函数
agg = df.agg({'Rank': ['sum', 'min'], 'Metascore': ['max', 'min']}) _print('agg不同字段不同函数', agg)
10. 窗口函数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个数求一次均值 df['A_rolling'] = df['A'].rolling(window=3).mean() _print('rolling', df)
10.2. expandingexpanding 又叫扩展窗口函数,扩展是指由序列的第一个元素开始,逐个向后计算元素的聚合值
# 从1个开始,每次都累加上之前的值 df['A_expanding'] = df['A'].expanding(min_periods=2).sum() _print('expanding', df)
10.3. shift移动函数,可以获得某列前后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. 列转行列转行就是把列名提到行里面去
df = pd.DataFrame([['张三', 10, 20], ['李四', 30, 40]], columns=['姓名', '语文', '数学']) print(df)
11.1. stack需要将不变的列设置为索引(原始字段为姓名,语文,数学,转换后为姓名,科目,成绩。姓名字段不变)
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,设置列名', df_stack)
11.2. meltid_vars:列转行后,不变的那一列 value_vars:列转行后,需要变动的那些列的列名 var_name:列转为行后,value_vars所属的字段名 http://qn./202211181539833.png value_name:列转为行后,新表的值那一列的列明
df_melt = df.melt(id_vars='姓名', value_vars=['语文', '数学'], var_name='科目', value_name='成绩') _print('df_melt', df_melt)
12. 行转列行转列就是把行里的值提成列名
tmp = pd.DataFrame({'姓名': ['张三', '李四', '王五', '张三', '李四', '王五', '张三', '李四', '王五'], '科目': ['英语', '英语', '英语', '数学', '数学', '数学', '语文', '语文', '语文'], '分数': [90, 60, 70, 80, 98, 80, 85, 90, 75]})
_print('行转列原始数据', tmp)
12.1. unstacktmp2 = tmp.set_index(['姓名', '科目'])['分数'].unstack().reset_index() _print('行转列unstack', tmp2) df = tmp2.rename_axis(columns=None) # 消除科目两个字 _print('行转列unstack', df)
12.2. pivotdf = tmp.pivot(index='姓名', columns='科目', values='分数').reset_index().rename_axis(columns=None) print(df)
13. 小案例13.1. 新增一个字段,内容为所有父级ID,例:1.0->3.0->8df = pd.DataFrame([(1, '总裁室', np.NaN), (2, '研发部', 1), (3, '市场部', 1), (4, '后端', 2), (5, '前端', 2), (6, '大数据', 2), (7, '数仓开发', 6), (8, '数据分析', 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 计算以下列表中的字母出现次数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) # 转Dataframe也行 res = res.value_counts().to_dict() print(res)
|