本篇内容为整理《利用Python进行数据分析》,博主使用代码为 Python3,部分内容和书本有出入。

在前几篇中我们介绍了 NumPy、pandas、matplotlib 三个库的基本操作,本篇介绍对数据的一些操作。

数据规整化:清理、转换、合并、重塑

数据聚合与分组运算

数据规整化:清理、转换、合并、重塑

合并数据集

pandas.merge:可根据一个或多个键将不同DataFrame中的行链接起来。

pandas.concat:可沿着一条轴将多个对象堆叠到一起。

combine_first:可将重复数据编接在一起,用一个对象中的值填充另一个对象中的缺失值。

数据库风格的 DataFrame 合并

数据集的合并或连接运算:通过一个或多个键将行链接起来。

多对一的合并:

若没有指定用哪个列进行连接,merge会将重叠列名当做键,指定如下:

若两个对象的列名不同,可分别进行指定:

默认情况下,merge做inner连接,结果中的键是交集。外连接求取的是键的并集:

多对多的合并操作:

连接方式只影响出现在结果中的键。

根据多个键进行合并,传入一个由列名组成的列表:

在进行列-列连接时,DataFrame对象中的索引会被丢弃。

suffixes选项:指定附加到左右两个DataFrame对象的重叠列名上的字符串。

索引上的合并

当DataFrame中的连接键位于其索引中时,传入left_index=True、 right_index=True,以说明索引应该被用作连接键:

对于层次化索引的数据:

必须以列表的形式指明用作合并键的列(注意对重复索引值的处理):

使用合并双方的索引:

DataFrame的 join 实例方法:

更方便的实现按索引合并,不管有没有重叠的列。在连接键上作左连接。

支持参数DataFrame的索引跟调用者DataFrame的某个列之间的连接:

对于简单的索引合并,可以向join传入一组DataFrame(concat 函数也是这个功能):

轴向连接

数据合并运算:

连接(concatenation)

绑定(binding)

堆叠(stacking)

NumPy有一个用于合并原始NumPy数组的concatenation函数:

pandas的concat函数:

默认情况下,concat在 axis=0 上工作,产生一个新Series。传入 axis=1,产生一个DataFrame:

这种情况下,另外一条轴上没有重叠,传入 join = 'inner' 得到它们的交集:

使用 key 参数,在连接轴上创建一个层次化索引:

沿着 axis=1 对Series进行合并,keys 就会成为DataFrame的列头:

对DataFrame对象也是如此:

传入一个字典,则字典的键会被当做keys选项的值:

用于管理层次化索引创建方式的参数:

跟当前分析工作无关的DataFrame行索引:

传入 ignore_index = True:

合并重叠数据

关于有索引全部或部分重叠的两个数据集。

NumPy的where函数,用于表达一种矢量化的if-else:

Series的combine_first方法,实现与上面一样的功能,并会进行数据对齐:

对于DataFrame 一样:

可以看作用参数对象中的数据为调用者对象的缺失数据“打补丁”。

重塑和轴向旋转

用于重新排列表格型数据的基础运算:重塑(reshape)或轴向旋转(pivot)。

重塑层次化索引

stark:将数据的列“旋转”为行

unstark:将数据的行“旋转”为列

用stack方法将行转为列,得到一个Series:

对层次化索引的Series,可以用unstack将其重新排为一个DataFrame:

默认情况下,unstack操作最内层。

传入分层级别的编号或名称可对其他级别进行unstack操作:

如果不是所有的级别值都能在各分组找到的话,unstack操作可能会引入缺失数据:

stack默认会滤除缺失数据,因此该运算是可逆的:

对DataFrame进行unstack操作时,作为旋转轴的级别将会成为结果中的最低级别:

将“长格式”旋转为“宽格式”

时间序列数据通常以 “长格式(long)”或“堆叠格式(stacked)”存储在数据库和 CSV 中。

转成DataFrame,用 pivot 方法:

得到的DataFrame带有层次化的列:

假设有两个需要参与重塑的数据列:

pivot其实只是一个快捷方式:用set_index创建层次化索引,再用unstack重塑。

以上是数据的重排,下面是过滤、清理及其他转换工作。

数据转换

移除重复数据

DataFrame中出现的重复行:

