Python

[Pandas]基础大全

2020-01-24  本文已影响0人  DDuncan
import pandas as pd

引言

原始的数据有时候是一串文字(过度聚合),有时候是分散在多个位置的分离文件(过于分散)。数据的预处理就是要把原始的数据拆分、组合、标准化,并将异常的数据剔除掉。在这个过程中,字符串的拆分与合并非常重要。python内建函数可以实现简单字符串的拆分与合并(split与format函数)。而re库、pandas库又提供了更加强大的数据预处理手段,能帮助我们运用简单的代码实现复杂的功能。建议在进行数据处理的时候,将数据转换为DataFrame格式,运用pandas库强大的功能库进行处理。

一、概括篇

Panel Data(面板数据),大部分类型的底层数组都是numpy.ndarray
足以处理金融、统计、社会科学、工程等领域里的大多数典型用例
轻松直观地处理带标签数据和关系数据
为行和列设定标签
将不同格式的数据加载到 DataFrame 中
可以将不同的数据集合并到一起
与 NumPy 和 Matplotlib 集成
社区活跃
长远目标:成为最强大、最灵活、可以支持任何语言的开源数据分析工具

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()方法即可把数据软转换为正确的类型

排序

  1. 按索引排序
    Series.sort_index()
    DataFrame.sort_index()
  2. 按值排序
    Series.sort_values()
    DataFrame.sort_values() 参数 by 用于指定按哪列排序(一列或多列数据)
  3. 按索引与值排序
  4. 按多重索引的列排序

遍历(迭代)

Series 迭代时被视为数组;支持字典式的 items()方法, (Index, 标量值)元组
DataFrame 列标签;支持字典式的items()方法,(Columns, Series)元组

统计

pd.Series.value_counts()
pd.DataFrame.value_counts()

  1. 表级函数应用
    通过链式调用函数时,最好使用pipe()方法
  2. 行列级函数应用
    apply()方法可以沿着 DataFrame 的轴应用任何函数,比如,描述性统计方法,该方法支持 axis 参数
  3. 聚合 API
    agg()transform() 快速、简洁地执行多个聚合操作
  4. 元素级函数应用
    并非所有函数都能接受 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 的区别:

  1. 每个元素分配索引标签(label 即index)
  2. 可以存储不同类型的数据

+可变
+带标签的一维数组,可存储整数、浮点数、字符串、Python 对象等类型的数据(轴标签统称为索引)
+类似多维数组:操作与 ndarray 类似,支持大多数 NumPy 函数,还支持索引切片
+类似字典:必须提供索引

  1. 通过list创建
    pd.Series([list])
    pd.Series(data = [30, 6, 'Yes', 'No'], index = ['eggs', 'apples', 'milk', 'bread'])
  2. 特殊:时间序列
    pd.data_range()
    Series 时间序列

属性

.shape
.ndim
.size
.values
.index

  1. 访问
    Series['label/index']
    +.loc 标签索引
    +.iloc 数值索引
  2. 判断
    in

  1. 索引重置与更换
    reindex()
    reindex_like() 用align对齐多个对象
  2. 索引重命名
    .Series.rename() 支持按不同的轴基于映射(字典或 Series)调整标签
  3. 数据平移
    pd.Series().shift(N) 向下平移N行

Series.drop(label, inplace=False) 与 reindex 经常配合使用,该函数用于删除轴上的一组标签

排序 @概括篇-排序

  1. 搜索排序
    Series.searchsorted() 这与numpy.ndarray.searchsorted() 的操作方式类似
  2. 最大值与最小值
    .nsmallest().nlargest() 方法,本方法返回 N 个最大或最小的值

遍历

.items() (Index, 标量值)元组

与单个数字

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)

  1. 用 Series字典或字典生成
    dict = {'key1': pd.Series([]), index = [], 'key2': pd.Series([]), index = []}
    df = pd.DataFrame(dict)
    +列:字典的key
    +行:字典的value,也就是Series的index(Series的Data作为DataFrame的数据)
    没有Series.index时,从0开始计数作为行标签
  2. 用多维数组字典、列表字典生成
    dict = {'key1':[], 'key2': []}
    df = pd.DataFrame(dict)
    +列:字典的key
    +行:对应没有Series.index的情况,从0开始计数作为行标签(列表作为DataFrame的数据)
    多维字典生成DataFrame
    查看各列的数据类型
  3. 用结构多维数组或记录多维数组生成
  4. 用嵌套字典的列表生成
    list = [{'bikes': 20, 'pants': 30, 'watches': 35}, {'watches': 10, 'glasses': 50, 'bikes': 15, 'pants':5}]
    df = pd.DataFrame(list)
    +列:所有的key
    +行:每个字典对应一行,但没有行标签,自动生成数字标签(数据就是字典key对应的值)
    嵌套字典的列表
  5. 用嵌套字典的元组生成


    嵌套字典的元组
  6. 用ndarray创建
    a=np.array([[1,2,3],[4,5,6],[7,8,9]])
    df1=pd.DataFrame(a,index=['row0','row1','row2'],columns=list('ABC'))
  7. 其余
    DataFrame.from_dict 接收字典组成的字典或数组序列字典,并生成 DataFrame
    DataFrame.from_records 构建器支持元组列表或结构数据类型(dtype)的多维数组

属性

.index
.columns
.shape (行, 列)
.ndim
.size 行*列==元素
.values 数据data(Series.values或DataFrame.values)

  1. 访问 (切片操作适用)
    df[Column][Row/Index]
    df.loc[:, [columns]] 标签索引,选择列

df.iloc[2,:] 数值索引,查询第二行
df.at[row, column] 快速定位DataFrame的元素
df.iat[x,x] 数值索引,快速定位
.ix[] 先用loc的方式来索引,索引失败就转成iloc(将被剔除,尽量不要使用)

不同的索引方式
  1. 布尔(逻辑判断)
    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

  2. 选取部分表格
    pd.DataFrame(df, index = ['glasses', 'bike'], columns = ['Alice'])

  3. 选取某列含有特殊数值的行
    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)]

  1. 选取某行含有特殊数值的列
    df[[Columns]]
    cols=[x for i,x in enumerate(df2.columns) if df2.iat[0,i]==3]
    df2=df2[cols]

df.T 转置

  1. 数据精度设置
    pd.set_option('precision', 1) 小数点后一位

  2. 修改列标签
    df.columns = ['a', 'b']

  3. 修改行标签
    .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元素可变

  4. 万能
    df = df.rename(columns={'oldName1': 'newName1', 'oldName2': 'newName2'})
    df.reindex(index=[], columns=[])

  1. 添加标签/索引
    pd.DataFrame(data, index = ['label 1', 'label 2', 'label 3'])
    index = pd.MultiIndex.from_tuples(tuples, names=['first', 'second']) 建立行索引
    建立行索引
  2. 添加新的列
    df[new_column] = df[old_column1] + df[old_column2]
    dataframe.insert(loc,label,data)

  3. 添加新的行
    首先创建新的 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([]) 在重命名的基础上添加新的类别名称

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]

四、拓展


References

上一篇下一篇

猜你喜欢

热点阅读