TranslateProject/translated/tech/20160615 Excel Filter and Edit - Demonstrated in Pandas.md
Markgolzh 5b9e93fdae 翻译完成-byzky001
翻译完成
2016-09-02 09:50:30 +08:00

16 KiB
Raw Blame History

Excel “过滤和编辑” - Pandas中的示范操作

介绍

我听许多人说我之前的关于pandas处理一般的Excel任务的文章对于帮助新的pandas用户将Excel任务转化成对应的pandas代码是有用的。这边文章将会保持那个传统通过介绍不同的pandas使用Excel的过滤功能作为一个模型进行索引的例子来理解这样的处理。

大多数pandas的新手首先学到的东西就是基本的数据过滤。即使在过去的时间中使用pandas工作持续数月我最近意识到我没有在我每天的工作中使用的pandas过滤的方法还有另外一个好处。也就是说你可以在一个给定的列上过滤但更新另一组列通过使用一个简化的pandas的语法。这和我所说的Excel中的“过滤和编辑”很像。

这篇文章将会介绍一些过滤一个pandas数据帧同时更新各种标准的例子。同时我将解释关于panda的索引和如何使用索引功能例如 .loc , .ix和 .iloc来简单快速的更新一个基于简单或者是复杂标准的数据子集。

Excel: “过滤与编辑”

在数据透视表以外在EXCEL工具的顶部是一过滤器。这个简单的工具允许用户通过不同的数据文本与格式标准去快速过滤与排序数据。这里是由几个不同的条件过滤数据产生的样本数据的基本截图

该过滤过程是直观的,即使是最新手的用户,也很容易掌握。我也注意到,人们将使用此功能来选择行的数据,然后根据行的标准更新额外的列。下面的例子显示了我所描述的情形:

在这个例子中我过滤了Account Number, SKU和Unit Price的数据。接着我手工增加了Commission_Rate这列并且在每个单元格中输入0.01。这种方法的好处是可以很容易理解和管理有联系的复杂数据而不用写长Excel公式或者进入VBA。这种方法的缺点是它是不可重复的同时对于从外面入门的人了解哪些标准被用于任何过滤器可能是困难的。

例如假设你看相关的截图如果不看每一列数据没有明显的方法去知道什么被过滤了。幸运的是我们可以在pandas中完成相似操作。不奇怪的是在pandas中使用简单干净的代码来执行“过滤和编辑”模式是简单的。

布尔检索

现在我想通过pandas中一些布尔索引的细节来使你对这个问题有点感觉。 如果你想要去理解pandas的在大部分广泛的索引和数据选择这是一个重要的概念去理解。这种想法可能看起来有点复杂对新的pandas用户可能对经验丰富的用户来说太基础但我认为重要的是要花一些时间了解它。如果你掌握了这一概念用pandas进行数据工作的基本过程将更简单。

pandas支持索引(或者选择数据)通过使用标签,基于数字的位置或者一个布尔值的队列(True/False)。使用一个布尔值的列表来选择一个行被称为布尔索引,将是本文其余部分的重点。

我发现我的pandas的工作流程往往侧重于使用布尔值的列表选择我的数据。换句话说当我创建了pandas数据帧我倾向于保持默认的索引在数据框架。因此索引本身并不具有真正意义同时也不是简单的选择数据。

关键点 pandas中布尔索引是一个几个选择行的数据的强大的和有用的方法。

让我们看一些例子数据框架帮助澄清布尔指标在pandas中做的是什么。

首先我们将创建一个非常小的数据帧仅仅从一个Python的列表获得并使用它来展示布尔检索是如何工作的。

import pandas as pd
sales = [('account', ['Jones LLC', 'Alpha Co', 'Blue Inc', 'Mega Corp']),
         ('Total Sales', [150, 200, 75, 300]),
         ('Country', ['US', 'UK', 'US', 'US'])]
df = pd.DataFrame.from_items(sales)

