前言
本文選取了四個(gè)經(jīng)典案例,主要聚焦Pandas在數(shù)據(jù)分析中的簡單應(yīng)用,結(jié)合代碼學(xué)習(xí)利用Python進(jìn)行數(shù)據(jù)分析過程(●ˇ?ˇ●)。在每個(gè)例題開始前,我們將會(huì)標(biāo)注出本例題涉及的重要知識(shí)點(diǎn),并在重要處添加解釋和代碼注釋,共讀者參考。
如果你遇到任何問題,歡迎在評(píng)論區(qū)一起討論╰(*°▽°*)╯
點(diǎn)擊最上方橫幅??下載本文例子中用到的數(shù)據(jù)包,或點(diǎn)此??下載鏈接
敬告:數(shù)據(jù)內(nèi)容僅供學(xué)習(xí)使用,不代表任何真實(shí)數(shù)據(jù)!請(qǐng)勿作他用!╰(‵□′)╯?
了解Pandas
Pandas(Python Data Analysis Library)是基于NumPy的數(shù)據(jù)分析模塊,它提供了大量標(biāo)準(zhǔn)數(shù)據(jù)模型和高效操作大型數(shù)據(jù)集所需的工具??梢哉fPandas是使得Python能夠成為高效且強(qiáng)大的數(shù)據(jù)分析環(huán)境的重要因素之一。
Pandas提供了兩種主要的數(shù)據(jù)結(jié)構(gòu):Series和DataFrame。這些數(shù)據(jù)結(jié)構(gòu)使得在Python中進(jìn)行數(shù)據(jù)操作和分析變得更加方便。
1. Series: Series是Pandas中的一維標(biāo)記數(shù)組。它類似于一維數(shù)組或列表,但附帶了標(biāo)簽(label),使得數(shù)據(jù)可以按標(biāo)簽進(jìn)行訪問和操作。Series由兩部分組成:數(shù)據(jù)部分和索引(index)。數(shù)據(jù)部分存儲(chǔ)了一組值,而索引是用于標(biāo)識(shí)和訪問這些值的標(biāo)簽。
例如,創(chuàng)建一個(gè)Series對(duì)象來表示學(xué)生的分?jǐn)?shù):
import pandas as pd
scores = pd.Series([85, 90, 75, 80])
這將創(chuàng)建一個(gè)包含分?jǐn)?shù)數(shù)據(jù)的Series對(duì)象。默認(rèn)情況下,索引將從0開始自動(dòng)分配??梢酝ㄟ^指定索引來自定義標(biāo)簽:
scores = pd.Series([85, 90, 75, 80], index=['Alice', 'Bob', 'Charlie', 'Dave'])
現(xiàn)在,每個(gè)分?jǐn)?shù)都與對(duì)應(yīng)的學(xué)生姓名相關(guān)聯(lián)。
2. DataFrame: DataFrame是Pandas中最常用的數(shù)據(jù)結(jié)構(gòu),它類似于一個(gè)二維表格或電子表格。它由行和列組成,每一列可以包含不同類型的數(shù)據(jù)(如數(shù)字、字符串、布爾值等)。
可以將DataFrame視為一組Series對(duì)象的集合,它們共享相同的索引。DataFrame提供了許多功能,包括數(shù)據(jù)選擇、過濾、排序、統(tǒng)計(jì)和數(shù)據(jù)可視化等。
創(chuàng)建一個(gè)簡單的DataFrame示例:
data = {'Name': ['Alice', 'Bob', 'Charlie', 'Dave'],
'Age': [25, 30, 35, 40],
'City': ['New York', 'London', 'Paris', 'Tokyo']}
df = pd.DataFrame(data)
將創(chuàng)建一個(gè)包含姓名、年齡和城市的DataFrame對(duì)象。每一列都表示一個(gè)Series對(duì)象,而DataFrame提供了將它們組合在一起的結(jié)構(gòu)。
(≧?≦)?學(xué)習(xí)更多關(guān)于Pandas的知識(shí),請(qǐng)?zhí)D(zhuǎn)到:Pandas教程(非常詳細(xì))-CSDN博客
1.MoviesLens 1M數(shù)據(jù)集?
GroupLens實(shí)驗(yàn)室提供了一些從MoviesLens用戶那里收集的20世紀(jì)90年代末到21世紀(jì)初的電影評(píng)分?jǐn)?shù)據(jù)的集合。浙西額數(shù)據(jù)提供了電影的評(píng)分、流派、年份和觀眾數(shù)據(jù)(年齡、郵編、性別、職業(yè))。MovisLens1M數(shù)據(jù)集包含6000個(gè)用戶對(duì)4000部電影的100萬個(gè)評(píng)分。數(shù)據(jù)分布在三個(gè)表格之中:分別包含評(píng)分、用戶信息和電影信息。
接下來我們將結(jié)合代碼共同學(xué)習(xí)這一分析過程。本例題涉及以下知識(shí)點(diǎn),重要處會(huì)有解釋:
-
數(shù)據(jù)合并和連接:使用
pd.merge()
函數(shù)將多個(gè)DataFrame
對(duì)象合并為一個(gè)新的DataFrame
,根據(jù)共同的列進(jìn)行連接。通過合并數(shù)據(jù),可以將不同來源的數(shù)據(jù)整合在一起,以便進(jìn)行綜合分析。 -
數(shù)據(jù)透視表:使用
pivot_table()
函數(shù)創(chuàng)建數(shù)據(jù)透視表,基于不同的維度對(duì)數(shù)據(jù)進(jìn)行匯總和聚合。 -
數(shù)據(jù)分組和聚合:使用
groupby()
函數(shù)對(duì)DataFrame
對(duì)象進(jìn)行分組,并應(yīng)用聚合函數(shù)(如平均值、計(jì)數(shù)等)對(duì)每個(gè)組進(jìn)行計(jì)算。通過分組和聚合,可以對(duì)數(shù)據(jù)進(jìn)行更詳細(xì)的分析和統(tǒng)計(jì)。 -
數(shù)據(jù)排序和篩選:使用
sort_values()
函數(shù)對(duì)DataFrame
對(duì)象進(jìn)行排序,根據(jù)特定的列進(jìn)行升序或降序排序。同時(shí),使用條件語句進(jìn)行篩選,選擇符合特定條件的行或列數(shù)據(jù)。 -
數(shù)據(jù)操作和轉(zhuǎn)換:使用字符串處理函數(shù)(如
split()
、explode()
等)對(duì)字符串類型的列進(jìn)行操作和轉(zhuǎn)換,以提取有用的信息或?qū)?shù)據(jù)拆分成多個(gè)行。這些操作可以使數(shù)據(jù)更加便于分析和理解。 -
數(shù)據(jù)統(tǒng)計(jì)和計(jì)算:使用聚合函數(shù)(如
mean()
、std()
等)對(duì)數(shù)據(jù)進(jìn)行統(tǒng)計(jì)和計(jì)算,揭示數(shù)據(jù)的統(tǒng)計(jì)特征和變化情況。
import pandas as pd
#文件皆位于根目錄下
# 讀取"users.dat"文件,它將列名設(shè)置為unames,并將分隔符設(shè)置為::。header=None參數(shù)表示文件中沒有標(biāo)題行,因此應(yīng)使用unames中提供的列名。
unames = ["user_id", "gender", "age", "occupation", "zip"]
users = pd.read_table("datasets/movielens/users.dat", sep="::", header=None, names=unames, engine="python")
# 讀取"ratings.dat"文件
rnames = ["user_id", "movie_id", "rating", "timestamp"]
ratings = pd.read_table("datasets/movielens/ratings.dat", sep="::", header=None, names=rnames, engine="python")
# 讀取"movies.dat"文件
mnames = ["movie_id", "title", "genres"]
movies = pd.read_table("datasets/movielens/movies.dat", sep="::", header=None, names=mnames, engine="python")
#這段代碼片段讀取了三個(gè)文件("users.dat"、"ratings.dat"和"movies.dat"),
#并將它們分別存儲(chǔ)在不同的pandas DataFrame中(users、ratings和movies),以便進(jìn)一步分析或處理。
users.head(5)#輸出用戶DataFrame的前5行數(shù)據(jù)
ratings.head(5)# 輸出評(píng)分DataFrame的前5行數(shù)據(jù)
movies.head(5)# 輸出電影DataFrame的前5行數(shù)據(jù)
ratings# 輸出完整的ratings DataFrame
user_id | movie_id | rating | timestamp | |
---|---|---|---|---|
0 | 1 | 1193 | 5 | 978300760 |
1 | 1 | 661 | 3 | 978302109 |
2 | 1 | 914 | 3 | 978301968 |
3 | 1 | 3408 | 4 | 978300275 |
4 | 1 | 2355 | 5 | 978824291 |
... | ... | ... | ... | ... |
1000204 | 6040 | 1091 | 1 | 956716541 |
1000205 | 6040 | 1094 | 5 | 956704887 |
1000206 | 6040 | 562 | 5 | 956704746 |
1000207 | 6040 | 1096 | 4 | 956715648 |
1000208 | 6040 | 1097 | 4 | 956715569 |
#使用pd.merge()函數(shù)將ratings、users和movies三個(gè)DataFrame合并為一個(gè)名為data的新DataFrame。
#這個(gè)新的data DataFrame將包含了三個(gè)原始DataFrame中的所有列和行,基于它們之間的共同列進(jìn)行合并。
data = pd.merge(pd.merge(ratings, users), movies)
data#輸出data DataFrame合并后的所有數(shù)據(jù)
data.iloc[0]#輸出data DataFrame中的第一行數(shù)據(jù)
user_id 1 movie_id 1193 rating 5 timestamp 978300760 gender F age 1 occupation 10 zip 48067 title One Flew Over the Cuckoo's Nest (1975) genres Drama Name: 0, dtype: object
#使用pivot_table()函數(shù)基于data DataFrame創(chuàng)建了一個(gè)名為mean_ratings的新DataFrame,
#該DataFrame計(jì)算了每個(gè)電影標(biāo)題(title)在不同性別(gender)下的平均評(píng)分。
mean_ratings = data.pivot_table("rating", index="title",columns="gender", aggfunc="mean")
mean_ratings.head(5)#mean_ratings DataFrame 的前5行輸出
gender | F | M |
---|---|---|
title | ||
$1,000,000 Duck (1971) | 3.375000 | 2.761905 |
'Night Mother (1986) | 3.388889 | 3.352941 |
'Til There Was You (1997) | 2.675676 | 2.733333 |
'burbs, The (1989) | 2.793478 | 2.962085 |
...And Justice for All (1979) | 3.828571 | 3.689024 |
Q:什么是數(shù)據(jù)透視表?
A:數(shù)據(jù)透視表是一種數(shù)據(jù)匯總和聚合的方法,通過對(duì)數(shù)據(jù)進(jìn)行重新排列和匯總,可以提供對(duì)數(shù)據(jù)的多個(gè)維度的聚合結(jié)果。數(shù)據(jù)透視表可以幫助我們更好地理解數(shù)據(jù)之間的關(guān)系和趨勢(shì),從而支持更深入的數(shù)據(jù)分析和決策。數(shù)據(jù)透視表的主要優(yōu)勢(shì)是可以快速而靈活地匯總數(shù)據(jù),并以一種直觀的方式展示匯總結(jié)果。以下是數(shù)據(jù)透視表的幾個(gè)關(guān)鍵要素:
1. 行索引:選擇一個(gè)或多個(gè)列作為行索引,根據(jù)這些列的值進(jìn)行數(shù)據(jù)的分組和分類。行索引決定了透視表中的每一行。
2. 列索引:選擇一個(gè)或多個(gè)列作為列索引,根據(jù)這些列的值進(jìn)行數(shù)據(jù)的分組和分類。列索引決定了透視表中的每一列。
3. 聚合值:選擇一個(gè)或多個(gè)列作為聚合值,對(duì)這些列的值進(jìn)行聚合計(jì)算,如求和、平均值、計(jì)數(shù)等。聚合值決定了透視表中每個(gè)單元格的內(nèi)容。
4. 聚合函數(shù):選擇適當(dāng)?shù)木酆虾瘮?shù)對(duì)聚合值進(jìn)行計(jì)算。常見的聚合函數(shù)包括求和、平均值、計(jì)數(shù)、最大值、最小值等。
通過這些要素的組合,可以根據(jù)不同的需求和分析目標(biāo)創(chuàng)建不同形式的數(shù)據(jù)透視表。數(shù)據(jù)透視表的結(jié)果可以提供對(duì)數(shù)據(jù)的多維度聚合結(jié)果,幫助我們發(fā)現(xiàn)數(shù)據(jù)中的模式、趨勢(shì)和關(guān)聯(lián)性。
#使用groupby()函數(shù)對(duì)data DataFrame按電影標(biāo)題(title)進(jìn)行分組,并計(jì)算每個(gè)電影標(biāo)題對(duì)應(yīng)的評(píng)分?jǐn)?shù)量。
ratings_by_title = data.groupby("title").size()
ratings_by_title.head()#顯示每個(gè)電影標(biāo)題對(duì)應(yīng)的評(píng)分?jǐn)?shù)量。
active_titles = ratings_by_title.index[ratings_by_title >= 250]#從評(píng)分?jǐn)?shù)量中篩選出了評(píng)分?jǐn)?shù)大于等于250的活躍電影標(biāo)題
active_titles
Index([''burbs, The (1989)', '10 Things I Hate About You (1999)', '101 Dalmatians (1961)', '101 Dalmatians (1996)', '12 Angry Men (1957)', '13th Warrior, The (1999)', '2 Days in the Valley (1996)', '20,000 Leagues Under the Sea (1954)', '2001: A Space Odyssey (1968)', '2010 (1984)', ... 'X-Men (2000)', 'Year of Living Dangerously (1982)', 'Yellow Submarine (1968)', 'You've Got Mail (1998)', 'Young Frankenstein (1974)', 'Young Guns (1988)', 'Young Guns II (1990)', 'Young Sherlock Holmes (1985)', 'Zero Effect (1998)', 'eXistenZ (1999)'], dtype='object', name='title', length=1216)
#使用loc索引器從mean_ratings DataFrame 中選擇評(píng)分?jǐn)?shù)大于等于250的活躍電影標(biāo)題
mean_ratings = mean_ratings.loc[active_titles]
mean_ratings
gender | F | M |
---|---|---|
title | ||
'burbs, The (1989) | 2.793478 | 2.962085 |
10 Things I Hate About You (1999) | 3.646552 | 3.311966 |
101 Dalmatians (1961) | 3.791444 | 3.500000 |
101 Dalmatians (1996) | 3.240000 | 2.911215 |
12 Angry Men (1957) | 4.184397 | 4.328421 |
... | ... | ... |
Young Guns (1988) | 3.371795 | 3.425620 |
Young Guns II (1990) | 2.934783 | 2.904025 |
Young Sherlock Holmes (1985) | 3.514706 | 3.363344 |
Zero Effect (1998) | 3.864407 | 3.723140 |
eXistenZ (1999) | 3.098592 | 3.289086 |
#使用rename()函數(shù)將mean_ratings DataFrame 中的索引標(biāo)簽從"Seven Samurai (The Magnificent Seven) (Shichinin no samurai) (1954)"更改為
#"Seven Samurai (Shichinin no samurai) (1954)"。
mean_ratings = mean_ratings.rename(index={"Seven Samurai (The Magnificent Seven) (Shichinin no samurai) (1954)":
"Seven Samurai (Shichinin no samurai) (1954)"})
#使用sort_values()函數(shù)根據(jù)女性觀眾的平均評(píng)分("F"列)對(duì)mean_ratings DataFrame 進(jìn)行降序排序
top_female_ratings = mean_ratings.sort_values("F", ascending=False)
top_female_ratings.head()
gender | F | M | diff |
---|---|---|---|
title | |||
Close Shave, A (1995) | 4.644444 | 4.473795 | -0.170650 |
Wrong Trousers, The (1993) | 4.588235 | 4.478261 | -0.109974 |
Sunset Blvd. (a.k.a. Sunset Boulevard) (1950) | 4.572650 | 4.464589 | -0.108060 |
Wallace & Gromit: The Best of Aardman Animation (1996) | 4.563107 | 4.385075 | -0.178032 |
Schindler's List (1993) | 4.562602 | 4.491415 | -0.071187 |
#通過計(jì)算mean_ratings DataFrame 中男性觀眾平均評(píng)分("M"列)與女性觀眾平均評(píng)分("F"列)的差異,將差異值添加為名為"diff"的新列。
mean_ratings["diff"] = mean_ratings["M"] - mean_ratings["F"]
mean_ratings
gender | F | M | diff |
---|---|---|---|
title | |||
'burbs, The (1989) | 2.793478 | 2.962085 | 0.168607 |
10 Things I Hate About You (1999) | 3.646552 | 3.311966 | -0.334586 |
101 Dalmatians (1961) | 3.791444 | 3.500000 | -0.291444 |
101 Dalmatians (1996) | 3.240000 | 2.911215 | -0.328785 |
12 Angry Men (1957) | 4.184397 | 4.328421 | 0.144024 |
... | ... | ... | ... |
Young Guns (1988) | 3.371795 | 3.425620 | 0.053825 |
Young Guns II (1990) | 2.934783 | 2.904025 | -0.030758 |
Young Sherlock Holmes (1985) | 3.514706 | 3.363344 | -0.151362 |
Zero Effect (1998) | 3.864407 | 3.723140 | -0.141266 |
eXistenZ (1999) | 3.098592 | 3.289086 | 0.190494 |
#使用sort_values()函數(shù)根據(jù)差異值("diff"列)對(duì)mean_ratings DataFrame 進(jìn)行升序排序
sorted_by_diff = mean_ratings.sort_values("diff")
sorted_by_diff.head()
gender | F | M | diff |
---|---|---|---|
title | |||
Dirty Dancing (1987) | 3.790378 | 2.959596 | -0.830782 |
Jumpin' Jack Flash (1986) | 3.254717 | 2.578358 | -0.676359 |
Grease (1978) | 3.975265 | 3.367041 | -0.608224 |
Little Women (1994) | 3.870588 | 3.321739 | -0.548849 |
Steel Magnolias (1989) | 3.901734 | 3.365957 | -0.535777 |
#通過使用切片操作[::-1]對(duì)sorted_by_diff DataFrame 進(jìn)行逆序排序,并返回前5行內(nèi)容。
sorted_by_diff[::-1].head(5)
gender | F | M | diff |
---|---|---|---|
title | |||
Good, The Bad and The Ugly, The (1966) | 3.494949 | 4.221300 | 0.726351 |
Kentucky Fried Movie, The (1977) | 2.878788 | 3.555147 | 0.676359 |
Dumb & Dumber (1994) | 2.697987 | 3.336595 | 0.638608 |
Longest Day, The (1962) | 3.411765 | 4.031447 | 0.619682 |
Cable Guy, The (1996) | 2.250000 | 2.863787 | 0.613787 |
#使用groupby()函數(shù)按電影標(biāo)題(title)分組,并計(jì)算每個(gè)電影標(biāo)題對(duì)應(yīng)的評(píng)分標(biāo)準(zhǔn)差。
rating_std_by_title = data.groupby("title")["rating"].std()
#從標(biāo)準(zhǔn)差結(jié)果中篩選出評(píng)分?jǐn)?shù)大于等于250的活躍電影標(biāo)題,
rating_std_by_title = rating_std_by_title.loc[active_titles]
rating_std_by_title.head()
title 'burbs, The (1989) 1.107760 10 Things I Hate About You (1999) 0.989815 101 Dalmatians (1961) 0.982103 101 Dalmatians (1996) 1.098717 12 Angry Men (1957) 0.812731 Name: rating, dtype: float64
#使用sort_values()函數(shù)將rating_std_by_title Series 對(duì)象按評(píng)分標(biāo)準(zhǔn)差進(jìn)行降序排序,并返回前10個(gè)最大的標(biāo)準(zhǔn)差值。
rating_std_by_title.sort_values(ascending=False)[:10]
title Dumb & Dumber (1994) 1.321333 Blair Witch Project, The (1999) 1.316368 Natural Born Killers (1994) 1.307198 Tank Girl (1995) 1.277695 Rocky Horror Picture Show, The (1975) 1.260177 Eyes Wide Shut (1999) 1.259624 Evita (1996) 1.253631 Billy Madison (1995) 1.249970 Fear and Loathing in Las Vegas (1998) 1.246408 Bicentennial Man (1999) 1.245533 Name: rating, dtype: float64
#展示"genres"列的前5行數(shù)據(jù)
movies["genres"].head()
#將每個(gè)電影的"genres"列按豎線字符分割成一個(gè)列表
movies["genres"].head().str.split("|")
#將分割后的列表賦值給了一個(gè)名為"genre"的新列,并刪除了原始的"genres"列。這樣,"genre"列包含了每個(gè)電影的類型列表。
movies["genre"] = movies.pop("genres").str.split("|")
movies.head()
movie_id | title | genre | |
---|---|---|---|
0 | 1 | Toy Story (1995) | [Animation, Children's, Comedy] |
1 | 2 | Jumanji (1995) | [Adventure, Children's, Fantasy] |
2 | 3 | Grumpier Old Men (1995) | [Comedy, Romance] |
3 | 4 | Waiting to Exhale (1995) | [Comedy, Drama] |
4 | 5 | Father of the Bride Part II (1995) | [Comedy] |
#使用explode()函數(shù)將"genre"列中的列表元素展開為多行,并將結(jié)果存儲(chǔ)在名為"movies_exploded"的新DataFrame中。然后顯示前10行的數(shù)據(jù)。
movies_exploded = movies.explode("genre")
movies_exploded[:10]
movie_id | title | genre | |
---|---|---|---|
0 | 1 | Toy Story (1995) | Animation |
0 | 1 | Toy Story (1995) | Children's |
0 | 1 | Toy Story (1995) | Comedy |
1 | 2 | Jumanji (1995) | Adventure |
1 | 2 | Jumanji (1995) | Children's |
1 | 2 | Jumanji (1995) | Fantasy |
2 | 3 | Grumpier Old Men (1995) | Comedy |
2 | 3 | Grumpier Old Men (1995) | Romance |
3 | 4 | Waiting to Exhale (1995) | Comedy |
3 | 4 | Waiting to Exhale (1995) | Drama |
#使用pd.merge()函數(shù)將"movies_exploded"、"ratings"和"users"三個(gè)DataFrame進(jìn)行合并,創(chuàng)建一個(gè)名為"ratings_with_genre"的新DataFrame。
ratings_with_genre = pd.merge(pd.merge(movies_exploded, ratings), users)
#選擇"ratings_with_genre" DataFrame 中的第一行數(shù)據(jù)。
ratings_with_genre.iloc[0]
#使用groupby()函數(shù)對(duì)"ratings_with_genre" DataFrame 按"genre"和"age"分組,并計(jì)算每個(gè)組中"rating"列的平均值。
genre_ratings = (ratings_with_genre.groupby(["genre", "age"])
["rating"].mean()#使用mean()函數(shù)計(jì)算每個(gè)分組的平均值
.unstack("age"))#使用unstack("age")將結(jié)果重塑為以"age"作為列索引的形式。
genre_ratings[:10]
age | 1 | 18 | 25 | 35 | 45 | 50 | 56 |
---|---|---|---|---|---|---|---|
genre | |||||||
Action | 3.506385 | 3.447097 | 3.453358 | 3.538107 | 3.528543 | 3.611333 | 3.610709 |
Adventure | 3.449975 | 3.408525 | 3.443163 | 3.515291 | 3.528963 | 3.628163 | 3.649064 |
Animation | 3.476113 | 3.624014 | 3.701228 | 3.740545 | 3.734856 | 3.780020 | 3.756233 |
Children's | 3.241642 | 3.294257 | 3.426873 | 3.518423 | 3.527593 | 3.556555 | 3.621822 |
Comedy | 3.497491 | 3.460417 | 3.490385 | 3.561984 | 3.591789 | 3.646868 | 3.650949 |
Crime | 3.710170 | 3.668054 | 3.680321 | 3.733736 | 3.750661 | 3.810688 | 3.832549 |
Documentary | 3.730769 | 3.865865 | 3.946690 | 3.953747 | 3.966521 | 3.908108 | 3.961538 |
Drama | 3.794735 | 3.721930 | 3.726428 | 3.782512 | 3.784356 | 3.878415 | 3.933465 |
Fantasy | 3.317647 | 3.353778 | 3.452484 | 3.482301 | 3.532468 | 3.581570 | 3.532700 |
Film-Noir | 4.145455 | 3.997368 | 4.058725 | 4.064910 | 4.105376 | 4.175401 | 4.125932 |
2.美國1880-2010年的嬰兒名字
美國社會(huì)保障局(SSA)提供了從1880年至現(xiàn)在的嬰兒姓名頻率的數(shù)據(jù)??梢允褂眠@些數(shù)據(jù)做很多事情:
根據(jù)給定的名字對(duì)嬰兒名字隨時(shí)間的比例進(jìn)行可視化
確定一個(gè)名字的相對(duì)排位
確定每年最受歡迎的名字,或者流行程度最高或最低的名字
接下來我們將結(jié)合代碼共同學(xué)習(xí)這一分析過程。本例題涉及以下知識(shí)點(diǎn),重要處會(huì)有解釋:
-
數(shù)據(jù)分組和聚合:通過使用
groupby()
函數(shù)對(duì)DataFrame進(jìn)行分組操作,可以根據(jù)指定的列對(duì)數(shù)據(jù)進(jìn)行分組。在代碼中,使用groupby()
函數(shù)按年份和性別進(jìn)行分組,并計(jì)算每個(gè)分組的出生人數(shù)總和。 -
數(shù)據(jù)排序和排名:通過使用
sort_values()
函數(shù)對(duì)DataFrame進(jìn)行排序操作,可以根據(jù)指定的列對(duì)數(shù)據(jù)進(jìn)行排序。在代碼中,使用sort_values()
函數(shù)對(duì)數(shù)據(jù)進(jìn)行降序排序,以獲取出生人數(shù)最多的姓名。 -
數(shù)據(jù)透視:通過使用
pivot_table()
函數(shù),可以對(duì)數(shù)據(jù)進(jìn)行透視操作,計(jì)算每個(gè)分組的匯總統(tǒng)計(jì)信息。在代碼中,使用透視表計(jì)算了按年份和性別分組的出生數(shù)總和,并將結(jié)果存儲(chǔ)在total_births
和table
這兩個(gè)DataFrame中。 -
數(shù)據(jù)可視化:使用Matplotlib庫的
plot()
函數(shù)對(duì)數(shù)據(jù)進(jìn)行可視化。代碼中使用折線圖和柱狀圖展示了不同年份和性別的出生人數(shù)、比例等信息。通過數(shù)據(jù)可視化可以更直觀地觀察數(shù)據(jù)的趨勢(shì)和分布情況。 -
數(shù)據(jù)處理和篩選:通過對(duì)DataFrame應(yīng)用函數(shù)、使用條件語句和基于特定列的篩選,可以對(duì)數(shù)據(jù)進(jìn)行處理和篩選。在代碼中,使用
apply()
函數(shù)、sort_values()
函數(shù)、isin()
函數(shù)等對(duì)數(shù)據(jù)進(jìn)行處理和篩選,以滿足特定的需求。
#在讀取時(shí),為列指定了列名為["name", "sex", "births"]。
names1880 = pd.read_csv("datasets/babynames/yob1880.txt",
names=["name", "sex", "births"])
names1880
name | sex | births | |
---|---|---|---|
0 | Mary | F | 7065 |
1 | Anna | F | 2604 |
2 | Emma | F | 2003 |
3 | Elizabeth | F | 1939 |
4 | Minnie | F | 1746 |
... | ... | ... | ... |
1995 | Woodie | M | 5 |
1996 | Worthy | M | 5 |
1997 | Wright | M | 5 |
1998 | York | M | 5 |
1999 | Zachariah | M | 5 |
#對(duì) names1880 DataFrame 進(jìn)行分組,按照性別("sex")進(jìn)行分組,并計(jì)算每個(gè)性別對(duì)應(yīng)的出生數(shù)("births" 列)的總和。
names1880.groupby("sex")["births"].sum()
sex F 90993 M 110493 Name: births, dtype: int64
Q:如何對(duì)數(shù)據(jù)進(jìn)行分組和聚合?
A:在數(shù)據(jù)分析中,經(jīng)常需要根據(jù)某個(gè)特定的列對(duì)數(shù)據(jù)進(jìn)行分組,并對(duì)每個(gè)分組進(jìn)行聚合操作,以計(jì)算統(tǒng)計(jì)指標(biāo)或得出結(jié)論。在本段代碼中,我們通過使用groupby()
函數(shù)按照年份和性別對(duì)數(shù)據(jù)進(jìn)行分組,然后使用sum()
函數(shù)計(jì)算每個(gè)分組的出生人數(shù)總和。這樣可以幫助我們理解和描述數(shù)據(jù)的整體趨勢(shì),比如年份和性別對(duì)出生人數(shù)的影響。
pieces = []
#代碼通過循環(huán)遍歷從1880年到2010年的文件,并將每個(gè)文件的內(nèi)容讀取為DataFrame
for year in range(1880, 2011):
path = f"datasets/babynames/yob{year}.txt"
frame = pd.read_csv(path, names=["name", "sex", "births"])
#為每個(gè)DataFrame添加一個(gè)名為"year"的列
frame["year"] = year
pieces.append(frame)
#用pd.concat()函數(shù)將所有DataFrame連接成一個(gè)單獨(dú)的DataFrame
names = pd.concat(pieces, ignore_index=True)
names#顯示該Frame
name | sex | births | year | |
---|---|---|---|---|
0 | Mary | F | 7065 | 1880 |
1 | Anna | F | 2604 | 1880 |
2 | Emma | F | 2003 | 1880 |
3 | Elizabeth | F | 1939 | 1880 |
4 | Minnie | F | 1746 | 1880 |
... | ... | ... | ... | ... |
1690779 | Zymaire | M | 5 | 2010 |
1690780 | Zyonne | M | 5 | 2010 |
1690781 | Zyquarius | M | 5 | 2010 |
1690782 | Zyran | M | 5 | 2010 |
1690783 | Zzyzx | M | 5 | 2010 |
#使用pivot_table()函數(shù)計(jì)算了按年份和性別分組的出生數(shù)總和
total_births = names.pivot_table("births", index="year",
columns="sex", aggfunc=sum)
#顯示total_births DataFrame 的最后幾行
total_births.tail()
#繪制了一個(gè)標(biāo)題為"Total births by sex and year"的出生數(shù)按年份和性別的折線圖。
total_births.plot(title="Total births by sex and year")
?
#定義了一個(gè)名為add_prop的函數(shù)。該函數(shù)接收一個(gè)分組,并為該分組計(jì)算一個(gè)名為"prop"的新列,表示每個(gè)名字在該年份和性別分組中的比例,每個(gè)名字的出生率
def add_prop(group):
group["prop"] = group["births"] / group["births"].sum()
return group
#將names DataFrame 按年份和性別分組,并對(duì)每個(gè)分組應(yīng)用add_prop函數(shù)
names = names.groupby(["year", "sex"], group_keys=False).apply(add_prop)
name | sex | births | year | prop | |
---|---|---|---|---|---|
0 | Mary | F | 7065 | 1880 | 0.077643 |
1 | Anna | F | 2604 | 1880 | 0.028618 |
2 | Emma | F | 2003 | 1880 | 0.022013 |
3 | Elizabeth | F | 1939 | 1880 | 0.021309 |
4 | Minnie | F | 1746 | 1880 | 0.019188 |
... | ... | ... | ... | ... | ... |
1690779 | Zymaire | M | 5 | 2010 | 0.000003 |
1690780 | Zyonne | M | 5 | 2010 | 0.000003 |
1690781 | Zyquarius | M | 5 | 2010 | 0.000003 |
1690782 | Zyran | M | 5 | 2010 | 0.000003 |
1690783 | Zzyzx | M | 5 | 2010 | 0.000003 |
#按照 "year" 和 "sex" 進(jìn)行分組,并計(jì)算每個(gè)組中的 "prop" 列的總和。
names.groupby(["year", "sex"])["prop"].sum()
year sex 1880 F 1.0 M 1.0 1881 F 1.0 M 1.0 1882 F 1.0 ... 2008 M 1.0 2009 F 1.0 M 1.0 2010 F 1.0 M 1.0 Name: prop, Length: 262, dtype: float64
#該函數(shù)接收一個(gè)分組,并按照 "births" 列(出生人數(shù))的降序?qū)Ψ纸M進(jìn)行排序,然后選擇排序結(jié)果中的前1000行
def get_top1000(group):
return group.sort_values("births", ascending=False)[:1000]
#按照 "year" 和 "sex" 進(jìn)行分組,并對(duì)每個(gè)分組應(yīng)用 get_top1000 函數(shù)
grouped = names.groupby(["year", "sex"])
top1000 = grouped.apply(get_top1000)
top1000.head()
name | sex | births | year | prop | |||
---|---|---|---|---|---|---|---|
year | sex | ||||||
1880 | F | 0 | Mary | F | 7065 | 1880 | 0.077643 |
1 | Anna | F | 2604 | 1880 | 0.028618 | ||
2 | Emma | F | 2003 | 1880 | 0.022013 | ||
3 | Elizabeth | F | 1939 | 1880 | 0.021309 | ||
4 | Minnie | F | 1746 | 1880 | 0.019188 |
#使用reset_index()函數(shù)對(duì)top1000 DataFrame 進(jìn)行重置索引,并丟棄原始索引。設(shè)置drop=True可以移除原始索引列,以便在重置索引后不保留它。
top1000 = top1000.reset_index(drop=True)
top1000.head()#顯示出生人數(shù)最多的前5名
name | sex | births | year | prop | |
---|---|---|---|---|---|
0 | Mary | F | 7065 | 1880 | 0.077643 |
1 | Anna | F | 2604 | 1880 | 0.028618 |
2 | Emma | F | 2003 | 1880 | 0.022013 |
3 | Elizabeth | F | 1939 | 1880 | 0.021309 |
4 | Minnie | F | 1746 | 1880 | 0.019188 |
#代碼根據(jù) "sex" 列的值將 top1000 DataFrame 分為男孩("M")和女孩("F")兩個(gè)子數(shù)據(jù)集。
boys = top1000[top1000["sex"] == "M"]
girls = top1000[top1000["sex"] == "F"]
#使用 pivot_table() 函數(shù)對(duì) top1000 DataFrame 進(jìn)行數(shù)據(jù)透視,計(jì)算了每個(gè)名字在不同年份下的出生數(shù)總和
total_births = top1000.pivot_table("births", index="year",
columns="name",
aggfunc=sum)
#碼使用 info() 方法打印出 total_births DataFrame 的信息,然后從中選擇了 "John"、"Harry"、"Mary" 和 "Marilyn" 四個(gè)名字的列,
#并繪制了一個(gè)子圖展示每年的出生數(shù)。
total_births.info()
#選擇這四個(gè)名字進(jìn)行繪制
subset = total_births[["John", "Harry", "Mary", "Marilyn"]]
#使用 plot() 方法對(duì) subset DataFrame 進(jìn)行繪圖,設(shè)置 subplots=True 以繪制子圖,figsize=(12, 10) 用于設(shè)置圖形的大小
subset.plot(subplots=True, figsize=(12, 10),
title="Number of births per year")
import matplotlib.pyplot as plt#創(chuàng)建一個(gè)新的畫布。
plt.figure()
#使用 pivot_table() 函數(shù)計(jì)算了 top1000 DataFrame 中 的出生率總和
table = top1000.pivot_table("prop", index="year",
columns="sex", aggfunc=sum)
#使用 plot() 方法繪制了一個(gè)折線圖,展示了每年男女出生率關(guān)系
table.plot(title="Sum of table1000.prop by year and sex",
yticks=np.linspace(0, 1.2, 13))
?
df = boys[boys["year"] == 2010]#2010年男孩出生人數(shù)表
df
name | sex | births | year | prop | |
---|---|---|---|---|---|
260877 | Jacob | M | 21875 | 2010 | 0.011523 |
260878 | Ethan | M | 17866 | 2010 | 0.009411 |
260879 | Michael | M | 17133 | 2010 | 0.009025 |
260880 | Jayden | M | 17030 | 2010 | 0.008971 |
260881 | William | M | 16870 | 2010 | 0.008887 |
... | ... | ... | ... | ... | ... |
261872 | Camilo | M | 194 | 2010 | 0.000102 |
261873 | Destin | M | 194 | 2010 | 0.000102 |
261874 | Jaquan | M | 194 | 2010 | 0.000102 |
261875 | Jaydan | M | 194 | 2010 | 0.000102 |
261876 | Maxton | M | 193 | 2010 | 0.000102 |
#對(duì) DataFrame 中的 "prop" 列進(jìn)行排序,并計(jì)算累計(jì)和。然后,展示了累計(jì)和的前10個(gè)值,
#并使用 searchsorted() 方法找到累計(jì)和達(dá)到 0.5 時(shí)的索引位置。
prop_cumsum = df["prop"].sort_values(ascending=False).cumsum()
prop_cumsum[:10]
prop_cumsum.searchsorted(0.5)
116
#從名為 boys 的 DataFrame 中選擇了年份為 1900 的數(shù)據(jù),并對(duì)該子數(shù)據(jù)集按 "prop" 列進(jìn)行降序排序。
#然后,計(jì)算累計(jì)和,并使用 searchsorted() 方法找到累計(jì)和達(dá)到 0.5 時(shí)的索引位置,最后加上 1。
df = boys[boys.year == 1900]
in1900 = df.sort_values("prop", ascending=False).prop.cumsum()
in1900.searchsorted(0.5) + 1
25
#定義了一個(gè)名為 get_quantile_count 的函數(shù)。該函數(shù)接收一個(gè)分組,并按照 "prop" 列的值進(jìn)行降序排序。然后,計(jì)算累計(jì)和,
#并使用 searchsorted() 方法找到累計(jì)和達(dá)到給定分位數(shù) q 時(shí)的位置,最后加上 1。
def get_quantile_count(group, q=0.5):
group = group.sort_values("prop", ascending=False)
return group.prop.cumsum().searchsorted(q) + 1
diversity = top1000.groupby(["year", "sex"]).apply(get_quantile_count)
diversity = diversity.unstack()
fig = plt.figure()
diversity.head()
#使用 plot() 方法繪制了一個(gè)圖表,標(biāo)題為 "Number of popular names in top 50%"。圖表展示了每個(gè)年份和性別組合中達(dá)到前50%的名字?jǐn)?shù)量。
diversity.plot(title="Number of popular names in top 50%")
#定義了一個(gè)名為 get_last_letter 的函數(shù)。該函數(shù)接收一個(gè)字符串 x,并返回字符串的最后一個(gè)字母。
def get_last_letter(x):
return x[-1]
#使用 map() 方法將 get_last_letter 函數(shù)應(yīng)用于 names DataFrame 的 "name" 列,將每個(gè)名字的最后一個(gè)字母提取出來
last_letters = names["name"].map(get_last_letter)
last_letters.name = "last_letter"
#使用 pivot_table() 函數(shù)對(duì) names DataFrame 進(jìn)行數(shù)據(jù)透視,計(jì)算每個(gè)年份和性別組合中,根據(jù)最后一個(gè)字母進(jìn)行分組的出生數(shù)總和
table = names.pivot_table("births", index=last_letters,
columns=["sex", "year"], aggfunc=sum)
#將展示按照特定年份(1910、1960 和 2010)的出生數(shù)數(shù)據(jù),并且按照性別和最后一個(gè)字母的分布。
subtable = table.reindex(columns=[1910, 1960, 2010], level="year")
subtable.head()
sex | F | M | ||||
---|---|---|---|---|---|---|
year | 1910 | 1960 | 2010 | 1910 | 1960 | 2010 |
last_letter | ||||||
a | 108376.0 | 691247.0 | 670605.0 | 977.0 | 5204.0 | 28438.0 |
b | NaN | 694.0 | 450.0 | 411.0 | 3912.0 | 38859.0 |
c | 5.0 | 49.0 | 946.0 | 482.0 | 15476.0 | 23125.0 |
d | 6750.0 | 3729.0 | 2607.0 | 22111.0 | 262112.0 | 44398.0 |
e | 133569.0 | 435013.0 | 313833.0 | 28655.0 | 178823.0 | 129012.0 |
#展示每個(gè)年份和性別組合中每個(gè)字母的比例,以及它們?cè)趯?duì)應(yīng)年份的出生數(shù)總和的占比。
subtable.sum()
letter_prop = subtable / subtable.sum()
letter_prop
sex | F | M | ||||
---|---|---|---|---|---|---|
year | 1910 | 1960 | 2010 | 1910 | 1960 | 2010 |
last_letter | ||||||
a | 0.273390 | 0.341853 | 0.381240 | 0.005031 | 0.002440 | 0.014980 |
b | NaN | 0.000343 | 0.000256 | 0.002116 | 0.001834 | 0.020470 |
c | 0.000013 | 0.000024 | 0.000538 | 0.002482 | 0.007257 | 0.012181 |
d | 0.017028 | 0.001844 | 0.001482 | 0.113858 | 0.122908 | 0.023387 |
e | 0.336941 | 0.215133 | 0.178415 | 0.147556 | 0.083853 | 0.067959 |
f | NaN | 0.000010 | 0.000055 | 0.000783 | 0.004325 | 0.001188 |
g | 0.000144 | 0.000157 | 0.000374 | 0.002250 | 0.009488 | 0.001404 |
h | 0.051529 | 0.036224 | 0.075852 | 0.045562 | 0.037907 | 0.051670 |
i | 0.001526 | 0.039965 | 0.031734 | 0.000844 | 0.000603 | 0.022628 |
j | NaN | NaN | 0.000090 | NaN | NaN | 0.000769 |
k | 0.000121 | 0.000156 | 0.000356 | 0.036581 | 0.049384 | 0.018541 |
l | 0.043189 | 0.033867 | 0.026356 | 0.065016 | 0.104904 | 0.070367 |
m | 0.001201 | 0.008613 | 0.002588 | 0.058044 | 0.033827 | 0.024657 |
n | 0.079240 | 0.130687 | 0.140210 | 0.143415 | 0.152522 | 0.362771 |
o | 0.001660 | 0.002439 | 0.001243 | 0.017065 | 0.012829 | 0.042681 |
p | 0.000018 | 0.000023 | 0.000020 | 0.003172 | 0.005675 | 0.001269 |
q | NaN | NaN | 0.000030 | NaN | NaN | 0.000180 |
r | 0.013390 | 0.006764 | 0.018025 | 0.064481 | 0.031034 | 0.087477 |
s | 0.039042 | 0.012764 | 0.013332 | 0.130815 | 0.102730 | 0.065145 |
t | 0.027438 | 0.015201 | 0.007830 | 0.072879 | 0.065655 | 0.022861 |
u | 0.000684 | 0.000574 | 0.000417 | 0.000124 | 0.000057 | 0.001221 |
v | NaN | 0.000060 | 0.000117 | 0.000113 | 0.000037 | 0.001434 |
w | 0.000020 | 0.000031 | 0.001182 | 0.006329 | 0.007711 | 0.016148 |
x | 0.000015 | 0.000037 | 0.000727 | 0.003965 | 0.001851 | 0.008614 |
y | 0.110972 | 0.152569 | 0.116828 | 0.077349 | 0.160987 | 0.058168 |
z | 0.002439 | 0.000659 | 0.000704 | 0.000170 | 0.000184 | 0.001831 |
import matplotlib.pyplot as plt
#使用 Matplotlib 庫繪制了一個(gè)包含兩個(gè)子圖的圖形窗口,每個(gè)子圖展示了不同性別的字母比例數(shù)據(jù)
fig, axes = plt.subplots(2, 1, figsize=(10, 8))
#在第一個(gè)子圖中繪制了一個(gè)垂直柱狀圖。kind="bar" 表示繪制柱狀圖,rot=0 表示不旋轉(zhuǎn) x 軸標(biāo)簽,ax=axes[0] 表示繪制在第一個(gè)子圖上,title="Male" 設(shè)置了子圖的標(biāo)題為 "Male",即男性。
letter_prop["M"].plot(kind="bar", rot=0, ax=axes[0], title="Male")
#在第二個(gè)子圖中繪制了一個(gè)垂直柱狀圖。kind="bar" 表示繪制柱狀圖,rot=0 表示不旋轉(zhuǎn) x 軸標(biāo)簽,ax=axes[1] 表示繪制在第二個(gè)子圖上,
#title="Female" 設(shè)置了子圖的標(biāo)題為 "Female",即女性。legend=False 表示不顯示圖例。
letter_prop["F"].plot(kind="bar", rot=0, ax=axes[1], title="Female",
legend=False)
plt.subplots_adjust(hspace=0.25) # 調(diào)整子圖之間的垂直間距
letter_prop = table / table.sum() # 計(jì)算每個(gè)字母在每年出生人數(shù)中的比例
dny_ts = letter_prop.loc[["d", "n", "y"], "M"].T # 從letter_prop中選擇字母"d", "n", "y"在男性出生人數(shù)中的比例,并進(jìn)行轉(zhuǎn)置操作
dny_ts.head() # 顯示dny_ts DataFrame的前幾行數(shù)據(jù)
last_letter | d | n | y |
---|---|---|---|
year | |||
1880 | 0.083055 | 0.153213 | 0.075760 |
1881 | 0.083247 | 0.153214 | 0.077451 |
1882 | 0.085340 | 0.149560 | 0.077537 |
1883 | 0.084066 | 0.151646 | 0.079144 |
1884 | 0.086120 | 0.149915 | 0.080405 |
plt.close("all") # 關(guān)閉所有打開的圖形窗口
fig = plt.figure() # 創(chuàng)建一個(gè)新的Figure對(duì)象
dny_ts.plot() # 對(duì)dny_ts DataFrame進(jìn)行折線圖的可視化
all_names = pd.Series(top1000["name"].unique()) # 從top1000 DataFrame的"name"列獲取唯一的姓名,并將結(jié)果存儲(chǔ)在all_names變量中
lesley_like = all_names[all_names.str.contains("Lesl")] # 選擇all_names中包含"Lesl"的姓名,并將結(jié)果賦值給lesley_like變量
lesley_like # 顯示lesley_like Series,即包含以"Lesl"開頭的姓名
632 Leslie 2294 Lesley 4262 Leslee 4728 Lesli 6103 Lesly dtype: object
filtered = top1000[top1000["name"].isin(lesley_like)] # 根據(jù)top1000 DataFrame中的"name"列與lesley_like中的姓名進(jìn)行匹配,篩選出匹配的行數(shù)據(jù),并將結(jié)果賦值給filtered變量
filtered.groupby("name")["births"].sum() # 對(duì)filtered DataFrame按姓名進(jìn)行分組,計(jì)算每個(gè)姓名的出生人數(shù)總和,并顯示結(jié)果
name Leslee 1082 Lesley 35022 Lesli 929 Leslie 370429 Lesly 10067 Name: births, dtype: int64
table = filtered.pivot_table("births", index="year", columns="sex", aggfunc="sum") # 根據(jù)年份和性別對(duì)filtered DataFrame進(jìn)行透視,計(jì)算每個(gè)年份和性別的出生人數(shù)總和,并將結(jié)果存儲(chǔ)在table變量中
table = table.div(table.sum(axis="columns"), axis="index") # 對(duì)table DataFrame進(jìn)行行歸一化,即每行的總和作為除數(shù),計(jì)算每個(gè)年份和性別的歸一化比例
table.tail() # 顯示table DataFrame的最后幾行數(shù)據(jù),即歸一化后的比例結(jié)果
sex | F | M |
---|---|---|
year | ||
2006 | 1.0 | NaN |
2007 | 1.0 | NaN |
2008 | 1.0 | NaN |
2009 | 1.0 | NaN |
2010 | 1.0 | NaN |
fig = plt.figure() # 創(chuàng)建一個(gè)新的Figure對(duì)象
table.plot(style={"M": "k-", "F": "k--"}) # 對(duì)table DataFrame進(jìn)行折線圖的可視化,男性使用黑色實(shí)線,女性使用黑色虛線
3.美國農(nóng)業(yè)部視頻數(shù)據(jù)庫
美國農(nóng)業(yè)部提供了食物營養(yǎng)信息數(shù)據(jù)庫。每種事務(wù)都有一些識(shí)別屬性以及兩份營養(yǎng)元素和營養(yǎng)比例的列表。這種形式的數(shù)據(jù)不適合分析,所以需要做一些工作將數(shù)據(jù)轉(zhuǎn)換成更好的形式。
接下來我們將結(jié)合代碼共同學(xué)習(xí)這一分析過程。本例題涉及以下知識(shí)點(diǎn),重要處會(huì)有代碼注釋:
-
創(chuàng)建和操作Pandas DataFrame:使用
pd.DataFrame()
函數(shù)創(chuàng)建Pandas DataFrame對(duì)象,使用head()
方法查看DataFrame的前幾行數(shù)據(jù),使用info()
方法查看DataFrame的基本信息。 -
數(shù)據(jù)篩選和計(jì)數(shù):使用
pd.value_counts()
函數(shù)對(duì)選定列中的每個(gè)唯一值進(jìn)行計(jì)數(shù)。 -
循環(huán)和列表操作:使用
for
循環(huán)遍歷列表中的每個(gè)元素,使用append()
方法將元素添加到列表中。 -
合并DataFrame:使用
pd.concat()
函數(shù)將多個(gè)DataFrame對(duì)象合并為一個(gè)大的DataFrame,使用merge()
函數(shù)基于指定的列將兩個(gè)DataFrame合并。 -
數(shù)據(jù)清洗:使用
drop_duplicates()
方法刪除重復(fù)的行。 -
列重命名:使用
rename()
方法重命名DataFrame的列名。 -
可視化:使用
matplotlib.pyplot
庫進(jìn)行可視化,使用plot()
方法繪制條形圖。 -
分組和聚合:使用
groupby()
方法對(duì)DataFrame進(jìn)行分組,并使用聚合函數(shù)計(jì)算每個(gè)分組的統(tǒng)計(jì)量。
import json
db = json.load(open("datasets/usda_food/database.json"))
# 計(jì)算對(duì)象db的長度,即列表中元素的數(shù)量
len(db)
# 獲取db列表中索引為0的元素的所有鍵
db[0].keys()
# 從db列表中索引為0的元素中獲取鍵為"nutrients"的值的列表,并返回列表中的第一個(gè)元素
db[0]["nutrients"][0]
# *注意*將db列表中索引為0的元素中的"nutrients"值轉(zhuǎn)換為Pandas DataFrame對(duì)象
nutrients = pd.DataFrame(db[0]["nutrients"])
# 顯示nutrients DataFrame的前7行數(shù)據(jù)
nutrients.head(7)
value | units | description | group | |
---|---|---|---|---|
0 | 25.18 | g | Protein | Composition |
1 | 29.20 | g | Total lipid (fat) | Composition |
2 | 3.06 | g | Carbohydrate, by difference | Composition |
3 | 3.28 | g | Ash | Other |
4 | 376.00 | kcal | Energy | Energy |
5 | 39.28 | g | Water | Composition |
6 | 1573.00 | kJ | Energy | Energy |
Q:為什么需要將db列表中索引為0的元素中的"nutrients"值轉(zhuǎn)換為Pandas DataFrame對(duì)象?
A:創(chuàng)建和操作Pandas DataFrame:nutrients = pd.DataFrame(db[0]["nutrients"])將db列表中索引為0的元素中的"nutrients"值轉(zhuǎn)換為Pandas DataFrame對(duì)象,并將其存儲(chǔ)在nutrients變量中。這樣我們可以使用Pandas提供的函數(shù)和方法對(duì)數(shù)據(jù)進(jìn)行處理和分析。nutrients.head(7)使用head()方法顯示nutrients DataFrame的前7行數(shù)據(jù)。
info_keys = ["description", "group", "id", "manufacturer"] # 包含要從數(shù)據(jù)庫中提取的信息的鍵的列表
info = pd.DataFrame(db, columns=info_keys) # 使用info_keys作為列名,創(chuàng)建包含db數(shù)據(jù)的Pandas DataFrame對(duì)象,并將其存儲(chǔ)在info變量中
info.head() # 顯示info DataFrame的前幾行數(shù)據(jù)
info.info() # 顯示info DataFrame的基本信息,包括列名、每列的非空值數(shù)量、每列的數(shù)據(jù)類型等
<class 'pandas.core.frame.DataFrame'> RangeIndex: 6636 entries, 0 to 6635 Data columns (total 4 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 description 6636 non-null object 1 group 6636 non-null object 2 id 6636 non-null int64 3 manufacturer 5195 non-null object dtypes: int64(1), object(3) memory usage: 207.5+ KB
pd.value_counts(info["group"])[:10]
'''
info["group"]:從DataFrame info 中選擇了名為 "group" 的列,該列包含了食物的分組信息。
pd.value_counts():對(duì)選定列中的每個(gè)唯一值進(jìn)行計(jì)數(shù),并返回計(jì)數(shù)結(jié)果。
[:10]:取計(jì)數(shù)結(jié)果中的前 10 個(gè)值,即返回出現(xiàn)次數(shù)最多的前 10 個(gè)分組
'''
Vegetables and Vegetable Products 812 Beef Products 618 Baked Products 496 Breakfast Cereals 403 Legumes and Legume Products 365 Fast Foods 365 Lamb, Veal, and Game Products 345 Sweets 341 Fruits and Fruit Juices 328 Pork Products 328 Name: group, dtype: int64
Q:如何進(jìn)行數(shù)據(jù)篩選和計(jì)數(shù)?
A:info_keys = ["description", "group", "id", "manufacturer"]定義了一個(gè)包含要從數(shù)據(jù)庫中提取的信息的鍵的列表。
info = pd.DataFrame(db, columns=info_keys)使用info_keys作為列名,創(chuàng)建包含db數(shù)據(jù)的Pandas DataFrame對(duì)象,并將其存儲(chǔ)在info變量中。
info.head()顯示info DataFrame的前幾行數(shù)據(jù)。info.info()顯示info DataFrame的基本信息,包括列名、每列的非空值數(shù)量、每列的數(shù)據(jù)類型等。
pd.value_counts(info["group"])[:10]對(duì)info["group"]列中的每個(gè)唯一值進(jìn)行計(jì)數(shù),并返回計(jì)數(shù)結(jié)果的前10個(gè)值,即返回出現(xiàn)次數(shù)最多的前10個(gè)分組。
nutrients = [] # 創(chuàng)建一個(gè)空列表用于存儲(chǔ)營養(yǎng)信息
for rec in db:
fnuts = pd.DataFrame(rec["nutrients"]) # 為每個(gè)記錄創(chuàng)建一個(gè)包含營養(yǎng)信息的DataFrame對(duì)象
fnuts["id"] = rec["id"] # 添加一個(gè)名為"id"的列,將記錄的id值賦給該列的每個(gè)元素
nutrients.append(fnuts) # 將每個(gè)記錄的營養(yǎng)信息DataFrame添加到nutrients列表中
nutrients = pd.concat(nutrients, ignore_index=True) # 將nutrients列表中的DataFrame對(duì)象合并為一個(gè)大的DataFrame,并重新索引行號(hào)
nutrients
value | units | description | group | id | |
---|---|---|---|---|---|
0 | 25.180 | g | Protein | Composition | 1008 |
1 | 29.200 | g | Total lipid (fat) | Composition | 1008 |
2 | 3.060 | g | Carbohydrate, by difference | Composition | 1008 |
3 | 3.280 | g | Ash | Other | 1008 |
4 | 376.000 | kcal | Energy | Energy | 1008 |
... | ... | ... | ... | ... | ... |
389350 | 0.000 | mcg | Vitamin B-12, added | Vitamins | 43546 |
389351 | 0.000 | mg | Cholesterol | Other | 43546 |
389352 | 0.072 | g | Fatty acids, total saturated | Other | 43546 |
389353 | 0.028 | g | Fatty acids, total monounsaturated | Other | 43546 |
389354 | 0.041 | g | Fatty acids, total polyunsaturated | Other | 43546 |
nutrients.duplicated().sum() # 統(tǒng)計(jì)重復(fù)行的數(shù)量
nutrients = nutrients.drop_duplicates() # 刪除重復(fù)的行
col_mapping = {"description" : "food",
"group" : "fgroup"}
info = info.rename(columns=col_mapping, copy=False) # 重命名info DataFrame的列名為food和fgroup
info.info() # 顯示info DataFrame的基本信息
col_mapping = {"description" : "nutrient",
"group" : "nutgroup"}
nutrients = nutrients.rename(columns=col_mapping, copy=False) # 重命名nutrients DataFrame的列名為nutrient和nutgroup
nutrients # 顯示重命名后的nutrients DataFrame
<class 'pandas.core.frame.DataFrame'> RangeIndex: 6636 entries, 0 to 6635 Data columns (total 4 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 food 6636 non-null object 1 fgroup 6636 non-null object 2 id 6636 non-null int64 3 manufacturer 5195 non-null object dtypes: int64(1), object(3) memory usage: 207.5+ KB
value | units | nutrient | nutgroup | id | |
---|---|---|---|---|---|
0 | 25.180 | g | Protein | Composition | 1008 |
1 | 29.200 | g | Total lipid (fat) | Composition | 1008 |
2 | 3.060 | g | Carbohydrate, by difference | Composition | 1008 |
3 | 3.280 | g | Ash | Other | 1008 |
4 | 376.000 | kcal | Energy | Energy | 1008 |
... | ... | ... | ... | ... | ... |
389350 | 0.000 | mcg | Vitamin B-12, added | Vitamins | 43546 |
389351 | 0.000 | mg | Cholesterol | Other | 43546 |
389352 | 0.072 | g | Fatty acids, total saturated | Other | 43546 |
389353 | 0.028 | g | Fatty acids, total monounsaturated | Other | 43546 |
389354 | 0.041 | g | Fatty acids, total polyunsaturated | Other | 43546 |
ndata = pd.merge(nutrients, info, on="id") # 基于"id"列將nutrients和info兩個(gè)DataFrame進(jìn)行合并,并將結(jié)果存儲(chǔ)在ndata中
ndata.info() # 顯示ndata DataFrame的基本信息
ndata.iloc[30000] # 獲取ndata DataFrame中索引為30000的行的數(shù)據(jù)
<class 'pandas.core.frame.DataFrame'> Int64Index: 375176 entries, 0 to 375175 Data columns (total 8 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 value 375176 non-null float64 1 units 375176 non-null object 2 nutrient 375176 non-null object 3 nutgroup 375176 non-null object 4 id 375176 non-null int64 5 food 375176 non-null object 6 fgroup 375176 non-null object 7 manufacturer 293054 non-null object dtypes: float64(1), int64(1), object(6) memory usage: 25.8+ MBvalue 0.04 units g nutrient Glycine nutgroup Amino Acids id 6158 food Soup, tomato bisque, canned, condensed fgroup Soups, Sauces, and Gravies manufacturer Name: 30000, dtype: object
fig = plt.figure() # 創(chuàng)建一個(gè)新的空白Figure對(duì)象,并將其賦值給變量fig
result = ndata.groupby(["nutrient", "fgroup"])["value"].quantile(0.5) # 根據(jù)"nutrient"和"fgroup"列進(jìn)行分組,計(jì)算"value"列的中位數(shù),并將結(jié)果存儲(chǔ)在result變量中
result["Zinc, Zn"].sort_values().plot(kind="barh") # 從result中選擇"Zinc, Zn"列的數(shù)據(jù),對(duì)數(shù)據(jù)進(jìn)行排序,然后使用水平條形圖進(jìn)行可視化
Q:如何進(jìn)行可視化?
A:在Python中,有多個(gè)庫可以用于數(shù)據(jù)可視化,下面是一些基本的可視化操作示例:
1.折線圖:使用matplotlib
庫可以創(chuàng)建折線圖來顯示數(shù)據(jù)的趨勢(shì)和變化:
import matplotlib.pyplot as plt
# 創(chuàng)建數(shù)據(jù)
x = [1, 2, 3, 4, 5]
y = [10, 15, 7, 12, 9]
# 繪制折線圖
plt.plot(x, y)
# 添加標(biāo)簽和標(biāo)題
plt.xlabel('X軸')
plt.ylabel('Y軸')
plt.title('折線圖')
# 顯示圖形
plt.show()
2.柱狀圖:柱狀圖常用于顯示不同類別之間的比較:
import matplotlib.pyplot as plt
# 創(chuàng)建數(shù)據(jù)
categories = ['A', 'B', 'C', 'D']
values = [10, 15, 7, 12]
# 繪制柱狀圖
plt.bar(categories, values)
# 添加標(biāo)簽和標(biāo)題
plt.xlabel('類別')
plt.ylabel('數(shù)值')
plt.title('柱狀圖')
# 顯示圖形
plt.show()
3.散點(diǎn)圖:散點(diǎn)圖用于顯示兩個(gè)變量之間的關(guān)系:
import matplotlib.pyplot as plt
# 創(chuàng)建數(shù)據(jù)
x = [1, 2, 3, 4, 5]
y = [10, 15, 7, 12, 9]
# 繪制散點(diǎn)圖
plt.scatter(x, y)
# 添加標(biāo)簽和標(biāo)題
plt.xlabel('X軸')
plt.ylabel('Y軸')
plt.title('散點(diǎn)圖')
# 顯示圖形
plt.show()
4.直方圖:直方圖用于顯示數(shù)據(jù)的分布情況:
import matplotlib.pyplot as plt
# 創(chuàng)建數(shù)據(jù)
data = [1, 2, 2, 3, 3, 3, 4, 4, 5]
# 繪制直方圖
plt.hist(data)
# 添加標(biāo)簽和標(biāo)題
plt.xlabel('數(shù)值')
plt.ylabel('頻數(shù)')
plt.title('直方圖')
# 顯示圖形
plt.show()
回到本例題:?
by_nutrient = ndata.groupby(["nutgroup", "nutrient"]) # 根據(jù)"nutgroup"和"nutrient"列進(jìn)行分組,將結(jié)果存儲(chǔ)在by_nutrient變量中
def get_maximum(x):
return x.loc[x.value.idxmax()] # 定義一個(gè)函數(shù)get_maximum,用于獲取每個(gè)分組中"value"列取得最大值的行
max_foods = by_nutrient.apply(get_maximum)[["value", "food"]] # 對(duì)每個(gè)分組應(yīng)用get_maximum函數(shù),獲取"value"列最大值所對(duì)應(yīng)的行,并選擇"value"和"food"兩列
max_foods["food"] = max_foods["food"].str[:50] # 將"food"列的字符串長度截取為最多50個(gè)字符
max_foods.loc["Amino Acids"]["food"] # 從 max_foods DataFrame 中選擇索引為 "Amino Acids" 的行,返回一個(gè)包含該行數(shù)據(jù)的 Series。從該 Series 中選擇名為 "food" 的列,返回 "Amino Acids" 分類下食物名稱的數(shù)據(jù)。
nutrient Alanine Gelatins, dry powder, unsweetened Arginine Seeds, sesame flour, low-fat Aspartic acid Soy protein isolate Cystine Seeds, cottonseed flour, low fat (glandless) Glutamic acid Soy protein isolate Glycine Gelatins, dry powder, unsweetened Histidine Whale, beluga, meat, dried (Alaska Native) Hydroxyproline KENTUCKY FRIED CHICKEN, Fried Chicken, ORIGINA... Isoleucine Soy protein isolate, PROTEIN TECHNOLOGIES INTE... Leucine Soy protein isolate, PROTEIN TECHNOLOGIES INTE... Lysine Seal, bearded (Oogruk), meat, dried (Alaska Na... Methionine Fish, cod, Atlantic, dried and salted Phenylalanine Soy protein isolate, PROTEIN TECHNOLOGIES INTE... Proline Gelatins, dry powder, unsweetened Serine Soy protein isolate, PROTEIN TECHNOLOGIES INTE... Threonine Soy protein isolate, PROTEIN TECHNOLOGIES INTE... Tryptophan Sea lion, Steller, meat with fat (Alaska Native) Tyrosine Soy protein isolate, PROTEIN TECHNOLOGIES INTE... Valine Soy protein isolate, PROTEIN TECHNOLOGIES INTE... Name: food, dtype: object
4.2012年聯(lián)邦選舉委員會(huì)數(shù)據(jù)庫
美國聯(lián)邦選舉委員會(huì)公布了有關(guān)政治運(yùn)動(dòng)貢獻(xiàn)的數(shù)據(jù)。這些數(shù)據(jù)包括捐贈(zèng)者姓名、職業(yè)和雇主、地址和繳費(fèi)金額。你可以嘗試做以下分析:
1.按職業(yè)和雇主的捐贈(zèng)統(tǒng)計(jì);2.按捐贈(zèng)金額統(tǒng)計(jì);3.按州進(jìn)行統(tǒng)計(jì)。
接下來我們將結(jié)合代碼共同學(xué)習(xí)這一分析過程。本例題涉及以下知識(shí)點(diǎn),重要處會(huì)有解釋:
-
獲取唯一值:
fec["cand_nm"].unique()
從fec
DataFrame的"cand_nm"列獲取唯一的候選人姓名,并將結(jié)果存儲(chǔ)在unique_cands
變量中。 -
數(shù)據(jù)分組:
grouped = fec.groupby("cand_nm")
根據(jù)候選人姓名對(duì)fec
DataFrame進(jìn)行分組。 -
數(shù)據(jù)透視表:
by_occupation = fec.pivot_table("contb_receipt_amt", index="contbr_occupation", columns="party", aggfunc="sum")
使用pivot_table()
函數(shù)創(chuàng)建數(shù)據(jù)透視表,對(duì)"contb_receipt_amt"列進(jìn)行求和聚合,以"contbr_occupation"為行索引,以"party"為列索引。 -
可視化:
over_2mm.plot(kind="barh")
對(duì)DataFrame進(jìn)行可視化,例如水平條形圖。 -
數(shù)據(jù)映射:使用字典對(duì)列中的值進(jìn)行映射,例如
fec["contbr_occupation"].map(get_occ)
使用自定義函數(shù)get_occ
將"contbr_occupation"列中的值進(jìn)行映射。 -
數(shù)據(jù)堆疊和展開:
grouped.size().unstack(level=0)
計(jì)算每個(gè)候選人在不同區(qū)間標(biāo)簽下的數(shù)據(jù)量,并將結(jié)果轉(zhuǎn)換為寬格式,以候選人姓名為列。 -
數(shù)據(jù)透視表和缺失值填充:
totals = grouped["contb_receipt_amt"].sum().unstack(level=0).fillna(0)
計(jì)算每個(gè)候選人在不同州的總捐款金額,將結(jié)果轉(zhuǎn)換為寬格式,并用0填充缺失值。 -
數(shù)據(jù)歸一化和比例計(jì)算:
percent = totals.div(totals.sum(axis="columns"), axis="index")
對(duì)每個(gè)州的總捐款金額進(jìn)行歸一化,以每行的總和作為除數(shù),計(jì)算歸一化后的比例。
fec = pd.read_csv("datasets/fec/P00000001-ALL.csv", low_memory=False) # 從CSV文件中讀取數(shù)據(jù),并將結(jié)果存儲(chǔ)在fec變量中,low_memory參數(shù)設(shè)置為False以確保讀取所有數(shù)據(jù)
fec.info() # 顯示fec DataFrame的基本信息
fec.iloc[123456] # 獲取fec DataFrame中索引為123456的行的數(shù)據(jù)
<class 'pandas.core.frame.DataFrame'> RangeIndex: 1001731 entries, 0 to 1001730 Data columns (total 16 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 cmte_id 1001731 non-null object 1 cand_id 1001731 non-null object 2 cand_nm 1001731 non-null object 3 contbr_nm 1001731 non-null object 4 contbr_city 1001712 non-null object 5 contbr_st 1001727 non-null object 6 contbr_zip 1001620 non-null object 7 contbr_employer 988002 non-null object 8 contbr_occupation 993301 non-null object 9 contb_receipt_amt 1001731 non-null float64 10 contb_receipt_dt 1001731 non-null object 11 receipt_desc 14166 non-null object 12 memo_cd 92482 non-null object 13 memo_text 97770 non-null object 14 form_tp 1001731 non-null object 15 file_num 1001731 non-null int64 dtypes: float64(1), int64(1), object(14) memory usage: 122.3+ MBcmte_id C00431445 cand_id P80003338 cand_nm Obama, Barack contbr_nm ELLMAN, IRA contbr_city TEMPE contbr_st AZ contbr_zip 852816719 contbr_employer ARIZONA STATE UNIVERSITY contbr_occupation PROFESSOR contb_receipt_amt 50.0 contb_receipt_dt 01-DEC-11 receipt_desc NaN memo_cd NaN memo_text NaN form_tp SA17A file_num 772372 Name: 123456, dtype: object
unique_cands = fec["cand_nm"].unique() # 從fec DataFrame的"cand_nm"列獲取唯一的候選人姓名,將結(jié)果存儲(chǔ)在unique_cands變量中
unique_cands # 顯示unique_cands數(shù)組,即唯一的候選人姓名列表
unique_cands[2] # 獲取unique_cands數(shù)組中索引為2的元素,即第三個(gè)候選人的姓名
parties = {"Bachmann, Michelle": "Republican",
"Cain, Herman": "Republican",
"Gingrich, Newt": "Republican",
"Huntsman, Jon": "Republican",
"Johnson, Gary Earl": "Republican",
"McCotter, Thaddeus G": "Republican",
"Obama, Barack": "Democrat",
"Paul, Ron": "Republican",
"Pawlenty, Timothy": "Republican",
"Perry, Rick": "Republican",
"Roemer, Charles E. 'Buddy' III": "Republican",
"Romney, Mitt": "Republican",
"Santorum, Rick": "Republican"}
# 設(shè)置黨派
fec["cand_nm"][123456:123461] # 獲取fec DataFrame中"cand_nm"列索引為123456到123460的行的數(shù)據(jù)
fec["cand_nm"][123456:123461].map(parties) # 對(duì)索引為123456到123460的"cand_nm"列的數(shù)據(jù)應(yīng)用parties字典,將候選人姓名映射為對(duì)應(yīng)的黨派
fec["party"] = fec["cand_nm"].map(parties) # 將通過parties字典映射后的黨派信息添加為fec DataFrame的一個(gè)新列,列名為"party"
fec["party"].value_counts() # 統(tǒng)計(jì)"party"列中每個(gè)黨派的數(shù)量,并返回計(jì)數(shù)結(jié)果
Democrat 593746 Republican 407985 Name: party, dtype: int64
(fec["contb_receipt_amt"] > 0).value_counts() # 統(tǒng)計(jì)"contb_receipt_amt"列中大于0的值的數(shù)量和小于等于0的值的數(shù)量
True 991475 False 10256 Name: contb_receipt_amt, dtype: int64
fec = fec[fec["contb_receipt_amt"] > 0] # 從fec DataFrame中篩選出"contb_receipt_amt"列大于0的行,并將結(jié)果重新賦值給fec變量
fec_mrbo = fec[fec["cand_nm"].isin(["Obama, Barack", "Romney, Mitt"])] # 從fec DataFrame中篩選出"cand_nm"列包含"Obama, Barack"或"Romney, Mitt"的行,并將結(jié)果賦值給fec_mrbo變量
fec["contbr_occupation"].value_counts()[:10] # 統(tǒng)計(jì)"contbr_occupation"列中各個(gè)職業(yè)的數(shù)量,并返回前10個(gè)結(jié)果
RETIRED 233990 INFORMATION REQUESTED 35107 ATTORNEY 34286 HOMEMAKER 29931 PHYSICIAN 23432 INFORMATION REQUESTED PER BEST EFFORTS 21138 ENGINEER 14334 TEACHER 13990 CONSULTANT 13273 PROFESSOR 12555 Name: contbr_occupation, dtype: int64
occ_mapping = {
"INFORMATION REQUESTED PER BEST EFFORTS" : "NOT PROVIDED",
"INFORMATION REQUESTED" : "NOT PROVIDED",
"INFORMATION REQUESTED (BEST EFFORTS)" : "NOT PROVIDED",
"C.E.O.": "CEO"
} # 映射 “前” 為 “后”
def get_occ(x):
# 如果映射未提供,則返回 x
return occ_mapping.get(x, x)
fec["contbr_occupation"] = fec["contbr_occupation"].map(get_occ) # 使用 get_occ 函數(shù)將 "contbr_occupation" 列中的值進(jìn)行映射
emp_mapping = {
"INFORMATION REQUESTED PER BEST EFFORTS" : "NOT PROVIDED",
"INFORMATION REQUESTED" : "NOT PROVIDED",
"SELF" : "SELF-EMPLOYED",
"SELF EMPLOYED" : "SELF-EMPLOYED",
} # 映射 “前” 為 “后”
def get_emp(x):
# 如果映射未提供,則返回 x
return emp_mapping.get(x, x)
fec["contbr_employer"] = fec["contbr_employer"].map(get_emp) # 使用 get_emp 函數(shù)將 "contbr_employer" 列中的值進(jìn)行映射
by_occupation = fec.pivot_table("contb_receipt_amt", # 使用"contb_receipt_amt"列作為值進(jìn)行透視
index="contbr_occupation", # 使用"contbr_occupation"列作為行索引
columns="party", # 使用"party"列作為列索引
aggfunc="sum") # 對(duì)值進(jìn)行求和聚合
over_2mm = by_occupation[by_occupation.sum(axis="columns") > 2000000] # 選擇總和大于2000000的行并賦值給over_2mm變量
over_2mm # 顯示over_2mm DataFrame
party | Democrat | Republican |
---|---|---|
contbr_occupation | ||
ATTORNEY | 11141982.97 | 7477194.43 |
CEO | 2074974.79 | 4211040.52 |
CONSULTANT | 2459912.71 | 2544725.45 |
ENGINEER | 951525.55 | 1818373.70 |
EXECUTIVE | 1355161.05 | 4138850.09 |
HOMEMAKER | 4248875.80 | 13634275.78 |
INVESTOR | 884133.00 | 2431768.92 |
LAWYER | 3160478.87 | 391224.32 |
MANAGER | 762883.22 | 1444532.37 |
NOT PROVIDED | 4866973.96 | 20565473.01 |
OWNER | 1001567.36 | 2408286.92 |
PHYSICIAN | 3735124.94 | 3594320.24 |
PRESIDENT | 1878509.95 | 4720923.76 |
PROFESSOR | 2165071.08 | 296702.73 |
REAL ESTATE | 528902.09 | 1625902.25 |
RETIRED | 25305116.38 | 23561244.49 |
SELF-EMPLOYED | 672393.40 | 1640252.54 |
plt.figure() # 創(chuàng)建一個(gè)新的空白Figure對(duì)象
over_2mm.plot(kind="barh") # 對(duì)over_2mm DataFrame進(jìn)行水平條形圖的可視化
def get_top_amounts(group, key, n=5):
totals = group.groupby(key)["contb_receipt_amt"].sum() # 對(duì)group中的數(shù)據(jù)按key進(jìn)行分組,計(jì)算每個(gè)組中"contb_receipt_amt"列的總和
return totals.nlargest(n) # 返回總和最大的前n個(gè)組
grouped = fec_mrbo.groupby("cand_nm") # 根據(jù)候選人姓名對(duì)fec_mrbo DataFrame進(jìn)行分組
grouped.apply(get_top_amounts, "contbr_occupation", n=7) # 對(duì)分組后的數(shù)據(jù)應(yīng)用get_top_amounts函數(shù),按"contbr_occupation"列獲取每個(gè)組的前7個(gè)最大總和
grouped.apply(get_top_amounts, "contbr_employer", n=10) # 對(duì)分組后的數(shù)據(jù)應(yīng)用get_top_amounts函數(shù),按"contbr_employer"列獲取每個(gè)組的前10個(gè)最大總和
cand_nm contbr_employer Obama, Barack RETIRED 22694358.85 SELF-EMPLOYED 17080985.96 NOT EMPLOYED 8586308.70 INFORMATION REQUESTED 5053480.37 HOMEMAKER 2605408.54 SELF 1076531.20 SELF EMPLOYED 469290.00 STUDENT 318831.45 VOLUNTEER 257104.00 MICROSOFT 215585.36 Romney, Mitt INFORMATION REQUESTED PER BEST EFFORTS 12059527.24 RETIRED 11506225.71 HOMEMAKER 8147196.22 SELF-EMPLOYED 7409860.98 STUDENT 496490.94 CREDIT SUISSE 281150.00 MORGAN STANLEY 267266.00 GOLDMAN SACH & CO. 238250.00 BARCLAYS CAPITAL 162750.00 H.I.G. CAPITAL 139500.00 Name: contb_receipt_amt, dtype: float64
bins = np.array([0, 1, 10, 100, 1000, 10000, 100_000, 1_000_000, 10_000_000]) # 定義一個(gè)包含分箱邊界值的NumPy數(shù)組,用于將"contb_receipt_amt"列的值分成不同的區(qū)間
labels = pd.cut(fec_mrbo["contb_receipt_amt"], bins) # 使用pd.cut函數(shù)根據(jù)指定的分箱邊界將"contb_receipt_amt"列的值進(jìn)行分箱,并返回一個(gè)包含對(duì)應(yīng)區(qū)間標(biāo)簽的Series
labels # 顯示labels Series,即包含了每個(gè)"contb_receipt_amt"值所屬的區(qū)間標(biāo)簽
411 (10, 100] 412 (100, 1000] 413 (100, 1000] 414 (10, 100] 415 (10, 100] ... 701381 (10, 100] 701382 (100, 1000] 701383 (1, 10] 701384 (10, 100] 701385 (100, 1000] Name: contb_receipt_amt, Length: 694282, dtype: category Categories (8, interval[int64, right]): [(0, 1] < (1, 10] < (10, 100] < (100, 1000] < (1000, 10000] < (10000, 100000] < (100000, 1000000] < (1000000, 10000000]]
grouped = fec_mrbo.groupby(["cand_nm", labels]) # 根據(jù)候選人姓名和labels對(duì)fec_mrbo DataFrame進(jìn)行分組
grouped.size().unstack(level=0) # 計(jì)算每個(gè)候選人在不同區(qū)間標(biāo)簽下的數(shù)據(jù)量,并將結(jié)果轉(zhuǎn)換為寬格式(以候選人姓名為列),并顯示該結(jié)果
cand_nm | Obama, Barack | Romney, Mitt |
---|---|---|
contb_receipt_amt | ||
(0, 1] | 493 | 77 |
(1, 10] | 40070 | 3681 |
(10, 100] | 372280 | 31853 |
(100, 1000] | 153991 | 43357 |
(1000, 10000] | 22284 | 26186 |
(10000, 100000] | 2 | 1 |
(100000, 1000000] | 3 | 0 |
(1000000, 10000000] | 4 |
plt.figure() # 創(chuàng)建一個(gè)新的空白Figure對(duì)象
bucket_sums = grouped["contb_receipt_amt"].sum().unstack(level=0) # 計(jì)算每個(gè)候選人在不同區(qū)間標(biāo)簽下的"contb_receipt_amt"列的總和,并轉(zhuǎn)換為寬格式(以候選人姓名為列)
normed_sums = bucket_sums.div(bucket_sums.sum(axis="columns"), axis="index") # 對(duì)每個(gè)候選人在不同區(qū)間標(biāo)簽下的總和進(jìn)行歸一化,以每行的總和作為除數(shù),計(jì)算歸一化后的比例
normed_sums # 顯示歸一化后的比例結(jié)果
normed_sums[:-2].plot(kind="barh") # 對(duì)前面除去最后兩行的歸一化比例結(jié)果進(jìn)行水平條形圖的可視化
grouped = fec_mrbo.groupby(["cand_nm", "contbr_st"]) # 根據(jù)候選人姓名和捐贈(zèng)者所在州(contbr_st)對(duì)fec_mrbo DataFrame進(jìn)行分組
totals = grouped["contb_receipt_amt"].sum().unstack(level=0).fillna(0) # 計(jì)算每個(gè)候選人在不同州的總捐款金額,將結(jié)果轉(zhuǎn)換為寬格式(以候選人姓名為列),并用0填充缺失值
totals = totals[totals.sum(axis="columns") > 100000] # 篩選出總捐款金額超過100000的行
totals.head(10) # 顯示前10行的totals DataFrame
cand_nm | Obama, Barack | Romney, Mitt |
---|---|---|
contbr_st | ||
AK | 281840.15 | 86204.24 |
AL | 543123.48 | 527303.51 |
AR | 359247.28 | 105556.00 |
AZ | 1506476.98 | 1888436.23 |
CA | 23824984.24 | 11237636.60 |
CO | 2132429.49 | 1506714.12 |
CT | 2068291.26 | 3499475.45 |
DC | 4373538.80 | 1025137.50 |
DE | 336669.14 | 82712.00 |
FL | 7318178.58 | 8338458.81 |
percent = totals.div(totals.sum(axis="columns"), axis="index") # 對(duì)每個(gè)州的總捐款金額進(jìn)行歸一化,以每行的總和作為除數(shù),計(jì)算歸一化后的比例
percent.head(10) # 顯示前10行的percent DataFrame,即每個(gè)州的歸一化比例結(jié)果
cand_nm | Obama, Barack | Romney, Mitt |
---|---|---|
contbr_st | ||
AK | 0.765778 | 0.234222 |
AL | 0.507390 | 0.492610 |
AR | 0.772902 | 0.227098 |
AZ | 0.443745 | 0.556255 |
CA | 0.679498 | 0.320502 |
CO | 0.585970 | 0.414030 |
CT | 0.371476 | 0.628524 |
DC | 0.810113 | 0.189887 |
DE | 0.802776 | 0.197224 |
FL | 0.467417 | 0.532583 |
Q:什么是數(shù)據(jù)歸一化和比例計(jì)算?
A:數(shù)據(jù)歸一化(Data normalization)是一種常用的數(shù)據(jù)預(yù)處理技術(shù),用于將不同特征或變量的取值范圍進(jìn)行統(tǒng)一,使其具有相同的尺度或比例。數(shù)據(jù)歸一化的目的是消除不同特征之間的量綱差異,以便更好地進(jìn)行數(shù)據(jù)分析和建模。
在上述代碼中,我們對(duì)每個(gè)州的總捐款金額進(jìn)行了歸一化和比例計(jì)算:
首先對(duì)每行的數(shù)據(jù)進(jìn)行求和,計(jì)算每個(gè)州的總捐款金額。使用`div()`函數(shù)將每個(gè)州的總捐款金額除以每行的總和。這樣做的目的是將每個(gè)州的總捐款金額歸一化,并計(jì)算出每個(gè)州的捐款金額占總捐款金額的比例。
????????`totals.sum(axis="columns")`表示沿著行方向進(jìn)行求和。
????????`axis="index"`表示將每行的總和作為除數(shù)。文章來源:http://www.zghlxwxcb.cn/news/detail-580076.html
最后顯示歸一化和比例計(jì)算后的結(jié)果,即每個(gè)州的歸一化比例結(jié)果。文章來源地址http://www.zghlxwxcb.cn/news/detail-580076.html
到了這里,關(guān)于【Pandas】四個(gè)例子掌握用Python進(jìn)行數(shù)據(jù)分析!一看就懂!的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!