[Pandas]基础大全
import pandas as pd
引言
原始的数据有时候是一串文字(过度聚合),有时候是分散在多个位置的分离文件(过于分散)。数据的预处理就是要把原始的数据拆分、组合、标准化,并将异常的数据剔除掉。在这个过程中,字符串的拆分与合并非常重要。python内建函数可以实现简单字符串的拆分与合并(split与format函数)。而re库、pandas库又提供了更加强大的数据预处理手段,能帮助我们运用简单的代码实现复杂的功能。建议在进行数据处理的时候,将数据转换为DataFrame格式,运用pandas库强大的功能库进行处理。
一、概括篇
Panel Data(面板数据),大部分类型的底层数组都是numpy.ndarray
足以处理金融、统计、社会科学、工程等领域里的大多数典型用例
轻松直观地处理带标签数据和关系数据
为行和列设定标签
将不同格式的数据加载到 DataFrame 中
可以将不同的数据集合并到一起
与 NumPy 和 Matplotlib 集成
社区活跃
长远目标:成为最强大、最灵活、可以支持任何语言的开源数据分析工具
-
支持数据类型
对 Numpy 类型系统进行了扩充
用 object 存储字符串
整数的默认类型为 int64,浮点数的默认类型为 float64
Pandas 数据类型 -
数据结构的特性
Pandas 用
NaN
(Not a Number)表示缺失数据
DataFrame 里的缺失值用np.nan
表示
借助 numexpr 与 bottleneck 支持库,pandas 可以加速特定类型的二进制数值与布尔操作支持 add()、sub()、mul()、div() 及radd()、rsub() 等方法执行二进制操作
二进制比较操作的方法:
Pandas 二进制比较
- 通用操作
创建
.copy()
浅复制,不改变原始数据属性
.dtypes
属性
DataFrame:以 Series 形式返回每列的数据类型
DataFrame.dtypes.value_counts()
用于统计 DataFrame 里各列数据类型的数量
select_dtypes(include =[], exclude=[])
基于dtype
选择列数据类型转换
astype()
把一种数据类型转换为另一种,默认返回的是复制数据df.astype('float32').dtypes
说明:可以通过字典指定哪些列转换为哪些类型 {'Column': np.bool}
- 硬转换
.to_numpy()
或numpy.asarray()
.to_numeric()
转换为数值型
.to_datetime()
转换为 datetime 对象
.to_timedelta()
转换为 timedelta 对象- 软转换
数据有时存储的是正确类型,但在保存时却存成了 object 类型,此时,用DataFrame.infer_objects()
与Series.infer_objects()
方法即可把数据软转换为正确的类型
- 排序/遍历/统计
排序
- 按索引排序
Series.sort_index()
DataFrame.sort_index()
- 按值排序
Series.sort_values()
DataFrame.sort_values()
参数 by 用于指定按哪列排序(一列或多列数据)- 按索引与值排序
- 按多重索引的列排序
遍历(迭代)
Series 迭代时被视为数组;支持字典式的
items()
方法, (Index, 标量值)元组
DataFrame 列标签;支持字典式的items()
方法,(Columns, Series)元组
统计
pd.Series.value_counts()
pd.DataFrame.value_counts()
-
广播
多维(DataFrame)与低维(Series)对象之间的广播机制。
重点关注输入的 Series:通过 axis 关键字,匹配 index 或 columns 即可调用这些函数 -
函数应用(作为函数的参数)
用哪种方法取决于操作的对象是DataFrame 或 Series ,是行或列,还是元素
- 表级函数应用
通过链式调用函数时,最好使用pipe()
方法- 行列级函数应用
apply()
方法可以沿着 DataFrame 的轴应用任何函数,比如,描述性统计方法,该方法支持 axis 参数- 聚合 API
agg()
与transform()
快速、简洁地执行多个聚合操作- 元素级函数应用
并非所有函数都能接受 Numpy 数组,DataFrame 的applymap()
及 Series 的map()
,支持任何接收单个值并返回单个值的 Python函数。
举例:df[Column].apply(lambda x: x.split()[0])
pd.Series本身没有.split()
,但可以针对每个数据进行函数操作
二、Series篇
Series与Numpy中的一维array类似,二者与Python基本的数据结构List也很相近
区别是:List中的元素可以是不同的数据类型,而 Array 和 Series 中则只允许存储相同的数据类型,这样可以更有效的使用内存,提高运算效率
和 NumPy ndarray 的区别:
- 每个元素分配索引标签(label 即index)
- 可以存储不同类型的数据
- 数据结构的特性
+可变
+带标签的一维数组,可存储整数、浮点数、字符串、Python 对象等类型的数据(轴标签统称为索引)
+类似多维数组:操作与 ndarray 类似,支持大多数 NumPy 函数,还支持索引切片
+类似字典:必须提供索引
- 创建
- 通过list创建
pd.Series([list])
pd.Series(data = [30, 6, 'Yes', 'No'], index = ['eggs', 'apples', 'milk', 'bread'])- 特殊:时间序列
pd.data_range()
Series 时间序列
- 查/改/增/删
属性
.shape
.ndim
.size
.values
.index
查
- 访问
Series['label/index']
+.loc
标签索引
+.iloc
数值索引- 判断
in
改
- 索引重置与更换
reindex()
reindex_like()
用align对齐多个对象- 索引重命名
.Series.rename()
支持按不同的轴基于映射(字典或 Series)调整标签- 数据平移
pd.Series().shift(N)
向下平移N行
删
Series.drop(label, inplace=False)
与 reindex 经常配合使用,该函数用于删除轴上的一组标签
- 排序/遍历/统计
排序 @概括篇-排序
- 搜索排序
Series.searchsorted()
这与numpy.ndarray.searchsorted()
的操作方式类似- 最大值与最小值
.nsmallest()
与.nlargest()
方法,本方法返回 N 个最大或最小的值
遍历
.items()
(Index, 标量值)元组
- 特性:数学运算(参考ndarray)
与单个数字
Series + 2
Series - 2
Series * 2
乘法对字符串可行
Series / 2
除法对字符串不可行数学函数
np.exp(Series)
np.sqrt(Series)
np.power(Series,2)
- 补充:小技巧
结合布尔运算
list[True]
最后一个数
list[False]
第一个数
close_planets = time_light[[False, True, True, False, False]]
只输入True对应的两个元素(第一个[]表示index,第二个[]表示列表)
注意:元素个数和True/False个数必须匹配结合字符串方法
pd.Series.str.lower()
三、DataFrame篇
像 Series 一样, DataFrame 的 values 属性返回一个包含在 DataFrame 中的数据的二维 ndarray(Pandas大部分数据类型的底层是ndarray)
-
数据结构的特性
带标签的行和列的二维数据结构,可以存储很多类型的数据(类似Excel的电子表格) -
创建
- 用 Series字典或字典生成
dict = {'key1': pd.Series([]), index = [], 'key2': pd.Series([]), index = []}
df = pd.DataFrame(dict)
+列:字典的key
+行:字典的value,也就是Series的index(Series的Data作为DataFrame的数据)
没有Series.index时,从0开始计数作为行标签
- 用多维数组字典、列表字典生成
dict = {'key1':[], 'key2': []}
df = pd.DataFrame(dict)
+列:字典的key
+行:对应没有Series.index的情况,从0开始计数作为行标签(列表作为DataFrame的数据)
多维字典生成DataFrame
查看各列的数据类型- 用结构多维数组或记录多维数组生成
- 用嵌套字典的列表生成
list = [{'bikes': 20, 'pants': 30, 'watches': 35}, {'watches': 10, 'glasses': 50, 'bikes': 15, 'pants':5}]
df = pd.DataFrame(list)
+列:所有的key
+行:每个字典对应一行,但没有行标签,自动生成数字标签(数据就是字典key对应的值)
嵌套字典的列表用嵌套字典的元组生成
嵌套字典的元组- 用ndarray创建
a=np.array([[1,2,3],[4,5,6],[7,8,9]])
df1=pd.DataFrame(a,index=['row0','row1','row2'],columns=list('ABC'))
- 其余
DataFrame.from_dict
接收字典组成的字典或数组序列字典,并生成 DataFrame
DataFrame.from_records
构建器支持元组列表或结构数据类型(dtype)的多维数组
- 查/改/增/删
属性
.index
.columns
.shape
(行, 列)
.ndim
秩
.size
行*列==元素
.values
数据data(Series.values或DataFrame.values)
查
- 访问 (切片操作适用)
df[Column][Row/Index]
df.loc[:, [columns]]
标签索引,选择列
df.iloc[2,:]
数值索引,查询第二行
df.at[row, column]
快速定位DataFrame的元素
df.iat[x,x]
数值索引,快速定位
.ix[]
先用loc的方式来索引,索引失败就转成iloc(将被剔除,尽量不要使用)
- 布尔(逻辑判断)
indices = np.where(np.isnan(a))
获取索引值
indices = np.where(pd.isnull(a))
两者等价
np.where(np.isnan(df))
返回tuple 第一个ndarray表示行的数值索引,第二个ndarray表示列的数值索引
numpy.take(a, indices, axis=None, out=None, mode='raise')
提取指定索引位置的数据,并以一维数组或者矩阵返回(主要取决axis)
根据indices访问数据
df.loc[(df['C']>2) & (df['D']<10) ]
df.loc[df['C'].isin([3,5,6])]
df['D'] = np.where(df.A<3, 1, 0)
如果A<3,D为1;如果A≥3,D为0
- 选取部分表格
pd.DataFrame(df, index = ['glasses', 'bike'], columns = ['Alice'])
- 选取某列含有特殊数值的行
df.loc[[index]]
df[df.Column > 0]
df1[df1['A'].isin([1])]
选取df1中A列包含数字1的行
df1=df1[~df1['A'].isin([1])]
通过~取反,选取不包含数字1的行
df.[df.index.isin(newindex)]
- 选取某行含有特殊数值的列
df[[Columns]]
cols=[x for i,x in enumerate(df2.columns) if df2.iat[0,i]==3]
df2=df2[cols]
改
df.T
转置
- 数据精度设置
pd.set_option('precision', 1)
小数点后一位
- 修改列标签
df.columns = ['a', 'b']
- 修改行标签
.reset_index
df.set_index(Column)
将某列(的值)作为行标签/索引(常把日期/时间列作为行索引)
store_items =store_items.set_index('pants')
df.index = [index + '_5m' for index in df.index]
直接修改:问题默认的index是pandas.indexes.base.Index,这个格式可能会默认index里面数据的长度是确定的,导致加_5m后缀失败
关键:修改index的类型list(df.index) list元素可变
- 万能
df = df.rename(columns={'oldName1': 'newName1', 'oldName2': 'newName2'})
df.reindex(index=[], columns=[])
增
- 添加标签/索引
pd.DataFrame(data, index = ['label 1', 'label 2', 'label 3'])
index = pd.MultiIndex.from_tuples(tuples, names=['first', 'second'])
建立行索引
建立行索引- 添加新的列
df[new_column] = df[old_column1] + df[old_column2]
dataframe.insert(loc,label,data)
- 添加新的行
首先创建新的 Dataframe,然后将其附加到原始 DataFrame 上
pd.DataFrame(new_data, index = ['store 3'])
新行附加到 DataFrame 后,列按照字母顺序排序表格合并
pandas中提供了大量的方法能够轻松对Series,DataFrame和Panel对象进行不同满足逻辑关系的合并操作
df1.join(df2, axis=, join='outer')
pd.merge(df1, df2, on=[keys], suffixes=[], how='inner')
suffixes表示合并后列名的后缀
pd.concat([df1, df2, df3], axis = )
.append()
只有纵向合并(添加新的数据)
注意:两种方式均可
1)pd.func(data1, data2)
2)data1.func(data2)
- 堆叠stack
df.stack()
df.unstack(0)
0表示第一行索引展开成列
删
df2=df2.drop(cols,axis=1)
利用drop方法将含有特定数值的行/列(指定axis)删除
del df[Column]
df.pop(Column)
仅允许我们删除列
- 排序/遍历/统计
排序 @概括篇-排序
遍历(迭代)
items()
(Columns, Series)元组统计
empty()
、any(iterable)
、all()
、bool()
把数据汇总简化为布尔值(empty:验证元素是否为空)
df.head()
df.tail()
df.isnull()
返回一个大小和df一样的布尔型DataFrame,结合.sum()df.isnull().sum().sum()
第一个 sum()返回一个 Pandas.Series
df.count()
df.describe()
df.value_counts()
df.unique()
- 统计学函数
df.mean()
df,median()
df.max()
df.std()
df.corr()
相关系数矩阵
df..cov()
协方差矩阵
df.corrwith()
计算其列或行跟另一个Series或DataFrame之间的相关系数
统计函数- 分组汇总 .groupby()
data.groupby(['Year'])['Salary'].sum()
data.groupby(['Name'])['Salary'].sum()
data.groupby(['Year', 'Department'])['Salary'].sum()
data.groupby(['Year'])['Salary'].mean()
pandas.melt(df, id_vars=None, value_vars=None, var_name=None, value_name='value', col_level=None)
保留指定列,其他列打散:类似汇总统计的逆操作
- 数据透视表
pd.pivot_table(df, values=, index=[], columns=[])
- 特性:时间序列
pd.date_range(, periods=, freq=)
创建时间序列数据,也可以作为后续的行索引index freq='S'秒, 'D'天, 'M'月, 'Q-NOV'季度
df.rolling(N).mean()
计算 N 天期限的滚动均值
pd.Series.resample()
重采样
pd.Series.tz_localize('UTC')
时区
pd.Series.tz_localize('UTC').tz_convert('US/Eastern')
时区转换
pd.Series.to_period()
pd.Series.to_timestamp()
(pd.period_range.asfreq('M', 'end')).asfreq('H', 'start')
说明:+9 表示09:00
- 特性:数据处理相关操作
数学函数
df.sub()
减法数据整理与清洗
- 快速检查NaN
df.isnull().any()
np.nanmean(ndarray, axis=0)
属于Numpy中不包括NaN按axis取平均值(看作没有NaN)- 对NaN值的处理
df.dropna(axis= , inplace=False, how='any')
删除
df.fillna(0)
替换
df.fillna(method = 'ffill', axis=0)
针对行进行前向填充
df.fillna(method = 'backfill', axis=0)
针对行进行后向填充
df.interpolate(method = 'linear', axis)
linear 插值
df.replace(a, b)
.fill_value()
处理缺失值- 数据整理:进入特定分组
pd.cut()
1). 等距划分分组 pd.cut(ndarray, num) num表示划分的组数
2). 设定分组,使得每个数据点归入到相应分组
pd.cut()
pd.melt(df, id_vars=None, value_vars=None, var_name=None, value_name='value', col_level=None)
说明:将目标列“融化”,或合并,或拆解,形成新的特征列(适合单个个体多属性:统一只罗列一个属性)
+df:要处理的数据集。
+id_vars:不需要被转换的列名。
+value_vars:需要转换的列名,如果剩下的列全部都要转换,就不用写了。
+var_name和value_name是自定义设置对应的列名
+col_level :如果列是MultiIndex,则使用此级别
@示例:type1和type2合并成一个类型
#新的列名type_level,相应的值作为新的列type
#要改变的列
type_cols = ['type_1','type_2']
#不改变的列
non_type_cols = pokemon.columns.difference(type_cols)
pkmn_types = pokemon.melt(id_vars = non_type_cols, value_vars = type_cols,
var_name = 'type_level', value_name = 'type').dropna()
pkmn_types.head()
pd.melt() 效果
分类数据
df[Column].astype("category")
df[Column].cat.categories = []
重命名分类名称
df[Column].cat.categories.cat.set_categories([])
在重命名的基础上添加新的类别名称
- 特性:数据IO
ndarray读写效率最高,但最费硬盘空间,比如np.load()
,np.save()
,csv其次。比如pd.Dataframe.to_csv()
,pd.load_csv()
。
txt读写,当然也可以很快,但是需要频繁的split,对格式规范的数据比较麻烦。
至于简单的excel和word,可以用xlrd,xlwt来操作
numpy的速度比dataframe快,其次对于txt或者csv的数据,用map,reduce,filter三个函数,自己写好function往里面套就行,稍微有点麻烦,但最重要的是这样可以并行化,写好的东西可以直接放到map+reduce上跑,尤其是对于数据量比较大的时候。这样的写法另外一个好处是转向pyspark时非常的方便
CSV (comma-separated values)
df.to_csv('data/foo.csv')
pd.read_csv(filepath)
HDF5
df.to_hdf('data/foo.h5', 'df')
pd.read_hdf('data/foo.h5', 'df')
Excel
df.to_excel('data/foo.xlsx', sheet_name='Sheet1')
pd.read_excel('data/foo.xlsx', 'Sheet1',index_col=None, na_values=['NA'])
pickle模块
持久化:将对象以文件的形式存放在磁盘
.to_pickle('student.pickle')
-
特性:广播机制 @概括篇
-
特性:函数应用(作为函数的参数) @概括篇
-
补充:小技巧
0-1变量比例统计
np.sum(df['Column']) /df.shape[0]
四、拓展
- 模块pandas-datareader