一 pandas概述 Pandas 是 Python 的核心数据分析支持库,提供了快速、灵活、明确的数据结构,旨在简单、直观地处理关系型、标记型数据,
Pandas 适用于处理以下类型的数据:
与 SQL 或 Excel 表类似的,含异构列的表格数据;
有序和无序(非固定频率)的时间序列数据;
带行列标签的矩阵数据,包括同构或异构型数据;
任意其它形式的观测、统计数据集, 数据转入 Pandas 数据结构时不必事先标记。
Pandas 的主要数据结构是 Series (一维数据)与 DataFrame (二维数据),这两种数据结构足以处理金融、统计、社会科学、工程等领域里的大多数典型用例
Pandas 基于 NumPy 开发(所以有些numpy的操作pandas同样适用),可以与其它第三方科学计算支持库完美集成。
优点:
1 2 3 4 5 6 7 8 9 10 11 1.处理浮点与非浮点数据里的缺失数据,表示为 NaN; 2.大小可变:插入或删除 DataFrame 等多维对象的列; 3.自动、显式数据对齐:显式地将对象与一组标签对齐,也可以忽略标签,在 Series、DataFrame 计算时自动与数据对齐; 4.强大、灵活的分组(group by)功能:拆分-应用-组合数据集,聚合、转换数据; 5.把 Python 和 NumPy 数据结构里不规则、不同索引的数据轻松地转换为 DataFrame 对象; 6.基于智能标签,对大型数据集进行切片、花式索引、子集分解等操作; 7.直观地合并(merge)、**连接(join)**数据集; 8.灵活地重塑(reshape)、**透视(pivot)**数据集; 9.轴支持结构化标签:一个刻度支持多个标签; 10.成熟的 IO 工具:读取文本文件(CSV 等支持分隔符的文件)、Excel 文件、数据库等来源的数据,利用超快的 HDF5 格式保存 / 加载数据; 11.时间序列:支持日期范围生成、频率转换、移动窗口统计、移动窗口线性回归、日期位移等时间序列功能。
处理数据一般分为几个阶段:数据整理与清洗、数据分析与建模、数据可视化与制表,Pandas 是处理数据的理想工具。
二 数据结构
维数
名称
描述
1
Series
带标签的一维同构数组
2
DataFrame
带标签的,大小可变的,二维异构表格
Pandas 数据结构就像是低维数据的容器。比如,DataFrame 是 Series 的容器,Series 则是标量的容器。使用这种方式,可以在容器中以字典的形式插入或删除对象。
此外,通用 API 函数的默认操作要顾及时间序列与截面数据集的方向。多维数组存储二维或三维数据时,编写函数要注意数据集的方向,这对用户来说是一种负担;如果不考虑 C 或 Fortran 中连续性对性能的影响,一般情况下,不同的轴在程序里其实没有什么区别。Pandas 里,轴的概念主要是为了给数据赋予更直观的语义,即用“更恰当”的方式表示数据集的方向。这样做可以让用户编写数据转换函数时,少费点脑子。
处理 DataFrame 等表格数据时,index (行)或 columns (列)比 axis 0 和 axis 1 更直观。用这种方式迭代 DataFrame 的列,代码更易读易懂:
1 2 3 for col in df.columns: series = df[col]
Pandas 所有数据结构的值都是可变的,但数据结构的大小并非都是可变的,比如,Series 的长度不可改变,但 DataFrame 里就可以插入列。
Pandas 里,绝大多数方法都不改变原始的输入数据,而是复制数据,生成新的对象。 一般来说,原始输入数据不变 更稳妥。
三 基本使用 1 2 3 4 5 import pandas as pdimport numpy as nppd.read_csv() pd.read_excel() pd.read_html()
1 Series 有些操作与numpy一致
1 2 3 4 5 6 7 8 9 import pandas as pdimport numpy as nppd.Series(np.arange(4 ),index=list("abcd" )) dict_a={"name" :"fei" ,"age" :10 ,"te" :123 } pd.Series(dict_a)
series本质是由两个数组构成,一个数组构成建(index),一个构成数组的值(values) 建–>值
1 2 3 4 5 import pandas as pddf=pd.read_csv("user_info.csv" ).to_numpy() print(type(df)) t = df[0 ] pd.Series(t)
2 DataFrame DF既有行索引(index或axis=0),又有列索引(column或axis=1)
1 2 3 4 5 6 7 8 9 import pandas as pd import numpy as nppd.DataFrame(np.arange(12 ).reshape((3 ,4 )),index=list("abc" ),columns=list("qwer" )) dict_a={"name" :"fei" ,"age" :10 ,"te" :123 } pd.DataFrame(dict_a) dict_a={"name" :["fei" ],"age" :[10 ],"te" :[123 ]} pd.DataFrame(dict_a)
2.1基础属性 1 2 3 4 5 6 7 df.shape df.dtypes df.ndim df.index df.columns df.values
2.2df的整体情况查看 1 2 3 4 df.head(5 ) df.tail(3 ) df.info() df.describe()
2.3df的函数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 df.sort_values(by="列名" ,ascending=False ) df["name" ].str.split() .... df.join(df2) df.merge(df2,on="o" ,how="inner|outer|left|right" ) df=pd.read_csv("user_info.csv" ) df2=df.where(df["user_id" ]>462176 ) df2.dropna() dfgb=df.groupby(by="column_name" ) for i in dfgb: print(i) for i,j in dfgb: print(i) print(j) df.groupby(by=[df["" ],df["" ],....]) df.groupby(by=["age" ,"user_id" ]) dfgb.count() dfgb["user_id" ].count()
2.4 获取行列数据 获取行列数据实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 df[:20 ]["user_id" ] import numpy as npimport pandas as pddata=pd.DataFrame(np.arange(16 ).reshape(4 ,4 ),index=list('abcd' ),columns=list('ABCD' )) In[1 ]: data Out[1 ]: A B C D a 0 1 2 3 b 4 5 6 7 c 8 9 10 11 d 12 13 14 15 In[2 ]: data.loc['a' ] Out[2 ]: A 0 B 1 C 2 D 3 In[3 ]: data.iloc[0 ] Out[3 ]: A 0 B 1 C 2 D 3 In[4 ]:data.loc[:,['A' ]] Out[4 ]: A a 0 b 4 c 8 d 12 In[5 ]:data.iloc[:,[0 ]] Out[5 ]: A a 0 b 4 c 8 d 12 In[6 ]:data.loc[['a' ,'b' ],['A' ,'B' ]] Out[6 ]: A B a 0 1 b 4 5 In[7 ]:data.iloc[[0 ,1 ],[0 ,1 ]] Out[7 ]: A B a 0 1 b 4 5 In[8 ]:data.loc[:,:] Out[8 ]: A B C D a 0 1 2 3 b 4 5 6 7 c 8 9 10 11 d 12 13 14 15 In[9 ]:data.iloc[:,:] Out[9 ]: A B C D a 0 1 2 3 b 4 5 6 7 c 8 9 10 11 d 12 13 14 15 In[10 ]: data.loc[data['A' ]==0 ] Out[10 ]: A B C D a 0 1 2 3
布尔索引
2.5 缺失值处理 1 2 3 4 5 6 7 8 9 pd.isnull(df) pd.notnull(df) dropna(axis=0 ,how='any' ,inplace=False ) t.fillna(t.mean) t[t==0 ]=np.nan
2.6 索引和复合索引 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 df.index df.index=['x' ,'y' ] df.reindex(list("abcd" ) df.set_index("column_name" ,drop=False ) df.set_index("column_name" ).index.unique() df=pd.DataFrame({'a' :range(7 ),'b' :range(7 ,0 ,-1 ),'c' :['one' ,'one' ,'one' ,'two' ,'two' ,'two' ,'two' ],'d' :list("hjklmno" )}) df.set_index(['c' ,'d' ]) df=pd.DataFrame({'a' :range(7 ),'b' :range(7 ,0 ,-1 ),'c' :['one' ,'one' ,'one' ,'two' ,'two' ,'two' ,'two' ],'d' :list("hjklmno" )}) d=df.set_index(['d' ,'c' ])['a' ] d.index d.swaplevel() s1['a' ]['b' ] or s1["a" ,"b" ] df.loc["a" ].loc["b" ]
3 读取外部数据源 1 2 3 4 5 import pandas as pddf=pd.read_csv("user_info.csv" ) .....
4 时间序列 4.1 生成时间范围 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import pandas as pdpd.date_range(start=,end=,periods=,freq='d' ) import pandas as pdpd.date_range(start='2021-02-01' ,end='2021-03-01' ,freq='d' ) import pandas as pdpd.date_range(start='2021/02/01' ,periods=10 ,freq='m' ) pd.to_datetime(df["timeStamp" ],format="" ) pd.to_datetime("20210304" ,format="%Y-%m-%d %H:%M:%S" )
freq
别名
说明
D
日
B
工作日
H
小时
T或MIN
分
S
秒
L或MS
毫秒
U
微秒
M
月的最后一个日期
BM
每月最后一个工作日
MS
每月第一日
BMS
每月第一个工作日
4.2 df中使用时间序列 1 2 3 4 import pandas as pdimport numpy as npindex=pd.date_range(start='2021/02/01' ,periods=10 ,freq='m' ) pd.DataFrame(np.random.rand(10 ),index=index)
4.3 重采样 是将时间序列从一个频率转化为另一个频率进行处理的过程,将高频率转化为低频率的为降采样,低频率转化为高频率为升采样
1 2 3 4 5 6 import pandas as pdimport numpy as npindex=pd.date_range(start='2021/02/01' ,periods=100 ,freq='d' ) df=pd.DataFrame(np.random.rand(100 ),index=index)s df.resample("m" ).mean()
四 常用 创建数据集
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import numpy as npimport pandas as pdboolean=[True ,False ] gender=["男" ,"女" ] color=["white" ,"black" ,"yellow" ] data2=pd.DataFrame({ "height" :np.random.randint(150 ,190 ,100 ), "weight" :np.random.randint(40 ,90 ,100 ), "smoker" :[boolean[x] for x in np.random.randint(0 ,2 ,100 )], "gender" :[gender[x] for x in np.random.randint(0 ,2 ,100 )], "age" :np.random.randint(15 ,90 ,100 ), "color" :[color[x] for x in np.random.randint(0 ,len(color),100 ) ] } ) data2
1 新加列/行 1 2 3 4 5 6 7 data2['bmi' ] = (data2['weight' ] / ((data2['height' ]/100 ) *(data2['height' ]/100 ))).map(int) data2 new_index=pd.DataFrame({'height' :178 ,'weight' :74 ,'smoker' :False ,'gender' :'女' ,'age' :17 ,'color' :'white' ,'bmi' :23 },index=['e' ]) data=data.append(new_index,ignore_index=True ) data
2 map函数 如将gender列的男:1,女:0
1 2 3 4 5 6 7 8 9 10 data2['gender' ]=data2['gender' ].map(lambda x:1 if x == "男" else 0 ) data2 data2["gender" ] = data2["gender" ].map({"男" :1 , "女" :0 }) def gender_map (x ): gender = 1 if x == "男" else 0 return gender data["gender" ] = data["gender" ].map(gender_map)
3 apply函数 传入函数,进行计算
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 def BMI (series ): weight = series["weight" ] height = series["height" ]/100 BMI = weight/height**2 return BMI data2["BMI" ] = data2.apply(BMI,axis=1 ) data2[['whight' ,'age' ]].apply(np.sum,axis=0 ) weight 6608 age 5122 dtype: int64 df.applymap(lambda x:"%.2f" % x)
4 行列重命名 axis=0 :列 axis=1 :行
inplace : 是否映射会原dataframe
1 2 3 4 5 6 data2.rename({0 :'h' },axis=0 ,inplace=True ) data2 data2.rename({'height' :'h' },axis=1 ,inplace=True ) data2
5 删除列 1 data2.drop(["bmi" ],axis=1 ,inplace=True )
1 2 group = data2.groupby('color' ) list(group)
转换成列表的形式后,可以看到,列表由三个元组组成,每个元组中,第一个元素是组别(这里是按照color
进行分组,所以最后分为了”white”,”black”,”yellow”)
groupby
的过程就是将原有的DataFrame
按照groupby
的字段(这里是color
),划分为若干个分组DataFrame
,被分为多少个组就有多少个分组DataFrame
。所以说,在groupby
之后的一系列操作(如agg
、apply
等),均是基于子DataFrame
的操作
agg
聚合操作是groupby
后非常常见的操作,列出了常用的
1 min,max,sum,mean,median,std,var,count,.....
1 2 3 4 5 6 7 8 9 group.agg('mean' ).reset_index() group.agg({'weight' :'max' ,'smoker' :'count' }).reset_index() color weight smoker black 87 28 white 85 26 yellow 88 46
transfrom
就类似于窗口函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 group['weight' ].transform('mean' ) 0 64.730769 1 66.326087 2 66.326087 3 66.326087 4 66.326087 ... 95 64.730769 96 66.928571 97 66.928571 98 64.730769 99 66.326087 group['weight' ].agg('mean' ) color black 66.928571 white 64.730769 yellow 66.326087
应用可以像窗口函数似的给每一条数据附加一个聚合值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 data2['avg_weight' ] = group['weight' ].transform('mean' ) data2 h weight smoker gender age color avg_weight 0 178 74 True 0 28 white 64.730769 1 157 81 True 0 33 yellow 66.326087 2 169 77 True 0 37 yellow 66.326087 3 174 60 False 1 88 yellow 66.326087 4 174 88 False 0 65 yellow 66.326087 ... ... ... ... ... ... ... ... 95 173 75 True 0 58 white 64.730769 96 150 54 True 0 73 black 66.928571 97 178 82 False 0 45 black 66.928571 98 184 62 False 0 37 white 64.730769 99 166 75 False 0 62 yellow 66.326087 maxage_dict=group['age' ].max().to_dict() data2['max_age' ] = data2['color' ].map(maxage_dict) data2
apply
对于groupby
后的apply
,以分组后的子DataFrame
作为参数传入指定函数的,基本操作单位是DataFrame
,而未分组的apply
的基本操作单位是Series
;
1 2 3 4 5 6 7 8 9 10 11 12 def get_oldest_staff (x ): df = x.sort_values(by = 'age' ,ascending=True ) return df.iloc[-1 ,:] oldest_staff = group.apply(get_oldest_staff) oldest_staff.drop(['color' ],axis=1 ,inplace=True ) oldest_staff.reset_index() color h weight smoker gender age avg_weight black 150 60 True 0 87 66.928571 white 153 72 False 1 87 64.730769 yellow 170 82 False 0 88 66.326087
7 数据拼接 merge相当于sql中的join
merge有4中类型:
1 2 3 4 5 6 7 8 9 10 11 12 df_1.merge(df_2,how='inner' ,on='userid' ) df_1.merge(df_2,how='left' ,on='userid' ) df_1.merge(df_2,how='outer' ,on='userid' ) newdf=pd.merge(df[['a' , 'b' , 'c' , 'd' ]] ,df2 ,how='inner' ,on=['user_id' ,'cal_dt' ])
8 zip 将数据组合为元祖
1 2 3 4 5 6 7 8 9 10 a = [1 ,2 ,3 ,4 ] b = [5 ,6 ,7 ,8 ] zz= zip(a,b) print(list(zz)) zz2= zip(a,b) print(list(zip(*zz2))) [(1 , 5 ), (2 , 6 ), (3 , 7 ), (4 , 8 )] [(1 , 2 , 3 , 4 ), (5 , 6 , 7 , 8 )]
1 2 3 4 5 6 7 8 9 10 11 a = [1 ,2 ,3 ,4 ] b = [5 ,6 ,7 ,8 ] zz= zip(a,b) aa=list(map(lambda x: {"value" :x[0 ],"percent" :x[0 ]/(x[0 ]+x[1 ])}, zip(a,b))) aa [{'value' : 1 , 'percent' : 0.16666666666666666 }, {'value' : 2 , 'percent' : 0.25 }, {'value' : 3 , 'percent' : 0.3 }, {'value' : 4 , 'percent' : 0.3333333333333333 }]
9 行列转换 9.1 行转列
1 2 3 4 5 6 7 8 9 10 11 12 13 14 A a 12 A b 13 A c 14 B a 34 B b 56 B c 67 C a 90 C b 80 C c 95 转为 a b c A 12 13 14 B 34 56 67 C 90 80 95
1 2 3 4 5 6 7 8 9 10 11 12 13 data=pd.DataFrame([['A' ,'a' ,1 ],['A' ,'b' ,2 ],['A' ,'c' ,3 ], ['B' ,'a' ,4 ],['B' ,'b' ,5 ],['B' ,'c' ,6 ], ['C' ,'a' ,7 ],['C' ,'b' ,8 ],['A' ,'c' ,9 ]] ,columns=['姓名' ,'科目' ,'分数' ] ) data data_new=data.set_index(['姓名' ,'科目' ])["分数" ] data_new=data_new.unstack() data_new=data_new.rename_axis(columns=None ) data_new.reset_index()
调用unstack默认是将一级索引变成DataFrame的索引,二级索引变成DataFrame的列。更准确的说,unstack是将最后一级的索引变成DataFrame的列,前面的索引变成DataFrame的索引。比如有一个具有八级索引的Series,它在调用unstack的时候,默认是将最后一级索引变成DataFrame的列,前面七个索引整体作为DataFrame的索引。
只不过索引一般很少有超过二级的,所以这里就用二级举例了。因此问题来了,那么可不可以将一级索引(这里的"姓名")
变成DataFrame的列,二级索引(这里的"科目")
变成DataFrame的行呢?答案是可以的,在unstack中指定一个参数即可。
1 2 3 4 5 6 7 8 9 data_new=data.set_index(['姓名' ,'科目' ])["分数" ] data_new=data_new.unstack(level=0 ) data_new=data_new.rename_axis(columns=None ) data_new.reset_index()
1 2 print(pd.pivot(data, index="姓名" , columns="科目" , values="分数" ).rename_axis(columns=None ).reset_index())
9.2 一行转多行
Explode 和hive中的一致
1 2 3 4 5 6 data3=pd.DataFrame([['A' ,'a' ,'二,那你' ],['B' ,'b' ,'二' ],['C' ,'c' ,'二,那你,看看' ]],columns=['姓名' ,'别名' ,'组别' ]) data3 data3["组别" ] = data3["组别" ].str.split("," ) data3=data3.explode("组别" ) data3
9.3 根据字典拆分多列
1 2 3 4 5 6 7 df = pd.DataFrame({"id" : ["001" , "002" , "003" ], "info" : [{"姓名" : "琪亚娜·卡斯兰娜" , "生日" : "12月7日" , "外号" : "草履虫" }, {"姓名" : "布洛妮娅·扎伊切克" , "生日" : "8月18日" , "外号" : "板鸭" }, {"姓名" : "德丽莎·阿波卡利斯" , "生日" : "3月28日" , "外号" : "德丽傻" , "武器" : "犹大的誓约" }] }) tmp = df["info" ].apply(pd.Series) tmp
使用apply(pd.Series)的时候,对应的列里面的值必须是一个字典,不能是字典格式的字符串
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import pandas as pddf = pd.DataFrame({"id" : ["001" , "002" , "003" ], "info" : [str({"姓名" : "琪亚娜·卡斯兰娜" , "生日" : "12月7日" }), str({"姓名" : "布洛妮娅·扎伊切克" , "生日" : "8月18日" }), str({"姓名" : "德丽莎·阿波卡利斯" , "生日" : "3月28日" })] }) tmp = df["info" ].apply(pd.Series) print(tmp) """ 0 0 {'姓名': '琪亚娜·卡斯兰娜', '生日': '12月7日'} 1 {'姓名': '布洛妮娅·扎伊切克', '生日': '8月18日'} 2 {'姓名': '德丽莎·阿波卡利斯', '生日': '3月28日'} """ tmp = df["info" ].map(eval).apply(pd.Series) print(tmp) """ 姓名 生日 0 琪亚娜·卡斯兰娜 12月7日 1 布洛妮娅·扎伊切克 8月18日 2 德丽莎·阿波卡利斯 3月28日 """
不过在生产环境中还会有一个问题,我们知道Python中的eval是将一个字符串里面的内容当成值,或者你理解为就是把字符串周围的引号给剥掉。比如说:
a = "123", 那么eval(a)得到的就是整型123
a = "[1, 2, 3]", 那么eval(a)得到的就是列表[1, 2, 3]
a = "{'a': 1, 'b': 'xxx'}", 那么eval(a)得到的就是字典{'a': 1, 'b': 'xxx'}
a = "name", 那么eval(a)得到的就是变量name指向的值, 而如果不存在name这个变量, 则会抛出一个NameError
a = "'name'", 那么eval(a)得到的就是'name'这个字符串; 同理a = '"name"', 那么eval(a)得到的依旧是'name'这个字符串
9.4 列转行 melt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 姓名 水果 星期一 星期二 星期三 古明地觉 草莓 70斤 72斤 60斤 雾雨魔理沙 樱桃 61斤 60斤 81斤 琪露诺 西瓜 103斤 116斤 153斤 转为 姓名 水果 日期 销量 古明地觉 草莓 星期一 70斤 雾雨魔理沙 樱桃 星期一 61斤 琪露诺 西瓜 星期一 103斤 古明地觉 草莓 星期二 72斤 雾雨魔理沙 樱桃 星期二 60斤 琪露诺 西瓜 星期二 116斤 古明地觉 草莓 星期三 60斤 雾雨魔理沙 樱桃 星期三 81斤 琪露诺 西瓜 星期三 153斤
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import pandas as pddf = pd.DataFrame({"姓名" : ["古明地觉" , "雾雨魔理沙" , "琪露诺" ], "水果" : ["草莓" , "樱桃" , "西瓜" ], "星期一" : ["70斤" , "61斤" , "103斤" ], "星期二" : ["72斤" , "60斤" , "116斤" ], "星期三" : ["60斤" , "81斤" , "153斤" ], }) print(pd.melt(df, id_vars=["姓名" , "水果" ], value_vars=["星期一" , "星期二" , "星期三" ])) print(pd.melt(df, id_vars=["姓名" , "水果" ], value_vars=["星期一" , "星期二" , "星期三" ], var_name="星期几?" , value_name="销量" ))
10 读取数据速度优化 针对需要反复读取的文件有效,首次无效
pandas读取pkl和hdf的文件格式的速度要快于excel和csv,excel是最慢的,pkl最快
可以将csv和xls的保存为pkl文件,以后再次读取会变快
1 2 3 4 5 6 7 8 9 import pandas as pd df = pd.read_csv('xxx.csv' ) df.to_pickle('xxx.pkl' ) df = pd.read_pickle('xxx.pkl' ) df.to_hdf('xxx.hdf' ,'df' ) df = pd.read_hdf('xxx.pkl' ,'df' )
11 减小df的内存开销 数据量大时可用来减小内存开销。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 def reduce_mem_usage (df ): start_mem = df.memory_usage().sum() / 1024 **2 numerics = ['int16' , 'int32' , 'int64' , 'float16' , 'float32' , 'float64' ] for col in df.columns: col_type = df[col].dtypes if col_type in numerics: c_min = df[col].min() c_max = df[col].max() if str(col_type)[:3 ] == 'int' : if c_min > np.iinfo(np.int8).min and c_max < np.iinfo(np.int8).max: df[col] = df[col].astype(np.int8) elif c_min > np.iinfo(np.int16).min and c_max < np.iinfo(np.int16).max: df[col] = df[col].astype(np.int16) elif c_min > np.iinfo(np.int32).min and c_max < np.iinfo(np.int32).max: df[col] = df[col].astype(np.int32) elif c_min > np.iinfo(np.int64).min and c_max < np.iinfo(np.int64).max: df[col] = df[col].astype(np.int64) else : if c_min > np.finfo(np.float16).min and c_max < np.finfo(np.float16).max: df[col] = df[col].astype(np.float16) elif c_min > np.finfo(np.float32).min and c_max < np.finfo(np.float32).max: df[col] = df[col].astype(np.float32) else : df[col] = df[col].astype(np.float64) end_mem = df.memory_usage().sum() / 1024 **2 print('Memory usage after optimization is: {:.2f} MB' .format(end_mem)) print('Decreased by {:.1f}%' .format(100 * (start_mem - end_mem) / start_mem)) return df
常用方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 .sort_values() data2.sort_values(by='weight' ,ascending=True ) .fillna() data.fillna('B' ) data.fillna(method='bfill' ) .dropna() .isna() .any() data.isna().any() .value_counts() data2['color' ].value_counts() data2['color' ].value_counts(normalize=True ,ascending=True ) data2.describe() data2.info() data["age" ] = data["age" ].astype(int) .set_index() data2.set_index('height' ,inplace=True ) .reset_index() .drop_duplicates() data2['color' ].drop_duplicates() .isin() data.loc[data['color' ].isin(['red' ,'green' ])] pd.cut() pd.cut(data.salary,bins = 5 ) pd.cut(data.salary,bins = [0 ,10 ,20 ,30 ,40 ,50 ]) pd.cut(data.salary,bins = [0 ,10 ,20 ,30 ,40 ,50 ],labels = ['低' ,'中下' ,'中' ,'中上' ,'高' ]) pd.qcut() pd.qcut(data.salary,q = 3 ) .where() data['salary' ].where(data.salary<=40 ,40 ) pd.concat() pd.concat([data1,data2],ignore_index = False ) .pivot_table() data.pivot_table(values = 'salary' ,index = 'company' , columns = 'gender' ,aggfunc=np.mean)