DataFrame的duplicated方法返回一个布尔型Series,表示各行是否是重复行,drop_duplicates方法返回一个移除了重复行的DataFrame:

指定部分列进行重复项判断,如只希望根据k1列过滤重复项:

duplicated和drop_duplicates默认保留重复数值里第一次出现的组合,传入keep = last则保留最后一个:

利用函数或映射进行数据转换

根据数组、Series或DataFrame列中的值来实现转换。

编写一个肉类到动物的映射:

Series的map方法:可以接受一个函数或含有映射关系的字典型对象,用于修改对象的数据子集。

也可以传入一个能够完成全部这些工作的函数:

替换值

replace方法 :替换

利用fillna方法填充缺失数据可以看作替换的一种特殊情况。

替换一个值和一次性替换多个值:

对不同的值进行不同的替换:

传入的参数也可以是字典:

重命名轴索引

轴标签有一个map方法:

对函数或映射进行转换,从而得到一个新对象。

将其值赋给index,就可以对DataFrame进行就地修改了:

要创建数据集的转换版,而不是修改原始数据,用rename:

rename结合字典型对象可以实现对部分轴标签的更新:

rename实现了复制DataFrame并对其索引和列标签进行赋值,就地修改某个数据集,传入inplace=True:

离散化和面元划分

为了便于分析,连续数据常常被离散化或拆分为“面元(bin)”。

用pandas的cut函数:

pandas返回的是一个特殊的Categorical对象,它含有一个表示不同分类名称的数组和一个为年龄数据进行标号的属性:

哪边是闭端可以通过right=False进行修改:

设置自己的面元名称:

将labels选项设置为一个列表或数组即可。

如果向cut传入的是面元的数量而不是确切的面元边界,则它会根据数据的最小值和最大值计算等长面元:

将一些均匀分布的数据分成了四组。

qcut函数:根据样本分位数对数据进行面元划分。

由于qcut使用的是样本分位数,可以得到大小基本相等的面元(而 cut 根据数据的分布情况,可能无法使各个面元中含有相同数量的数据点)。

设置自定义的分位数:

在聚合和分组运算时会再次用到cut 和 qcut 这两个离散化函数。

检测和过滤异常值

判断是否存在异常值(outlier ):

找出某列中绝对值大小超过 3 的值:

选出全部含有“超过 3 或 -3 的值”的行:

将值限制在区间 -3 到 3 以内:

np.sign这个ufunc返回的是一个由 1 和 -1 组成的数组,表示原始值的符号。

排列和随机采样

numpy.random.permutation函数:对Series和DataFrame的列排列。

Permutation(5):需要排列的轴的长度。

然后就可以在基于ix的索引操作或take函数中使用该数组了:

选取随机子集(非替换):

用替换的方式产生样本:

计算指标/哑变量

将分类变量(Categorical)转换为“哑变量矩阵(dummy matrix)”或“指标矩阵(indicator matrix)”。

给DataFrame的列加上一个前缀,以便能够跟其他数据进行合并:

用get_dummies的prefix参数。

DataFrame中的某行同属于多个分类的情况,举个例子:

要为每个genre添加指标变量就需要做一些数据规整操作,构建多成员指标变量:

对于很大的数据,这种方式会变得非常慢,需要编写一个能够利用DataFrame内部机制的更低级的函数:

用get_dummies和cut之类的离散化函数。

字符串操作

字符串对象方法

Python 字符串对象的内置方法:

find找不到返回 -1,index找不到引发一个异常

传入空字符串常常用于删除模式:

正则表达式(regex)

提供了一种灵活的在文本中搜索或匹配字符串模式的方式。python 内置的re模块负责对字符串应用正则表达式。

re模块的函数分为三个大类:模式匹配、替换、拆分。

描述一个或多个空白符的regex是 \s+。

调用re.split('\s+', text)时,正则表达式会先被编译,然后再在text上调用其split方法。

可以用re.compile自己编译一个regex,以得到一个可重用的regex对象,如上所示。如果打算对许多字符串应用同一条正则表达式,强烈建议通过这种方法,可以节省大量的 CPU 时间。

得到匹配regex的所有模式:

findall:返回字符串中所有的匹配项。

search:只返回第一个匹配项。

