编写惯用的pandas代码的5个技巧

本文概述

  • 加载和浏览数据
  • 1.索引
  • 2.方法链接
  • 3.内存优化
  • 4. GroupBy
  • 5.可视化
  • 超越
Pandas是供Python数据科学家使用的事实上的工具箱, 它可以简化数据分析:例如, 在开始分析之前, 可以使用它来收集, 浏览和格式化数据。pandas通过其众多的I / O和便捷的数据操作功能使这些步骤变得轻而易举。而且, 正如你将在本教程的后面部分了解的那样, 它还具有一些可视化功能(通过使用matplotlib)。
尽管Pandas数据结构非常强大和灵活, 但它们也具有一些复杂性, 这会使你的分析变得更加困难而不是容易, 特别是对于初学者而言。在本教程中, 你将集中精力学习更多有关如何避免麻烦和编写更多惯用的Pandas代码的信息。除了学习如何加载, 浏览和清理数据之外, 你还将了解以下五个主题的更多信息:
  1. 借助loc和iloc进行索引, 以及使用query()查询你的DataFrame的简短介绍;
  2. 方法链接, 借助pipe()函数替代了嵌套函数;
  3. 内存优化, 可以通过设置数据类型来实现;
  4. 以天真的和pandas的方式进行分组操作;和
  5. 使用Matplotlib和Seaborn可视化你的DataFrame。
当然, 本教程绝非详尽无遗。 Pandas软件包非常丰富, 毫无疑问, 还有其他一些方法可以改进Pandas代码, 使它变得更加惯用。
让我们不再等待, 开始吧!
加载和浏览数据 与往常一样, 数据分析从加载和浏览数据开始。本部分只是一个热身, 你将在其中使用read_csv()函数加载世界大学排名, 之后, 你已经可以使用head()和describe()函数快速浏览数据。如果你对Pandas的完整介绍感兴趣, 请考虑从Pandas Foundations开始参加srcmini的三部分Pandas课程。
如果你已经了解了所有这些内容, 则可以跳过本节, 并了解如何以更加惯用的方式对Pandas进行索引。
导入包
首先, 让我们导入用于数据科学的常规Python程序包。你可能已经猜到了, pandas就是其中之一。
# If you're working with a notebook, don't forget to use Matplotlib magic! %matplotlib inline# Import `pandas` under the alias `pd` import pandas as pd# Import `seaborn` under the alias `sns` import seaborn as sns# Set the Seaborn theme if desired sns.set_style('darkgrid')

此外, 你还可以使用水印包:这是一个不错的工具, 可让你的笔记本更具再现性。与同事合作时, 可重复的工作非常重要。你未来的自我也会为此感谢你!你可以在此处阅读有关可再生数据科学的更多信息。
数据
为了开始本教程, 你还需要获取一些” 真实” 数据。对于本教程, 你将使用Kaggle的数据集。如果你不熟悉Kaggle, 它是最大的数据科学和机器学习社区之一。此外, 一旦你了解了基础知识, 它也是一个学习更多有关数据科学的好地方。
你将使用的数据集是世界大学排名。
如上所述, Pandas有许多方便的方法可以从不同的数据源读取数据(你可以在此处了解更多信息)。由于数据为CSV格式, 因此我们将使用.read_csv方法。但是在开始之前, 你需要从Kaggle下载数据(或者, 如果你不想创建帐户, 则可以从data文件夹下的代码存储库获取数据)。
提取数据后, 应该有一个包含不同csv文件的文件夹数据。
接下来, 你将使用《泰晤士高等教育》世界大学排名排名(以下简称” 时间” )和世界大学学术排名(简称” 上海” )的排名数据。数据文件夹CWUR中还有一个第三级系统, 但鲜为人知, 因此你现在可以放心忽略它。
# Import Times Higher Education World University Rankings data times_df = pd.read_csv('data/timesData.csv', thousands=", ")# Import Academic Ranking of World Universities data shanghai_df = pd.read_csv('data/shanghaiData.csv')

