如何在Python Pandas DataFrame中选择每个组中最大的一个?

介绍

在数据分析期间执行的最基本,最常见的操作之一是选择包含组中某些列的最大值的行。在本文中,我将向您展示如何在DataFrame中找到每个组中最大的组。

问题..

让我们首先了解任务,假设您获得了电影数据集,并要求根据受欢迎程度列出每年最受欢迎的电影。

怎么做..

1,准备数据

那么Google充满了数据集。我经常使用kaggle.com来获取数据分析所需的数据集。随时登录kaggle.com并搜索电影。将电影数据集下载到目录中,并将其导入到Pandas DataFrame中。

如果您像我一样从kaggle.com下载了数据,请喜欢帮助您处理数据的人。

import pandas as pd
import numpy as np
movies = pd.read_csv("https://raw.githubusercontent.com/sasankac/TestDataSet/master/movies_data.csv")
# see sample 5 rows
print(f"Output \n\n*** {movies.sample(n=5)} ")

输出结果

*** budget id original_language original_title popularity \
2028 22000000 235260 en Son of God 9.175762
2548 0 13411 en Malibu's Most Wanted 7.314796
3279 8000000 26306 en Prefontaine 8.717235
3627 5000000 10217 en The Sweet Hereafter 7.673124
4555 0 98568 en Enter Nowhere 3.637857

release_date revenue runtime status title \
2028 28/02/2014 67800064 138.0 Released Son of God
2548 10/04/2003 0 86.0 Released Malibu's Most Wanted
3279 24/01/1997 589304 106.0 Released Prefontaine
3627 14/05/1997 3263585 112.0 Released The Sweet Hereafter
4555 22/10/2011 0 90.0 Released Enter Nowhere

vote_average vote_count
2028 5.9 83
2548 4.7 77
3279 6.7 21
3627 6.8 103
4555 6.5 49

2.执行一些基本数据分析以了解数据。

# Identify the data-types
print(f"Output \n*** Datatypes are {movies.dtypes} ")

输出结果

*** Datatypes are budget int64
id int64
original_language object
original_title object
popularity float64
release_date object
revenue int64
runtime float64
status object
title object
vote_average float64
vote_count int64
dtype: object

2.现在,如果要节省大量内存使用量,可以转换float64和int64的数据类型。但是,在转换数据类型之前,我们必须格外小心并做好功课。

# Check the maximum numeric value.
print(f"Output \n *** maximum value for Numeric data type - {movies.select_dtypes(exclude=['object']).unstack().max()}")

# what is the max vote count value
print(f" *** Vote count maximum value - {movies[['vote_count']].unstack().max()}")

# what is the max movie runtime value
print(f" *** Movie Id maximum value - {movies[['runtime']].unstack().max()}")

输出结果

*** maximum value for Numeric data type - 2787965087.0
*** Vote count maximum value - 13752
*** Movie Id maximum value - 338.0

3.有些列不需要用64位表示,可以降低到16位,所以让我们开始吧。64位整数范围是-32768至+32767。我将为表决数和运行时执行此操作,并且可以为需要较少内存存储的列执行此操作。

4.现在,要确定每年最受欢迎的电影,我们需要按release_date分组,以获取最大的人气值。典型的SQL如下所示。

SELECT movie with max popularity FROM movies GROUP BY movie released year

5.不幸的是,我们的release_date是Object数据类型,有几种方法可以将它们转换为datetime。我将选择仅用年份创建一个新列,以便可以将该列用于分组。

movies['year'] = pd.to_datetime(movies['release_date']).dt.year.astype('Int64')
print(f"Output \n ***{movies.sample(n=5)}")

输出结果

*** budget id original_language original_title popularity \
757 0 87825 en Trouble with the Curve 18.587114
711 58000000 39514 en RED 41.430245
1945 13500000 152742 en La migliore offerta 30.058263
2763 13000000 16406 en Dick 4.742537
4595 350000 764 en The Evil Dead 35.037625

release_date revenue runtime status title \
757 21/09/2012 0 111.0 Released Trouble with the Curve
711 13/10/2010 71664962 111.0 Released RED
1945 1/01/2013 19255873 124.0 Released The Best Offer
2763 4/08/1999 27500000 94.0 Released Dick
4595 15/10/1981 29400000 85.0 Released The Evil Dead

vote_average vote_count year
757 6.6 366 2012
711 6.6 2808 2010
1945 7.7 704 2013
2763 5.7 67 1999
4595 7.3 894 1981

方法1-不使用分组依据

6.我们只需要3列,电影标题,电影发行年份和受欢迎度。因此,我们选择这些列并在year上使用sort_values来查看结果。

print(f"Output \n *** Method 1- Without Using Group By")
movies[["title", "year", "popularity"]].sort_values("year", ascending=True)

输出结果

*** Without Using Group By



标题人气
4592不宽容1916年3.232447
4661大游行1925年0.785744
2638都会1927年32.351527
4594百老汇旋律1929年0.968865
4457潘多拉魔盒1929年1.824184
............
2109我在你之前2016年53.161905
3081森林2016年19.865989
2288战斗谷2016年1.224105
4255成长史密斯2017年0.710870
4553美国仍然是地方<NA>0.000000

4803行×3列

8.现在看结果,我们还需要对受欢迎程度进行排序,以获取一年中最受欢迎的电影。将感兴趣的列作为列表传递。ascending = False将导致排序结果按降序排列。

movies[["title", "year", "popularity"]].sort_values(["year","popularity"], ascending=False)



标题人气
4255成长史密斯2017年0.710870
788死侍2016年514.569956
26美国队长:内战2016年198.372395
10蝙蝠侠对超人:正义曙光2016年155.790452
64X战警:天启2016年139.272042
............
4593百老汇旋律1929年0.968865
2638都会1927年32.351527
4660大游行1925年0.785744
4591不宽容1916年3.232447
4552美国仍然是地方<NA>0.000000

4802行×3列

9.好的,现在数据已完美排序。因此,下一步就是只保留每年的第一个值,并除去其余部分。猜猜怎么做?

我们将使用.drop_duplicates方法。

movies[["title", "year", "popularity"]].sort_values(["year","popularity"], ascending=False).drop_duplicates(subset="year")



标题人气
4255成长史密斯2017年0.710870
788死侍2016年514.569956
546奴才2015年875.581305
95星际2014年724.247784
124冰冻的2013年165.125366
............
4456潘多拉魔盒1929年1.824184
2638都会1927年32.351527
4660大游行1925年0.785744
4591不宽容1916年3.232447
4552美国仍然是地方<NA>0.000000

91行×3列

方法2-使用分组依据

我们也可以通过groupby达到相同的效果。该方法与上面显示的SQL非常相似。

print(f"Output \n *** Method 2 - Using Group By")
movies[["title", "year", "popularity"]].groupby("year", as_index=False).apply(lambda df:df.sort_values("popularity", ascending=False)
.head(1)).droplevel(0).sort_values("year", ascending=False)

输出结果

*** Method 2 - Using Group By



标题人气
4255成长史密斯2017年0.710870
788死侍2016年514.569956
546奴才2015年875.581305
95星际2014年724.247784
124冰冻的2013年165.125366
............
3804地狱天使1930年8.484123
4457潘多拉魔盒1929年1.824184
2638都会1927年32.351527
4661大游行1925年0.785744
4592不宽容1916年3.232447

90行×3列