|account |Total Sales |Country :--|:-- |:-- |: 0 |Jones LLC |150 |US 1 |Alpha Co |200 |UK 2 |Blue Inc |75 |US 3 |Mega Corp |300 |US

注意值0-3是怎么样会自动分配给行这些都是指数在这个数据集它们不是特别有意义的但对pandas是有用的重要的是要了解如下其他没有描述的使用情况下。

当我们引用布尔索引时,我们只是说,我们可以通过一个真实或错误的值的列表表示我们要查看的每一行。

在这种情况下如果我们想查看Jones有限责任公司Blue公司和Mega公司的数据我们可以看到True False名单会看起来像这样

indices = [True, False, True, True]

它应该是毫不奇怪你可以通过把这个列表传入你的数据你就看到它只会显示帧中我们的值是True的行

df[indices]
account Total Sales Country
0 Jones LLC 150 US
2 Blue Inc 75 US
3 Mega Corp 300 US

这里是一个刚刚发生的操作图像:

手工的列表创建索引是工作的。但是显然对任何一个超过微不足道的数据集不是可扩展或是很有用的。幸运的是pandas就可以用一个简单的查询语言有熟悉用Python创建这些布尔指标应该很容易或任何语言

例如让我们看看来自美国的所有销售线。如果我们执行的Python表达式基于Country列

df.Country == 'US'
0     True
1    False
2     True
3     True
Name: Country, dtype: bool

这个例子显示了pandas如何将你的Python的传统逻辑把它应用到一个数据帧并返回一个布尔值列表。那么这个布尔值的列表可以通过帧的数据获取相应的行。

在真正的代码中,你不需要做这两个步骤。简洁的做这事的方法典型的看上去如下:

df[df["Country"] == 'US']
account Total Sales Country
0 Jones LLC 150 US
2 Blue Inc 75 US
3 Mega Corp 300 US

虽然这个概念很简单你可以编写非常复杂的逻辑使用Python的威力过滤数据。

关键点 在这个例子中, df[df.Country == 'US'] 等价于 df[df["Country"] == 'US'] . 标记法是简洁的但是在你列名有空格时不会工作。

选择需要的列

现在我们已经找到了如何选择行的数据我们如何控制哪些列显示在上面的例子中没有明显的方法去做。Pandas能使用三种基于位置的索引支持这个用法.loc , iloc , 和 .ix . 。这些功能也允许我们选择除了我们所看到的行挑选列。

在这里有很大的困惑关于什么时候选择使用 .loc , iloc , 或者是 .ix。 快速总结的区别是:

  • .loc 用于标签索引
  • .iloc 用于基于整数的位置
  • .ix 是一个将尝试使用标签的快捷方式 (like .loc ) 但失败后将回落到基于位置的整数 (like .iloc )

因此问题是我该使用哪个?我必须坦诚我有的时候也会被这些搞混.我发现我最常使用 .loc 。主要是因为我的数据不适合于有意义的基于位置的索引(换句话说,我很少发现自己需要使用 .iloc ) 所以我坚持使用 .loc。

公平讲,每一个方法都有自己的位置,在许多情况下都是有用的。特别的一个场景是当处理多指标数据帧时。我不会在这篇文章中讨论那个话题-也许在未来的博文会说。

现在我们已经涵盖了这样一个话题,让我们来展示如何筛选一行的值的数据帧,具体选择要显示的列。

继续我们的例子,如果我们只是想显示对应于我们的指数的帐户名称,该怎么做?使用.loc很简单

df.loc[[True, True, False, True], "account"]
1     Alpha Co
2     Blue Inc
3    Mega Corp
Name: account, dtype: object

如果你想看到多个列,只需通过一个列表:

df.loc[[True, True, False, True], ["account", "Country"]]
account Country
0 Jones LLC US
1 Alpha Co UK
3 Mega Corp US

真正的威力是当你在你的数据上创建更复杂的查询。在这种情况下,让我们展示所有的帐户名称和销售> 200的国家