快速检查数据
正如你在srcmini的探索性数据分析教程中所了解的那样, Pandas提供了一些方法来快速检查DataFrame, 即.head()检查前n行(默认情况下n为5)和.describe()以获取快速的统计摘要。 。
通过执行以下代码行来刷新这些功能。数据已经为你加载在times_df和shanghai_df下:
现在, 你已经加载了数据, 你可以开始考虑如何以惯用的方式使用Pandas处理数据了!
1.索引 首先, 编写更多惯用的Pandas代码意味着利用索引的功能。索引意味着你可以从DataFrame中选择子集。
当你刚开始使用Pandas时, 可能需要一些时间来习惯索引的工作方式。实际上, 如果你以前使用过(Python)列表, 则可能已经熟悉使用方括号[]和冒号:来选择元素。此方法适用于DataFrames。
此外, 还有其他两种更惯用的方式来选择子集DataFrame。这两种方法分别是iloc和loc:
  • loc是基于标签的。这意味着, 如果你编写loc [2], 则正在查找具有标为2的索引的DataFrame的值。
  • iloc是基于位置的。这意味着, 如果你编写iloc [2], 则正在查找索引2处的DataFrame值。
在下面的srcmini Light块中尝试此操作, 方法是在IPython控制台中键入times_df.loc [2]和times_df.iloc [2]来查看区别。接下来, 尝试在loc, iloc和传统方括号的帮助下解决以下练习!
当然, 你的探索不仅可以简单地子集化或从数据的行和列中进行选择, 而且可以走得更远。当你将loc和iloc与例如布尔数组结合使用时, 事情会变得非常有趣。
你会看到, 这超出了根据列或索引选择数据的范围;有点像查询你的数据!
loc和iloc可以很好地索引数据, 但是当你开始使用两组彼此之间的方括号时要小心!pandas可以返回视图的副本, 在这种情况下, 你将不会知道自己还在做什么!因此, 如果结合使用loc或iloc的两组方括号, 请三思。
还请注意, 要查询数据, Pandas还为你提供了query()函数, 你可以使用该函数快速检查数据(自0.13版开始可用)。例如, 你可以编写查询以查看哪些大学的total_score略低于50:
当然, 查询数据还有更多可能性!为什么不尝试提出一些查询, 并在上述srcmini Light块的IPython控制台中对其进行测试?
如果你缺少灵感, 请尝试使用查询来返回排名第一的大学和排名第一的大学。此外, 你可以查询大学的校友人数。
你不知道如何编写查询吗?查看以下一些示例:
shanghai_df.query("national_rank == 1 and world_rank == 1") shanghai_df.query("alumni < 20")

2.方法链接 方法链接是Pandas的典型代表, 但是当你刚开始使用Python数据操作包时, 如何实现它可能并不容易。它基本上是一个对象一个接一个地调用方法。
在本节中, 你将通过使用pipe()创建数据管道来更深入地进行方法链接。
你已经注意到, 数据集完全不同。以下是一些区别:
  • Times数据集有14列, 而上海数据集有11列
  • 时报数据集有2603行, 而上海数据集有4897行
  • 上海的数据集中缺少的一列是大学所在的国家/地区。如果需要, 你稍后将从Times数据集中获取此信息。
因此, 为了使我们同时使用两个DataFrame, 我们将只需要选择公共列。希望这些通用列具有相似的内容。
因此, 公共列为:
  • total_score:用于确定排名的分数。如Kaggle说明页面中所述, 它们包含范围等级(即两个值之间)和相等等级(前面有=符号)
  • university_name:大学名称
  • world_rank:大学排名
  • 年:完成排名的年份