match:只匹配字符串的首部。

sub方法:将匹配到的模式替换为指定字符串,并返回所得到的新字符串。

不仅想找出电子邮件地址,还想将各个地址分为 3 个部分,只需将待分段的模式的各部分用圆括号包起来:

通过groups方法返回一个由模式各段组成的元组。

对于带有分组功能的模式,findall会返回一个元组列表:

sub还能通过诸如\1, \2之类的特殊符号访问各匹配项中的分组:

为各个匹配分组加上一个名称,由这种正则表达式所产生的匹配对象可以得到一个简单易用的带有分组名称的字典:

pandas 中矢量化的字符串函数

通过data.map,所有字符串和正则表达式方法都能被应用于各个值,但如存在NA就会报错,为了解决这个问题,Series有一些能够跳过NA值的字符串操作方法,通过Series的str属性即可访问这些方法:

也可以用正则表达式:

实现矢量化的元素获取操作,对str.get/str属性上使用索引:

对字符串进行子串截取:

数据聚合与分组运算

对数据集进行分组并对各组应用一个函数。

在将数据集准备好之后,通常的任务就是计算分组统计或生成透视表。pandas提供了一个灵活高效的gruopby功能,对数据集进行切片、切块、摘要等操作。

用 python 和pandas强大的表达能力可以执行复杂的多的分组运算:利用任何可以接受pandas对象或NumPy数组的函数。

GroupBy技术

分组运算:split(拆分)--apply(应用)--combine(合并)。

分组键的形式:

列表或数组,其长度与待分组的轴一样。

表示DataFrame某个列名的值。

字典或Series,给出待分组轴上的值与分组名之间的对应关系。

函数,用于处理轴索引或索引中的各个标签。

访问data1,并根据key1调用groupby。

变量grouped是一个GroupBy对象,它实际上还没有进行任何计算,只是含有一些有关分组键df['key1']的中间数据。

例如,调用GroupBy的mean方法来计算分组平均值:

Series根据分组键进行了聚合,产生了一个新的Series,其索引为key1列中的唯一值。

通过两个键对数据进行了分组后,得到的Series具有一个层次化索引:

分组键可以是任何长度适当的数组:

将列名用作分组键:

GroupBy的size方法返回一个含有分组大小的Series:

对分组进行迭代

GroupBy对象支持迭代,可以产生一组二元元组(由分组名和数据块组成)。

对于多重键,元组的第一个元素将会是由键值组成的元组。

对数据片段进行操作,如将这些数据片段做成一个字典:

groupby默认在axis=0上进行分组,通过设置可以在其它任何轴上进行分组,如可以根据dtype对列进行分组:

选取一个或一组列

对于由DataFrame产生的GroupBy对象,用一个或一组(单个字符串或字符串数组)列名对其进行索引,就能实现选取部分列进行聚合的目的:

例如,对部分列进行聚合:计算data2列的平均值并以DataFrame形式得到结果:

返回一个已分组的DataFrame(传入的是列表或数组)或Series(传入的是标量形式的单个列名):

通过字典或 Series 进行分组

除数组以外,分组信息还可以其他形式存在

根据分组计算列的sum:

将mapping这个字典传给groupby即可。

用Series作为分组键:

这里Series可以被看做一个固定大小的映射。pandas会检查Series以确保其索引根分组轴是对齐的。

通过函数进行分组

任何被当做分组键的函数都会在各个索引值上被调用一次,其返回值就会被用作分组名称。

将函数根数组、列表、字典、Series混合使用(任何东西最终都会被转换为数组):

Key_list和人名对应,再在相同长度的对应一列里选min的值。

根据索引级别分组

层次化索引数据集通过level关键字传入级别编号或名称:

数据聚合

可以使用经过优化的GroupBy的方法,还可以使用自己发明的聚合运算,还可以调用分组对象上已经定义好的任何方法,如 quantile可以计算Series或DataFrame列的样本分位数:

GroupBy会高效地对Series进行切片,然后对各片调用piece.quantile(0.9),最后将这些结果组装成最终结果。

使用自己的聚合函数,传入aggregate或agg方法即可:

有些方法如describe也可以用,但严格来讲它们并非聚合运算。

