Introduction

映射允许我们一次转换 DataFrame 或 Series 中整列的数据,每次转换一个值。然而,我们通常希望对数据进行分组,然后针对数据所在的组执行特定操作。

正如您将了解到的,我们使用 groupby() 操作来实现这一点。我们还将介绍一些其他主题,例如更复杂的 DataFrame 索引方法以及如何对数据进行排序。

要开始此主题的练习,请点击此处

Groupwise analysis

到目前为止,我们经常使用的一个函数是“value_counts()”函数。我们可以通过执行以下操作来复制“value_counts()”的功能:

import pandas as pd
reviews = pd.read_csv("../input/wine-reviews/winemag-data-130k-v2.csv", index_col=0)
pd.set_option("display.max_rows", 5)

In [2]:

reviews.groupby('points').points.count()

Out[2]:

points
80 397
81 692
...
99 33
100 19
Name: points, Length: 21, dtype: int64

groupby() 创建了一组评论,这些评论为给定的葡萄酒分配了相同的分值。然后,对于每个组,我们获取 points() 列并计算其出现的次数。value_counts() 只是 groupby() 操作的快捷方式。

我们可以将之前使用过的任何汇总函数用于这些数据。例如,要获取每个分值类别中最便宜的葡萄酒,我们可以执行以下操作:

In [3]:

reviews.groupby('points').price.min()

Out[3]:

points
80 5.0
81 5.0
...
99 44.0
100 80.0
Name: price, Length: 21, dtype: float64

您可以将我们生成的每个组视为 DataFrame 的一个切片,其中仅包含值匹配的数据。我们可以使用 apply() 方法直接访问此 DataFrame,然后以任何我们认为合适的方式操作数据。例如,以下是从数据集中每个酒庄中抽取第一款被评论的葡萄酒名称的一种方法:

In [4]:

reviews.groupby('winery').apply(lambda df: df.title.iloc[0])

Out[4]:

winery
1+1=3 1+1=3 NV Rosé Sparkling (Cava)
10 Knots 10 Knots 2010 Viognier (Paso Robles)
...
àMaurice àMaurice 2013 Fred Estate Syrah (Walla Walla V...
Štoka Štoka 2009 Izbrani Teran (Kras)
Length: 16757, dtype: object

为了实现更精细的控制,您还可以按多列进行分组。例如,以下是按国家和省份挑选最佳葡萄酒的方法:

In [5]:

reviews.groupby(['country', 'province']).apply(lambda df: df.loc[df.points.idxmax()])

Out[5]:

country description designation points price province region_1 region_2 taster_name taster_twitter_handle title variety winery
country province
Argentina Mendoza Province Argentina If the color doesn’t tell the full story, the … Nicasia Vineyard 97 120.0 Mendoza Province Mendoza NaN Michael Schachner @wineschach Bodega Catena Zapata 2006 Nicasia Vineyard Mal… Malbec Bodega Catena Zapata
Other Argentina Take note, this could be the best wine Colomé … Reserva 95 90.0 Other Salta NaN Michael Schachner @wineschach Colomé 2010 Reserva Malbec (Salta) Malbec Colomé
Uruguay San Jose Uruguay Baked, sweet, heavy aromas turn earthy with ti… El Preciado Gran Reserva 87 50.0 San Jose NaN NaN Michael Schachner @wineschach Castillo Viejo 2005 El Preciado Gran Reserva R… Red Blend Castillo Viejo
Uruguay Uruguay Cherry and berry aromas are ripe, healthy and … Blend 002 Limited Edition 91 22.0 Uruguay NaN NaN Michael Schachner @wineschach Narbona NV Blend 002 Limited Edition Tannat-Ca… Tannat-Cabernet Franc Narbona

425 行 × 13 列

另一个值得一提的 groupby() 方法是 agg(),它允许你同时在 DataFrame 上运行多个不同的函数。例如,我们可以生成一个简单的数据集统计摘要,如下所示:

In [6]:

reviews.groupby(['country']).price.agg([len, min, max])

Out[6]:

len min max
country
Argentina 3800 4.0 230.0
Armenia 2 14.0 15.0
Ukraine 14 6.0 13.0
Uruguay 109 10.0 130.0

43 行 × 3 列

有效使用 groupby() 可以让你对数据集进行许多非常强大的操作。

Multi-indexes

到目前为止,我们看到的所有示例中,我们处理的都是具有单标签索引的 DataFrame 或 Series 对象。groupby() 略有不同,根据我们运行的操作,它有时会导致所谓的多重索引。

多重索引与常规索引的不同之处在于它具有多个级别。例如:

In [7]:

countries_reviewed = reviews.groupby(['country', 'province']).description.agg([len])
countries_reviewed

Out[7]:

len
country province
Argentina Mendoza Province 3264
Other 536
Uruguay San Jose 3
Uruguay 24

425行×1列

In [8]:

mi = countries_reviewed.index
type(mi)

Out[8]:

pandas.core.indexes.multi.MultiIndex

多索引有几种处理其分层结构的方法,而单级索引则没有。它们还需要两级标签来检索值。处理多索引输出是 Pandas 新用户常见的“陷阱”。

多索引的用例及其使用说明在 Pandas 文档的 多索引 / 高级选择 部分中有详细说明。

不过,通常情况下,您最常使用的多索引方法是用于转换回常规索引的方法,即 reset_index() 方法:

In [9]:

countries_reviewed.reset_index()

Out[9]:

country province len
0 Argentina Mendoza Province 3264
1 Argentina Other 536
423 Uruguay San Jose 3
424 Uruguay Uruguay 24

425行×3列

Sorting

再次查看 countries_reviewed,我们可以看到分组返回的数据是按索引顺序排列的,而不是按值顺序排列的。也就是说,输出 groupby 的结果时,行的顺序取决于索引中的值,而不是数据中的值。

为了按所需的顺序获取数据,我们可以自行排序。sort_values() 方法非常方便。

In [10]:

countries_reviewed = countries_reviewed.reset_index()
countries_reviewed.sort_values(by='len')

Out[10]:

country province len
179 Greece Muscat of Kefallonian 1
192 Greece Sterea Ellada 1
415 US Washington 8639
392 US California 36247

425 行 × 3 列

sort_values() 默认按升序排序,即最小值优先。然而,大多数情况下,我们希望按降序排序,即数值较大的值优先。具体如下:

In [11]:

countries_reviewed.sort_values(by='len', ascending=False)

Out[11]:

country province len
392 US California 36247
415 US Washington 8639
63 Chile Coelemu 1
149 Greece Beotia 1

425 行 × 3 列

要按索引值排序,请使用配套方法 sort_index()。此方法具有相同的参数和默认顺序:

In [12]:

countries_reviewed.sort_index()

Out[12]:

country province len
0 Argentina Mendoza Province 3264
1 Argentina Other 536
423 Uruguay San Jose 3
424 Uruguay Uruguay 24

425 行 × 3 列

最后,请注意,您可以同时按多列排序:

In [13]:

countries_reviewed.sort_values(by=['country', 'len'])

Out[13]:

country province len
1 Argentina Other 536
0 Argentina Mendoza Province 3264
424 Uruguay Uruguay 24
419 Uruguay Canelones 43

425行×3列

Your turn

如果你还没有开始练习,你可以**从这里开始**。