为了连接两个数据, 我们需要先进行一些清理。然后立即应用完整的管道来清理数据:
你可能已经注意到, 本教程中我经常使用.pipe方法。如果你来自R世界, 则可能(以某种方式)熟悉它。
这是一种方便的新Pandas(自0.16.2版本开始)方法, 可让你链接操作并因此不需要中间DataFrame。你的代码更具可读性。
实际上, 如果没有此运算符, 则无需编写df.pipe(f).pipe(g).pipe(h), 而应编写:h(g(f(df)))。一旦嵌套函数的数量增加, 这将变得更难遵循。
要了解有关该主题的更多信息, 我强烈建议阅读以下博客文章。
现在, 两个数据框都已清理完毕, 我们可以将它们串联为一个数据框。另外, 不要忘记清理丢失的数据:
由于total_score列中大约丢失了38%的数据, 因此最好使用.drop方法删除该列。
3.内存优化 使你的Pandas代码更” 惯用” (在这种情况下更等于” 性能” )的第三种方法是优化内存使用。特别是当你开始使用方法链建立数据管道时, 你会发现内存在管道运行速度方面起着重要作用。你会在这里看到更多关于这方面的信息。
对于这个小的数据集, 这可能是过大的了, 但是将某些列转换为特定类型以优化内存使用通常是一个好习惯。首先, 让我们使用.info方法查找为rank_df分配多少内存。
第一行代码的结果告诉我们, 数据占用144 KB。但是, 在检查.info方法的参数时, 会发现存在一个可选参数, 即memory_usage, 默认情况下将其设置为None。将参数memory_usage设置为deep会发生什么?
新的内存占用量为6 -5.6, 比你最初的答案要精确得多。
这里发生了什么?
内存估算的差异源于以下事实:没有打开” deep” 标志, Pandas不会估算对象dtype的内存消耗。这种(Python)数据比其他numpy优化dtype占用更多的空间。这就是为什么建议将对象类型转换为更合适的类型的原因(例如, 在处理分类数据时使用类别)。
我们开始做吧!
def memory_change(input_df, column, dtype): df = input_df.copy() old = round(df[column].memory_usage(deep=True) / 1024, 2) # In KB new = round(df[column].astype(dtype).memory_usage(deep=True) / 1024, 2)# In KB change = round(100 * (old - new) / (old), 2) report = ("The inital memory footprint for {column} is: {old}KB.\n" "The casted {column} now takes: {new}KB.\n" "A change of {change} %.").format(**locals()) return reportprint(memory_change(ranking_df, 'world_rank', 'int16')) print(memory_change(ranking_df, 'university_name', 'category')) print(memory_change(ranking_df, 'name', 'category'))

现在你已经知道, 例如, 将world_rank更改为int16, 将可以更有效地利用你的内存, 是时候实际应用这些更改了。你可以使用astype()函数执行此操作。通过仔细检查你的内存使用情况现在结束:
那好多了。你可以通过将year列强制转换为int32来进一步优化。
4. GroupBy 现在我们有了格式正确的数据集(即处于整理状态), 并且内存占用已优化, 可以开始数据分析了。
现在, 有一些你可能有兴趣回答的问题:
  • 多年来, 每个排名系统给予的前五名大学是什么?
  • 这些排名每年有何不同?
让我们通过使用在上一节中已经看到的更加惯用的pandas指针来解决第一个问题!
开始之前, 请注意” 麻省理工学院(MIT)” 和” 麻省理工学院” 是同一所大学的两条不同记录。因此, 你将名字更改为后者。
请注意, 在这种情况下, 你在本教程前面看到的loc函数特别方便!
为了找到多年来排名前5的大学(通常是n所), 对于每个排名系统, 以下是使用伪代码的方法:
  • 对于每年(在” 年份” 列中)和每个排名系统(在” 名称” 列中):
  • 选择给定年份和给定排名系统的数据子集
  • 选择5所顶尖大学并将其存储在列表中
  • 将结果存储在以(年, 名称)为关键字, 以大学列表(降序)为值的字典中