自定义聚合函数比表中的经过优化的函数慢得多,这是因为在构造中间分组数据块时存在非常大的开销(函数调用、数据重排等)。

面向列的多函数应用

根据 'smoker' 和 'size' 对 tips 进行分组:

传入一组函数或函数名,得到的DataFrame的列就会以相应的函数命名:

传入一个由(name, function )元组组成的列表,各元组的第一个元素会被用作DataFrame的列名:

对于DataFrame,定义一组应用于全部列的函数,或不同的列应用不同的函数。

结果的DataFrame拥有层次化的列。相当于分别对列['tip_pct']和列['total_bill']进行聚合,然后用concat将结果组装到一起(列名用作 keys 参数)。

传入带有自定义名称的元组列表:

对不同的列应用不同的函数:向agg传入一个从列名映射到函数的字典

只有将多个函数应用到至少一列时,DataFrame才会拥有层次化的列:

以“无索引”的形式返回聚合数据

向groupby传入as_index=False,禁用功能由唯一的分组键组成索引:

分组级运算和转换

聚合只是分组运算的其中一种,它接受能够将一维数据简化为标量值的函数。

接下来介绍 transform 和 apply 方法,执行更多其他的分组运算。

为一个DataFrame添加一个用于存放各索引分组平均值的列:先聚合再合并。

下面在GroupBy上使用transform方法:

transform会将一个函数应用到各个分组,然后将结果放置到适当的位置上。

从各组中减去平均值:先创建一个距平化函数(demeaning function),然后将其传给transform。

检查demeaned现在的分组平均值是否为 0:

跟aggregate一样,transform也是一个有着严格条件的特殊函数,传入的函数只能产生两种结果,一个可以广播的标量值(如 np.mean) 或一个相同大小的结果数组。

apply:一般性的“拆分-应用-合并”

最一般化的GroupBy方法是apply:apply会将待处理的对象拆分成多个片段,然后对各片段调用传入的函数,最后尝试将各片段组合到一起。

根据分组选出最高的 5 个tip_pct值:编写一个函数,在指定列找出最大值,然后把这个值所在的行选取出来。

对smoker分组并用该分组函数调用apply,得到:

top函数在DataFrame的各个片段上调用,然后结果由pandas.concat组装到一起,并以分组名称进行了标记。

最后结果就有了一个层次化索引,其内层索引值来自原DataFrame。

如果传给apply的函数能够接受其他参数或关键字,可以将这些内容放在函数名后面一并传入:

在GroupBy对象上调用describe:

在GroupBy中,当调用如describe之类的方法时,实际上只是应用了下面两条代码的快捷方式:

除这些基本用法之外,能否充分发挥apply的威力很大程度上取决于你的创造力,传入的哪个函数能做什么全由你说了算,它只需返回一个pandas 对象或标量值即可。

禁止分组键

分组键会跟原始对象的索引共同构成结果对象中的层次化索引,将group_keys=False传入groupby即可禁止该效果:

分位数和桶分析

pandas有一些能根据指定面元或样本分位数将数据拆分成多块的工具(cut 和 qcut),将这些函数跟groupby结合起来,就能非常轻松地实现对数据集的桶或分位数分析了。

桶:bucket

分位数:quantile

“长度相等的桶”指的是“区间大小相等”,“大小相等的桶”指的是“数据点数量相等”。

利用cut将其装入长度相等的桶中:

由cut返回的Factor对象可直接用于groupby,可以对data2做一些统计计算:

要根据样本分位数得到大小相等的桶,使用qcut:

传入labels=False,即可只获取分位数的编号。否则那段还是区间而不是编号:

示例:用特定于分组的值填充缺失值

对于缺失数据的清理工作,有时用dropna将其滤除,有时则希望用一个固定值或由数据集本身所衍生出来的值去填充NA值,用fillna这个工具。

如用平均值去填充NA值:

对不同的分组填充不同的值:将数据分组,并使用apply和一个能够对各数据块调用fillna的函数即可。

用这个分组平均值去填充NA值:

也可以在代码中预定义各组的填充值,由于分组具有一个name 属性:

示例:随机采样和排列

从一个大数据集中随机抽取样本以进行蒙特卡罗模拟(Monte Carlo simulation)或其他分析工作。抽取的方式很多,其中的一些效率会比其他的高很多