df.loc[df["Total Sales"] > 200, ["account", "Country"]]

|account| Country :--|:--|:-- 3 |Mega Corp| US

这个过程可以被认为有点相当于我们上面讨论过的Excel的过滤器。你已经加入了额外的好处你也可以限制你检索的列数而不仅仅是行。

编辑列

所有这些都是好的背景,但当你使用一个类似的方法来更新一个或多个列的基础上的行选择这个过程真的是闪光的。

一个简单的例子,让我们增加一个佣金率列到我们的数据:

df["rate"] = 0.02
account Total Sales Country rate
0 Jones LLC 150 US 0.02
1 Alpha Co 200 UK 0.02
2 Blue Inc 75 US 0.02
3 Mega Corp 300 US 0.02

让我们说如果你卖了超过100你的利率是5%。基本的过程是设置一个布尔索引来选择列,然后将该值赋给利率列:

df.loc[df["Total Sales"] > 100, ["rate"]] = .05
account Total Sales Country rate
0 Jones LLC 150 US 0.05
1 Alpha Co 200 UK 0.05
2 Blue Inc 75 US 0.02
3 Mega Corp 300 US 0.05

希望如果你看过这篇文章这将是有意义的它会帮助你理解这个语法是如何工作的。现在你有了“过滤和编辑”方法的基本原理。最后一节将更详细的在Excel和pandas显示这个过程。

将这些合并在一起

对于最后的例子,我们将创建一个简单的佣金计算器,使用以下规则:

  • 所有的佣金计算在交易水平
  • 所有销售的基础佣金为2%
  • 所有衬衫都将获得2.5%的佣金
  • 一个特殊的程序正在进行中,在一个交易中销售的数额>10带得到4%的佣金
  • 所有在一个单一的交易鞋类销售> 1000美元有一个特别的奖金为250美元加上一个4.5%的的佣金

为了在Excel做到这一点使用的过滤器和编辑方法

  • 添加一个2%的佣金列
  • 添加一个0美元的奖金列
  • 衬衫上的过滤器并将vale改为2.5%
  • 清楚过滤器
  • 带和数量的过滤器>10和将值更改为4%
  • 清除过滤器
  • 鞋类过滤器> 1000美元并增加佣金和奖金价值分别为4.5%和250美元

我不会显示每一步的屏幕快照,但这里是最后一个过滤器的屏幕快照:

这种方法很简单可以在很好的操作但它不具备很好的可重复性也不能审核。当然还有其他的方法如在Excel公式或VBA实现这些。然而这种过滤器和编辑的方法是常见的是说明性的pandas的逻辑。

现在, 让我们在pandas中运行这个例子.

首先,读入Excel 文件同时加入默认值2%的利息一列:

import pandas as pd
df = pd.read_excel("https://github.com/chris1610/pbpython/blob/master/data/sample-sales-reps.xlsx?raw=true")
df["commission"] = .02
df.head()
account number customer name sales rep sku category quantity unit price ext price date commission
0 680916 Mueller and Sons Loring Predovic GP-14407 Belt 19 88.49 1681.31 2015-11-17 05:58:34 0.02
1 680916 Mueller and Sons Loring Predovic FI-01804 Shirt 3 78.07 234.21 2016-02-13 04:04:11 0.02
2 530925 Purdy and Sons Teagan OKeefe EO-54210 Shirt 19 30.21 573.99 2015-08-11 12:44:38 0.02
3 14406 Harber, Lubowitz and Fahey Esequiel Schinner NZ-99565 Shirt 12 90.29 1083.48 2016-01-23 02:15:50 0.02
4 398620 Brekke Ltd Esequiel Schinner NZ-99565 Shirt 5 72.64 363.20 2015-08-10 07:16:03 0.02

下一个规则是所有衬衫获得2.5%和带销售>10得到一个4%的利息:

df.loc[df["category"] == "Shirt", ["commission"]] = .025
df.loc[(df["category"] == "Belt") & (df["quantity"] >= 10), ["commission"]] = .04
df.head()

| account number |customer name |sales rep| sku |category |quantity| unit price| ext price |date |commission :--|:--|:--|:--|:--|:--|:--|:--|:--|:--|:--|:-- 0 |680916| Mueller and Sons| Loring Predovic| GP-14407| Belt| 19 |88.49| 1681.31 |2015-11-17 05:58:34| 0.040 1 |680916| Mueller and Sons| Loring Predovic| FI-01804| Shirt |3 |78.07 |234.21| 2016-02-13 04:04:11 |0.025 2 |530925 |Purdy and Sons |Teagan OKeefe| EO-54210 |Shirt| 19 |30.21 |573.99 |2015-08-11 12:44:38| 0.025 3 |14406| Harber, Lubowitz and Fahey| Esequiel Schinner| NZ-99565| Shirt| 12| 90.29| 1083.48| 2016-01-23 02:15:50 |0.025 4 |398620| Brekke Ltd| Esequiel Schinner| NZ-99565| Shirt| 5 |72.64 |363.20| 2015-08-10 07:16:03 |0.025

最后的佣金规则是加上特别的奖金:

df["bonus"] = 0
df.loc[(df["category"] == "Shoes") & (df["ext price"] >= 1000 ), ["bonus", "commission"]] = 250, 0.045

# Display a sample of rows that show this bonus
df.ix[3:7]

| account number| customer name |sales rep| sku |category| quantity| unit price| ext price| date| commission| bonus :--|:--|:--|:--|:--|:--|:--|:--|:--|:--|:--|:--|:-- 3| 14406| Harber, Lubowitz and Fahey| Esequiel Schinner| NZ-99565| Shirt |12 |90.29| 1083.48 |2016-01-23 02:15:50 |0.025 |0 4| 398620| Brekke Ltd| Esequiel Schinner |NZ-99565| Shirt| 5| 72.64| 363.20| 2015-08-10 07:16:03| 0.025| 0 5| 282122| Connelly, Abshire and Von Beth| Skiles| GJ-90272| Shoes| 20| 96.62| 1932.40 |2016-03-17 10:19:05 |0.045 |250 6 |398620 |Brekke Ltd| Esequiel Schinner |DU-87462 |Shirt| 10| 67.64 |676.40| 2015-11-25 22:05:36| 0.025| 0 7| 218667| Jaskolski-OHara| Trish Deckow| DU-87462| Shirt |11| 91.86| 1010.46 |2016-04-24 15:05:58| 0.025| 0

为了做好佣金的计算:

#  Calculate the compensation for each row
df["comp"] = df["commission"] * df["ext price"] + df["bonus"]

# Summarize and round the results by sales rep
df.groupby(["sales rep"])["comp"].sum().round(2)
sales rep
Ansley Cummings       2169.76
Beth Skiles           3028.60
Esequiel Schinner    10451.21
Loring Predovic      10108.60
Shannen Hudson        5275.66
Teagan O'Keefe        7989.52
Trish Deckow          5807.74
Name: comp, dtype: float64

如果你有兴趣,一个例子手册被托管在github.

总结

感谢阅读文章。 我发现在学习如何使用pandas的新用户的最大的挑战之一是如何找出如何使用他们的基于Excel的知识以建立一个等效的pandas为基础的解决方案。在许多情况下,andas的解决方案将是更健壮更快更容易审计和更强大的。然而学习曲线可以花一些时间。我希望这个例子显示了如何解决一个问题使用的是电子表格的过滤工具将是一个有用的指南为那些刚刚在这个pandas开始的旅程的。祝你好运!


via: http://pbpython.com/excel-filter-edit.html

作者:Chris Moffitt 译者:zky001 校对:校对者ID

本文由 LCTT 原创翻译,Linux中国 荣誉推出