让我们应用这个。
现在我们有了排名字典, 让我们找出多年来这两种排名方法有多少不同(以百分比为单位):如果所选的排名前5位的大学相同, 即使它们没有排名, 两者也是100%相似的相同。
你已经注意到, 这很乏味。有没有更好, 更惯用的pandas方式?
当然有!首先, 过滤排名数据框架以仅保留每年排名前5的大学和排名方法。还可以通过head()函数检查结果:
现在, 你可以使用正确的DataFrame了, 让我们使用.groupby方法使用上面定义的集合相似度比较两种排名方法。
你将获得与上述相同的结果, 而麻烦却更少。
5.可视化 现在, 你已经对数据集进行了一些初步分析, 现在该是可视化探索数据的时候了。更多惯用的Pandas代码还意味着你可以利用Matplotlib软件包中的Pandas绘图集成功能。因此, 你将立即绘制出精美的地块!
在本节中, 你将返回times_df和shanghai_df数据集, 以使用Matplotlib和Seaborn进行一些基本的可视化。
编写惯用的pandas代码的5个技巧

文章图片
上图立即表明, 校友栏有一些0值。在浏览数据时, definitley需要考虑到这一点:借助数据分析, 你将能够看到这0个值并能够对其进行处理。如果你想进一步了解这一点, 请查看srcmini的数据剖析教程。
或者, 如果你的值在数据集中没有位置, 则可以简单地将它们替换为NaN, 然后??删除所有列的NaN值, 这将使数据绘制更加困难。请注意, 这只是调整数据的一种快速方法, 你可能需要执行更详细的数据分析步骤以确保数据质量得到改善, 因为在下图中, 你仍然看到num_students列的值为0:
编写惯用的pandas代码的5个技巧

文章图片
当然, 你无需局限于Matplotlib即可可视化数据。还有其他可以让你快速可视化数据的库, 例如Seaborn。
Seaborn绘图工具主要用于创建视觉上吸引人的统计图(如官方网站中所述)。实际上, 在Matplotlib 2.0版之前, 创建漂亮的绘图很麻烦(虽然可能)。
pandas与Seaborn的结合还使你可以通过可视化方式快速迭代数据。
让我们探索一些例子!
看看下面的图, 你在其中计算特定国家/地区出现在数据中的次数, 进行前十次观察, 并确保在绘制小图时将计数从最高值到最低值进行排序:
编写惯用的pandas代码的5个技巧

文章图片
然后, 你可以继续绘制这些国家及其平均分数:
编写惯用的pandas代码的5个技巧

文章图片
你的情节也可能变得非常复杂。查看以下对图, 该图旨在更清楚地向你展示数据集中的成对关系:
import numpy as npnp.seterr(invalid='ignore')sns.pairplot(times_df, hue='country')plt.show()

编写惯用的pandas代码的5个技巧

文章图片
同样, 你可以查看FacetGrid和regplot的组合, 这使你对过去5个国家的total_score的演变有一些见解:
编写惯用的pandas代码的5个技巧

文章图片
最后, 当你浏览数据时, 相关图也可能会派上用场。你可以使用Seaborn的heatmap()函数来完成此操作:
编写惯用的pandas代码的5个技巧

文章图片
你可以继续进行这些可视化, 所以也许最好暂时停止:)。
超越 就是这样, 我希望你喜欢学习与Pandas合作的一些中间技术, 更具体地说是如何编写更多惯用的Pandas代码。
【编写惯用的pandas代码的5个技巧】如果你喜欢这篇博客文章, 并且想深入了解Pandas的性能, 我强烈建议你添加以下其他材料:
  • 汤姆·奥格斯珀格的《现代pandas》教程,
  • 斯蒂芬·西蒙斯(Stephen Simmons)的《这只pandas从内而外》的演讲, 以及
  • 如果你想了解更多有关如何使用其他Python工具实现groupby操作的信息, 我强烈建议阅读以下博客文章。

    推荐阅读