一个办法是:选取np.random.permutation(N)的前K个元素,其中N为完整数据的大小,K为期望的样本大小。

构造一副扑克牌:

从整副牌中抽出 5 张:

从每种花色中随机抽取两张牌,由于花色是牌名的最后一个字符,可以据此进行分组,并使用apply:

另一种方法:

示例:分组加权平均数和相关系数

例如对这个数据集利用category计算分组加权平均数:

来自 Yahoo! Finance 的数据集:

计算一个由日收益率(通过百分数变化计算)与 SPX 之间的年度相关系数组成的DataFrame:

计算列于列之间的相关系数:(苹果和微软的年度相关系数)

示例:面向分组的线性回归

还是上个例子,定义下面这个regress函数(利用 statsmodels 库)对各数据块执行普通最小二乘法回归(Ordinary Least Squares, OLS)。

按年计算 AAPL 对 SPX 收益率的线性回归:

透视表和交叉表

透视表(pivot table)

是各种电子表格程序和其他数据分析软件中一种常见的数据汇总工具。它根据一个或多个键对数据进行聚合,并根据行和列上的分组键将数据分配到各个矩形区域中。

在小费数据集中,根据day和smoker计算分组平均数(pivot_table 的默认聚合类型):

只想聚合tip_pct和size,并根据day进行分组:

传入margins=True添加分项小计,将会添加标签为All的行和列,其值对应于单个等级中所有数据的分组统计。

这里All值为平均数。

要使用其他的聚合函数,将其传给aggfunc即可。例如使用count或len得到有关分组大小的交叉表:

存在NA值,就设置一个fill_value:

交叉表(crosstab)

是一种用于计算分组频率的特殊透视表。

用pandas.crosstab函数(pivot_table 也能实现该功能:根据 Nationality 和 Handedness 对这段数据进行汇总):

crosstab的前两个参数可以是数组、Series、数组列表:

示例:2012联邦选举委员会数据库

加载数据

抽取有关赞助人和赞助模式的统计信息。

通过unique,可以获取全部的候选人名单:

利用字典说明党派关系:

通过这个映射以及 Series对象的map方法,可以根据候选人姓名得到一组党派信息:

注意,该数据集既包括赞助也包括退款(负的出资额),为了简化分析过程,限定该数据集只能有正的出资额:

由于 Barack Obama 和 Mitt Romney 是最主要的两名候选人,专门准备了一个子集,只包含针对他们两人的竞选活动的赞助信息:

根据职业和雇主统计赞助信息

首先,根据职业计算出资总额:

这里只列出了前10个,注意到 许多职业都涉及相同的基本工作类型或同一样东西有多种变体,清理一些这样的数据:将一个职业信息映射到另一个。

对雇主信息也进行了同样的处理。

这里利用了dict.get,它允许没有映射关系的职业也能“通过”。

现在,可以通过pivot_table根据党派和职业对数据进行聚合,然后过滤掉总出资额不足 200 万美元对数据:

做成柱状图:

对 Obama 和 Romney 总出资额最高的职业和企业:先对候选人进行分组,然后求取最大值:

对出资额分组

利用cut函数根据出资额的大小将数据离散化到多个面元中:

根据候选人姓名以及面元标签对数据进行分组:

对出资额求和并在面元内规格化,以便图形化显示两位候选人各种赞助额度的比例:

根据州统计赞助信息

首先,根据候选人和州对数据进行聚合:

对各行除以总赞助额,就得到各候选人在各州的总赞助额比例:

不足之处,欢迎指正。

