介绍
Maps允许我们一次把DataFrame 或 Series中的一列数据转换为一个值。但是,通常我们希望对数据进行分组,然后对数据所在的组执行特定的操作。
正如您将了解到的,我们使用 groupby() 函数来完成这个操作。本节我们还将讨论一些例如更复杂的 DataFrames 索引方法,以及如何对数据排序等其他主题。
分组分析
到目前为止,我们一直在大量使用的一个函数是 value_counts() 函数。我们可以通过执行以下操作完成value_counts() 函数所实现的功能:
import pandas as pdreviews = pd.read_csv("../data/winemag-data-130k-v2.csv", index_col=0)print(reviews.groupby('points').points.count())
points80 39781 69282 183683 302584 648085 953086 1260087 1693388 1720789 1222690 1541091 1135992 961393 648994 375895 153596 52397 22998 7799 33100 19Name: points, dtype: int64
groupby() 先创建一系列reviews的分组,将相同的分值的葡萄酒分配到一组。然后,针对每一个组,我们抓取points() 列并计算葡萄酒品牌出现的次数。value_counts() 是groupby() 操作的一个快捷方式。
我们可以对这些数据使用以前使用过的任何汇总函数。例如,要获得每个评分值组中最便宜的葡萄酒,我们可以执行以下操作:
import pandas as pdreviews = pd.read_csv("../data/winemag-data-130k-v2.csv", index_col=0)print(reviews.groupby('points').price.min())
points80 5.081 5.082 4.083 4.084 4.085 4.086 4.087 5.088 6.089 7.090 8.091 7.092 11.093 12.094 13.095 20.096 20.097 35.098 50.099 44.0100 80.0Name: price, dtype: float64
您可以将生成的每个组看成 DataFrame 中的只包括数据与其对应值的一个切片。我们可以直接使用apply() 方法访问这个 DataFrame ,然后我们可以以任何我们认为合适的方式操作数据。例如,下面方法可以从数据集中的每个酒庄中选择评价排名第一的葡萄酒的名称:
import pandas as pdreviews = pd.read_csv("../data/winemag-data-130k-v2.csv", index_col=0)print(reviews.groupby('winery').apply(lambda df: df.title.iloc[0]))
winery1+1=3 1+1=3 NV Rosé Sparkling (Cava)10 Knots 10 Knots 2010 Viognier (Paso Robles)100 Percent Wine 100 Percent Wine 2015 Moscato (California)1000 Stories 1000 Stories 2013 Bourbon Barrel Aged Zinfande...1070 Green 1070 Green 2011 Sauvignon Blanc (Rutherford)...Órale Órale 2011 Cabronita Red (Santa Ynez Valley)Öko Öko 2013 Made With Organically Grown Grapes Ma...Ökonomierat Rebholz Ökonomierat Rebholz 2007 Von Rotliegenden Spät...àMaurice àMaurice 2013 Fred Estate Syrah (Walla Walla V...Štoka Štoka 2009 Izbrani Teran (Kras)Length: 16757, dtype: object
对于更细粒度的控制,还可以按多个列进行分组。举个例子,下面是如何根据国家和省份挑选最好的葡萄酒:
import pandas as pdreviews = pd.read_csv("../data/winemag-data-130k-v2.csv", index_col=0)print(reviews.groupby(['country', 'province']).apply(lambda df: df.loc[df.points.idxmax()]))
country ... winerycountry province ...Argentina Mendoza Province Argentina ... Bodega Catena ZapataOther Argentina ... ColoméArmenia Armenia Armenia ... Van ArdiAustralia Australia Other Australia ... Marquis PhilipsNew South Wales Australia ... De Bortoli... ... ... ...Uruguay Juanico Uruguay ... Familia DeicasMontevideo Uruguay ... BouzaProgreso Uruguay ... PisanoSan Jose Uruguay ... Castillo ViejoUruguay Uruguay ... Narbona[425 rows x 13 columns]
另一个值得一提的可用于groupby() 方法是agg()函数,它允许您在 DataFrame 上同时运行一堆不同的函数。例如,下面代码可以生成数据集的简单统计摘要:
import pandas as pdreviews = pd.read_csv("../data/winemag-data-130k-v2.csv", index_col=0)print(reviews.groupby(['country']).price.agg([len, min, max]))
len min maxcountryArgentina 3800.0 4.0 230.0Armenia 2.0 14.0 15.0Australia 2329.0 5.0 850.0Austria 3345.0 7.0 1100.0Bosnia and Herzegovina 2.0 12.0 13.0Brazil 52.0 10.0 60.0Bulgaria 141.0 8.0 100.0Canada 257.0 12.0 120.0Chile 4472.0 5.0 400.0China 1.0 18.0 18.0Croatia 73.0 12.0 65.0Cyprus 11.0 11.0 21.0Czech Republic 12.0 15.0 45.0Egypt 1.0 NaN NaNEngland 74.0 25.0 95.0France 22093.0 5.0 3300.0Georgia 86.0 9.0 40.0Germany 2165.0 5.0 775.0Greece 466.0 8.0 79.0Hungary 146.0 10.0 764.0India 9.0 10.0 20.0Israel 505.0 8.0 150.0Italy 19540.0 5.0 900.0Lebanon 35.0 13.0 75.0Luxembourg 6.0 16.0 30.0Macedonia 12.0 15.0 20.0Mexico 70.0 8.0 108.0Moldova 59.0 8.0 42.0Morocco 28.0 14.0 40.0New Zealand 1419.0 7.0 130.0Peru 16.0 10.0 68.0Portugal 5691.0 5.0 1000.0Romania 120.0 4.0 320.0Serbia 12.0 15.0 42.0Slovakia 1.0 16.0 16.0Slovenia 87.0 7.0 90.0South Africa 1401.0 5.0 330.0Spain 6645.0 4.0 770.0Switzerland 7.0 21.0 160.0Turkey 90.0 14.0 120.0US 54504.0 4.0 2013.0Ukraine 14.0 6.0 13.0Uruguay 109.0 10.0 130.0
有效地使用groupby()方法会允许您对数据集执行许多非常强大的操作。
多索引
到目前为止,在我们看到的所有示例中,我们都使用带有单个标签索引的DataFrame或Series对象。groupby() 稍有不同,根据我们运行的操作不同,它有时会导致所谓的多索引。
多索引不同于常规索引,因为它有多个级别。例如:
import pandas as pdreviews = pd.read_csv("../data/winemag-data-130k-v2.csv", index_col=0)countries_reviewed = reviews.groupby(['country', 'province']).description.agg([len])print(countries_reviewed)
lencountry provinceArgentina Mendoza Province 3264Other 536Armenia Armenia 2Australia Australia Other 245New South Wales 85... ...Uruguay Juanico 12Montevideo 11Progreso 11San Jose 3Uruguay 24[425 rows x 1 columns]
mi = countries_reviewed.indexprint(type(mi)) # <class 'pandas.core.indexes.multi.MultiIndex'>
多索引有一些单索引没有的、能够处理分层结构的方法。它们还需要两个级别的标签来检索值。对于刚接触 pandas的用户来说,处理多索引输出是一个常见的“陷阱””gotcha”。
在pandas文档的multi index/Advanced Selection部分中,将详细介绍多索引的用例以及使用它们的说明。
但是,通常最常用的多索引方法是用于转换回常规索引的方法reset_index() 方法:
import pandas as pdreviews = pd.read_csv("../data/winemag-data-130k-v2.csv", index_col=0)countries_reviewed = reviews.groupby(['country', 'province']).description.agg([len])print(countries_reviewed.reset_index())
country province len0 Argentina Mendoza Province 32641 Argentina Other 5362 Armenia Armenia 23 Australia Australia Other 2454 Australia New South Wales 85.. ... ... ...420 Uruguay Juanico 12421 Uruguay Montevideo 11422 Uruguay Progreso 11423 Uruguay San Jose 3424 Uruguay Uruguay 24[425 rows x 3 columns]
排序
回头再看一下根据countries_reviewed的结果,我们可以看到分组返回的数据是按索引顺序返回的,而不是按值顺序返回的。也就是说,当输出groupby的结果时,行的顺序取决于索引中的值,而不是数据中的值。
为了得到我们想要的顺序的数据,可以自己排序。sort_values() 方法可以方便的实现这个功能。
import pandas as pdreviews = pd.read_csv("../data/winemag-data-130k-v2.csv", index_col=0)countries_reviewed = reviews.groupby(['country', 'province']).description.agg([len])countries_reviewed = countries_reviewed.reset_index()print(countries_reviewed.sort_values(by='len'))
country province len179 Greece Muscat of Kefallonian 1192 Greece Sterea Ellada 1194 Greece Thraki 1354 South Africa Paardeberg 140 Brazil Serra do Sudeste 1.. ... ... ...409 US Oregon 5373227 Italy Tuscany 5897118 France Bordeaux 5941415 US Washington 8639392 US California 36247[425 rows x 3 columns]
sort_values() 默认为最低值优先的升序排序。然而,大多数情况下,我们需要一个最高的数字排第一的降序排序,可以用指定参数 ascending=False 的方法实现:
import pandas as pdreviews = pd.read_csv("../data/winemag-data-130k-v2.csv", index_col=0)countries_reviewed = reviews.groupby(['country', 'province']).description.agg([len])countries_reviewed = countries_reviewed.reset_index()print(countries_reviewed.sort_values(by='len', ascending=False))
country province len392 US California 36247415 US Washington 8639118 France Bordeaux 5941227 Italy Tuscany 5897409 US Oregon 5373.. ... ... ...101 Croatia Krk 1247 New Zealand Gladstone 1357 South Africa Piekenierskloof 163 Chile Coelemu 1149 Greece Beotia 1[425 rows x 3 columns]
若要按索引值排序,请使用一个类似的方法sort_index(),此方法与 sort_values() 方法具有相同的参数和默认顺序:
import pandas as pdreviews = pd.read_csv("../data/winemag-data-130k-v2.csv", index_col=0)countries_reviewed = reviews.groupby(['country', 'province']).description.agg([len])print(countries_reviewed.sort_index())
len
country province
Argentina Mendoza Province 3264
Other 536
Armenia Armenia 2
Australia Australia Other 245
New South Wales 85
... ...
Uruguay Juanico 12
Montevideo 11
Progreso 11
San Jose 3
Uruguay 24
[425 rows x 1 columns]
最后,要知道可以同时按多个列排序:
import pandas as pd
reviews = pd.read_csv("../data/winemag-data-130k-v2.csv", index_col=0)
countries_reviewed = reviews.groupby(['country', 'province']).description.agg([len])
print(countries_reviewed.sort_values(by=['country', 'len']))
len
country province
Argentina Other 536
Mendoza Province 3264
Armenia Armenia 2
Australia Tasmania 42
New South Wales 85
... ...
Uruguay Montevideo 11
Progreso 11
Juanico 12
Uruguay 24
Canelones 43
[425 rows x 1 columns]
转载自链接
