[Pandas]基础大全

import pandas as pd

引言

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

一、概括篇

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

Pandas 特点

  • 支持数据类型
    对 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()方法即可把数据软转换为正确的类型
  • 排序/遍历/统计

排序

  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()

  • 广播
    多维(DataFrame)与低维(Series)对象之间的广播机制。
    重点关注输入的 Series:通过 axis 关键字,匹配 index 或 columns 即可调用这些函数

  • 函数应用(作为函数的参数)
    用哪种方法取决于操作的对象是DataFrame 或 Series ,是行或列,还是元素

  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, 标量值)元组

  • 特性:数学运算(参考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的电子表格)

  • 创建

  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([]) 在重命名的基础上添加新的类别名称

  • 特性:数据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



References

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容