如何在Python Pandas DataFrame中選擇每組的最大值?
簡介
在資料分析過程中,最基本和最常見的操作之一是從組內選擇包含某些列最大值的行。在這篇文章中,我將向您展示如何在DataFrame中查詢每組的最大值。
問題…
讓我們首先了解任務,假設您獲得了一個電影資料集,並要求根據受歡迎程度列出每年最受歡迎的電影。
怎麼做…
1.準備資料。
谷歌上有很多資料集。我經常使用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位int範圍是從-32768到+32767。我將對vote_count和runtime進行此操作,您可以對需要更少記憶體儲存的列進行此操作。
4.現在,要識別每年的最受歡迎電影,我們需要按release_date分組並獲取popularity的最大值。一個典型的SQL查詢如下所示。
SELECT movie with max popularity FROM movies GROUP BY movie released year
5.不幸的是,我們的release_date是物件資料型別,有幾種方法可以將其轉換為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 - 不使用GroupBy
6.我們只需要3列:電影標題、電影上映年份和受歡迎程度。所以我們選擇這些列,並使用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 |
64 | X戰警:天啟 | 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
我們也可以用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列