类的应用python平均分_【数据科学系统学习】Python # 数据分析基本操作[四] 数据规整化和数据聚合与分组运算...相关推荐

  1. 负基础学python编程_【数据科学系统学习】Python # 编程基础[二]

    在上一篇中我们讲到了函数,如果你想在所编写的别的程序中重用一些函数的话,应该怎么办?正如你可能想象到的那样,答案是模块(Modules).我们这一篇就从模块说起. 模块 为了编写可维护的代码,我们把很 ...

  2. 零基础学python 视频_零基础入门学习PYTHON(第2版)(微课视频版)

    小甲鱼畅销图书重磅升级,针对Python 3.7,通过生动的实例,让读者在实践中理解概念,在轻松.愉快中学会Python! 本书提倡理解为主,应用为王.因此,只要有可能,小甲鱼(注:作者)都会通过生动 ...

  3. python工程师_我作为石油工程师学习python的旅程

    python工程师 To be called literate in the 2020s there is a good chance you must know how to code. It ma ...

  4. python倒背如流_如何能高效率学习python?

    Python教程领到手,学习不用愁!领 学习编程,有兴趣最好,小时候就开始捣鼓电脑.知识兔上有大量编程视频教程课程,都是精品课程,1080P超高清画质教学视频,精品之精品,找一套优秀Python课程教 ...

  5. 如何快速学好python语言_如何快速的学习Python语言

    本文主要向大家介绍了如何快速的学习Python语言,通过具体的内容向大家展示,希望对大家学习Python语言有所帮助. 基于自己的学习方法来分享,请客观的看待我提到的几点意见,谢谢. 文末有我自己在g ...

  6. python学习方法_十二种学习Python的方法

    python学习方法 Python是地球上最流行的编程语言之一. 它被世界各地的开发商和制造商所接受. 大多数Linux和MacOS计算机都预装了Python版本,现在,即使是少数Windows计算机 ...

  7. 如何零基础学习python语言_零基础如何学习Python编程

    Python是一门简单优雅的计算机程序设计语言,相比于C语言.Java语言,Python编程具有以下特点: 1. Python语法简单,代码可读性高,容易入门: 2. Python代码具有一定的规范性 ...

  8. 少儿python教学_如何教少儿学习Python编程

    如何给少儿讲编程? 1.首先给少儿讲编程一定要简单,通俗易懂. 因为少儿接触的事务比较少,你要用形象的少儿可以接受的方式让他们理解. 2.讲编程的速度一定要慢. 因为少儿的接受能力相对较弱一些,所以要 ...

  9. 英语不好能学会python吗_英语不好可以学习python编程吗?老男孩python入门

    随着社会的发展以及进步,互联网行业变得更加受关注,现在编程人员市场上需求量增高,越来越多的人都想要学习编程,尤其是python,虽然语法清晰.简单易学,但是依然有部分人因为自己英文不好,担心学习不好, ...

最新文章

  1. LVS负载均衡群集的了解与基本配置(一)
  2. Why is OFDMA a Magical Feature in the 802.11ax Standard?
  3. 搜狐2012.9.15校园招聘会笔试题
  4. AgileEAS.NET之ORM访问器
  5. 计算机重启是什么原因,电脑自动重启,该怎么办,到底是什么原因,我来详细说明?...
  6. HDU 3729【二分匹配】
  7. MongoDB操作文件
  8. 微信公众号获得城市及街道位置信息
  9. matlab竞赛论文模板,数学建模竞赛论文模板.doc
  10. 基于杂化材料银-氨基硅烷氧化石墨烯的化学战剂的电化学传感
  11. pdf epub reader 比较
  12. spring-data-redis 实现用户登录次数限制以及冻结时间重试机制
  13. python 导数 vector_Python。Scipy数值导数
  14. GloVe 词向量模型
  15. Content-Disposition:attachment没有触发浏览器下载弹框
  16. 解读SM, SP和Warp
  17. 学习笔记 | 面对海量数据,为什么无法设计出完美的分布式缓存体系?
  18. Hadoop与workflow入门
  19. Ubuntu18.04美化
  20. Java 1089 狼人杀

热门文章

  1. 谷歌有情怀!谷歌开放大规模音频数据集 AudioSet
  2. 神经网络用作分类器(附代码matlab)
  3. python语言的官方网站-web2py
  4. 哪个服务器支持高并发,IIS Web服务器支持高并发设置方法详解
  5. ajax 返回数组某个属性值,jQuery Ajax向某个页面传值并取得返回的数组
  6. 回溯 皇后 算法笔记_什么叫回溯算法,一看就会,一写就废
  7. 对‘pthread_create’未定义的引用_全球两大引文数据库,都在悄悄少算引用次数...
  8. PowerDesigner设置code和name不联动的方法
  9. laravel5.5路由使用name的好处
  10. caffe android lib