前言
我们提供了四个数据集供大家学习,分别是:
1.MoviesLens 1M数据集
2.美国1880-2010年的婴儿名字
3.美国农业部视频数据库
4.2012年联邦选举委员会数据库
大家可以根据自己的兴趣进行选择阅读,关于数据以及jupyter notebook笔记包,大家可以点击这里下载链接:点击这里
1.MoviesLens 1M数据集
GroupLens实验室提供了一些从MoviesLens用户那里收集的20世纪90年代末到21世纪初的电影评分数据的集合。这些数据提供了电影的评分、流派、年份和观众数据(年龄、邮编、性别、职业)。 MovisLens1M数据集包含6000个用户对4000部电影的100万个评分。数据分布在三个表格之中:分别包含评分、用户信息和电影信息。
首先我们使用 pandas 读取 "movielens" 数据集的三个文件:users.dat、ratings.dat 和 movies.dat
import pandas as pd
unames = ["user_id", "gender", "age", "occupation", "zip"]
users = pd.read_csv("datasets/movielens/users.dat", sep="::",
header=None, names=unames, engine="python")
rnames = ["user_id", "movie_id", "rating", "timestamp"]
ratings = pd.read_csv("datasets/movielens/ratings.dat", sep="::",
header=None, names=rnames, engine="python")
mnames = ["movie_id", "title", "genres"]
movies = pd.read_csv("datasets/movielens/movies.dat", sep="::",
header=None, names=mnames, engine="python")
首先我们了解一下head函数,head() 函数对于快速查看数据框的开头几行非常有用,特别是在处理大型数据集时,可以帮助您了解数据的结构和格式。通过查看数据集的前几行,您可以获得关于数据列的名称、数据值的类型以及可能的缺失值等信息
# 打印 users 数据集的前5行
print(users.head(5))
# 打印 ratings 数据集的前5行
print(ratings.head(5))
# 打印 movies 数据集的前5行
print(movies.head(5))
接下来为了方便数据的处理,我们使用 pd.merge()
函数将 ratings
和 users
数据集按照共同的列(例如 user_id
)进行合并,然后再将合并后的结果与 movies
数据集按照共同的列(例如 movie_id
)进行合并。
接下来,通过 data
变量打印了合并后的数据集。这将显示合并后的数据集中的所有行和列。
如果想要访问合并后数据集的第一行,可以使用 iloc
属性,通过索引 0 来获取第一行的数据
#使用pd.merge()函数将ratings、users和movies三个DataFrame合并
data = pd.merge(pd.merge(ratings, users), movies)
#输出data DataFrame合并后的所有数据
data
#输出data DataFrame中的第一行数据
data.iloc[0]
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() 函数对合并后的数据集 data 进行数据透视,以计算不同电影标题(title)在不同性别(gender)下的平均评分。
mean_ratings = data.pivot_table("rating", index="title",
columns="gender", aggfunc="mean")
mean_ratings.head(5)
这段代码将返回一个新的数据集 mean_ratings
,其中每一行表示一个电影标题(title),每一列表示一个性别(gender),对应的值为该电影在该性别下的平均评分。
通过调用 head(5)
方法,代码展示了 mean_ratings
数据集的前 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 |
使用 groupby()
函数将数据集 data
按照电影标题(title
)进行分组,然后使用 size()
方法计算每个电影标题对应的评分数量。
# 根据电影标题对评分数据进行分组,并计算每个电影标题的评分数量
ratings_by_title = data.groupby("title").size()
ratings_by_title.head()
# 输出ratings_by_title数据集的前5行,显示每个电影标题对应的评分数量
title $1,000,000 Duck (1971) 37 'Night Mother (1986) 70 'Til There Was You (1997) 52 'burbs, The (1989) 303 ...And Justice for All (1979) 199 dtype: int64
# 筛选出评分数量大于等于250的活跃电影标题
active_titles = ratings_by_title.index[ratings_by_title >= 250]
#打印这些标题
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)
我们使用mean_ratings.loc[active_titles]
从 mean_ratings
数据集中选择出活跃电影标题对应的行。创建新的数据集
#返回一个新的数据集 mean_ratings,其中只包含活跃电影标题对应的行和相应的列(不同性别的平均评分)
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 |
mean_ratings.rename()
用于重命名 mean_ratings
数据集的索引
#使用rename()函数将mean_ratings DataFrame 中的索引标签从"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)"})
通过执行这段代码,可以更新 mean_ratings
数据集中的特定电影标题索引,以便更准确地匹配其他数据集或进行更清晰的分析。
使用mean_ratings.sort_values("F", ascending=False)
对 mean_ratings
数据集按照 "F" 列(女性评分)进行降序排序。
这段代码会返回一个新的数据集 top_female_ratings
,其中包含了按照女性评分降序排列的电影标题,并显示前几行结果。
#使用sort_values()函数根据女性观众的平均评分("F"列)对mean_ratings DataFrame 进行降序排序
top_female_ratings = mean_ratings.sort_values("F", ascending=False)
top_female_ratings.head()
gender | F | M |
---|---|---|
title | ||
Close Shave, A (1995) | 4.644444 | 4.473795 |
Wrong Trousers, The (1993) | 4.588235 | 4.478261 |
Sunset Blvd. (a.k.a. Sunset Boulevard) (1950) | 4.572650 | 4.464589 |
Wallace & Gromit: The Best of Aardman Animation (1996) | 4.563107 | 4.385075 |
Schindler's List (1993) | 4.562602 | 4.491415 |
执行这段代码,您可以获取在女性观众中评分最高的电影,并查看它们的平均评分。
在 mean_ratings
数据集中创建一个名为 "diff" 的新列。该列包含了每部电影的男性评分与女性评分之间的差异。
#创建一个新列diff,表示男女评分的差值
mean_ratings["diff"] = mean_ratings["M"] - mean_ratings["F"]
#打印数据集
mean_ratings
通过执行这段代码,您可以计算出每部电影男性评分和女性评分之间的差异,并将其保存在名为 "diff" 的新列中。
gender | F | M | diff |
---|---|---|---|
title | |||
$1,000,000 Duck (1971) | 3.375000 | 2.761905 | -0.613095 |
'Night Mother (1986) | 3.388889 | 3.352941 | -0.035948 |
'Til There Was You (1997) | 2.675676 | 2.733333 | 0.057658 |
'burbs, The (1989) | 2.793478 | 2.962085 | 0.168607 |
...And Justice for All (1979) | 3.828571 | 3.689024 | -0.139547 |
... | ... | ... | ... |
Zed & Two Noughts, A (1985) | 3.500000 | 3.380952 | -0.119048 |
Zero Effect (1998) | 3.864407 | 3.723140 | -0.141266 |
Zero Kelvin (Kjærlighetens kjøtere) (1995) | NaN | 3.500000 | NaN |
Zeus and Roxanne (1997) | 2.777778 | 2.357143 | -0.420635 |
eXistenZ (1999) | 3.098592 | 3.289086 | 0.190494 |
按照升序对数据集排列
#使用sort_values()函数根据差异值("diff"列)对mean_ratings DataFrame 进行升序排序
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]对sorted_by_diff DataFrame 进行逆序排序,并返回前5行内容。
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()函数按电影标题(title)分组,并计算每个电影标题对应的评分标准差。
rating_std_by_title = data.groupby("title")["rating"].std()
#从标准差结果中筛选出评分数大于等于250的活跃电影标题,
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()函数将rating_std_by_title Series 对象按评分标准差进行降序排序,并返回前10个最大的标准差值。
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行数据
movies["genres"].head()
#将每个电影的"genres"列按竖线字符分割成一个列表
movies["genres"].head().str.split("|")
#将分割后的列表赋值给了一个名为"genre"的新列,并删除了原始的"genres"列。这样,"genre"列包含了每个电影的类型列表。
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] |
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()
方法将 movies_exploded
、ratings
和 users
数据框进行合并,得到名为 ratings_with_genre
的新数据框。这个新的数据框包含了电影的详细信息、评分信息和用户信息。
接下来,使用 .iloc[0]
选择了 ratings_with_genre
数据框中的第一行数据,并进行了打印显示
#使用pd.merge()函数将"movies_exploded"、"ratings"和"users"三个DataFrame进行合并,创建一个名为"ratings_with_genre"的新DataFrame。
ratings_with_genre = pd.merge(pd.merge(movies_exploded, ratings), users)
#选择"ratings_with_genre" DataFrame 中的第一行数据。
ratings_with_genre.iloc[0]
movie_id 1 title Toy Story (1995) genre Animation user_id 1 rating 5 timestamp 978824268 gender F age 1 occupation 10 zip 48067 Name: 0, dtype: object
通过使用 .groupby()
方法按照 "genre" 和 "age" 列进行分组,计算了每个电影类型在不同年龄段的平均评分,并使用 .unstack("age")
方法对结果进行了重塑,得到一个包含电影类型为索引、年龄段为列的新数据框 genre_ratings
。
最后,使用切片操作 [:10]
显示 genre_ratings
数据框的前10行内容,其中包含了每个电影类型在不同年龄段的平均评分。
#使用groupby()函数对"ratings_with_genre" DataFrame 按"genre"和"age"分组,并计算每个组中"rating"列的平均值。
genre_ratings = (ratings_with_genre.groupby(["genre", "age"])
["rating"].mean()#使用mean()函数计算每个分组的平均值
.unstack("age"))#使用unstack("age")将结果重塑为以"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 |
MoviesLens 1M数据集的案例就介绍到这里了
2.美国1880-2010年的婴儿名字
美国社会保障局(SSA)提供了从1880年至现在的婴儿姓名频率的数据。可以使用这些数据做很多事情:
根据给定的名字对婴儿名字随时间的比例进行可视化
确定一个名字的相对排位
确定每年最受欢迎的名字,或者流行程度最高或最低的名字
下面进入代码实例
首先使用 pd.read_csv()
方法读取了名为 "yob1880.txt" 的文件,并将其存储为名为 names1880
的 pandas 数据框。
在读取文件时,指定列名,将第一列命名为 "name",第二列命名为 "sex",第三列命名为 "births"。
这样,您就创建了一个包含 "name"、"sex" 和 "births" 列的数据框 names1880
,其中每一行代表了一个在1880年出生的婴儿的信息。
#在读取时,为列指定了列名为["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 |
对 names1880
数据框按照性别进行分组,并计算每个性别的出生人数总和
#对 names1880 DataFrame 进行分组,按照性别("sex")进行分组,并计算每个性别对应的出生数("births" 列)的总和。
names1880.groupby("sex")["births"].sum()
sex F 90993 M 110493 Name: births, dtype: int64
接下来,我们创建一个名为 names
的 pandas 数据框,该数据框将包含从1880年到2010年期间的婴儿姓名数据。
在代码中,使用一个循环来遍历不同年份的文件,并将每个文件读取为一个独立的数据框。然后,将每个数据框中的 "name"、"sex" 和 "births" 列保留,并添加了一个名为 "year" 的列,用于存储对应的年份。最后,使用 pd.concat()
方法将所有的数据框连接成一个整体的数据框 names
。
通过将 ignore_index=True
参数传递给 pd.concat()
方法,可以重新为连接后的数据框生成连续的行索引。
pieces = []
#代码通过循环遍历从1880年到2010年的文件,并将每个文件的内容读取为DataFrame
for year in range(1880, 2011):
path = f"datasets/babynames/yob{year}.txt"
frame = pd.read_csv(path, names=["name", "sex", "births"])
#为每个DataFrame添加一个名为"year"的列
frame["year"] = year
pieces.append(frame)
#用pd.concat()函数将所有DataFrame连接成一个单独的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()
函数对 names
数据框进行操作,计算了按年份和性别分组的出生数总和
通过指定 "births" 作为要聚合的值列,在 index="year"
和 columns="sex"
的基础上进行分组,使用 sum
函数进行求和计算。这样,就创建了一个名为 total_births
的数据框,其中行索引为年份,列索引为性别,值为对应的出生数总和。
使用 tail()
方法显示了 total_births
数据框的最后几行,以便查看最近几年的数据。
最后使用 plot()
方法绘制了一个折线图,标题为 "Total births by sex and year",展示了按年份和性别分组的出生数总和的趋势。
#使用pivot_table()函数计算了按年份和性别分组的出生数总和
total_births = names.pivot_table("births", index="year",
columns="sex", aggfunc=sum)
#显示total_births DataFrame 的最后几行
total_births.tail()
#绘制了一个标题为"Total births by sex and year"的出生数按年份和性别的折线图。
total_births.plot(title="Total births by sex and year")
下面定义了一个名为 add_prop
的函数。该函数接收一个分组,并计算一个名为 "prop" 的新列,表示每个名字在该年份和性别分组中的比例(即出生率)。
在 add_prop
函数中,通过将每个名字对应的出生数除以该年份和性别分组中所有名字的出生数总和,计算了每个名字的出生率。然后,将计算结果存储在一个名为 "prop" 的新列中,并将修改后的分组返回。
接下来,使用 groupby()
方法按照 "year" 和 "sex" 进行分组,并通过 apply()
方法将 add_prop
函数应用于每个分组。这样,更新了 names
数据框,并在每个分组中添加了一个名为 "prop" 的新列,表示每个名字的出生率。
#定义了一个名为add_prop的函数。该函数接收一个分组,并为该分组计算一个名为"prop"的新列,表示每个名字在该年份和性别分组中的比例,每个名字的出生率
def add_prop(group):
group["prop"] = group["births"] / group["births"].sum()
return group
#将names DataFrame 按年份和性别分组,并对每个分组应用add_prop函数
names = names.groupby(["year", "sex"], group_keys=False).apply(add_prop)
使用 groupby()
方法按照 "year" 和 "sex" 对 names
数据框进行分组,并选择了 "prop" 列。然后,使用 sum()
方法计算了每个年份和性别组合中的出生率之和。
#按照 "year" 和 "sex" 进行分组,并计算每个组中的 "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.0Name: prop, Length: 262, dtype: float64
下面定义一个名为 get_top1000
的函数。该函数接收一个分组,并按照 "births" 列降序排序,然后返回前1000个结果。
接下来,使用 groupby()
方法按照 "year" 和 "sex" 对 names
数据框进行分组,并将结果存储在 grouped
变量中。
然后,使用 apply()
方法将 get_top1000
函数应用于每个分组,用于获取每个年份和性别组合中的前1000个出生人数最高的名字。
最后,通过调用 head()
方法显示了 top1000
数据框的前几行,以查看结果。
#该函数接收一个分组,并按照 "births" 列(出生人数)的降序对分组进行排序,然后选择排序结果中的前1000行
def get_top1000(group):
return group.sort_values("births", ascending=False)[:1000]
#按照 "year" 和 "sex" 进行分组,并对每个分组应用 get_top1000 函数
grouped = names.groupby(["year", "sex"])
top1000 = grouped.apply(get_top1000)
top1000.head()
使用 reset_index()
函数对 top1000
数据框进行重置索引,并丢弃了原始索引。通过设置 drop=True
参数,您移除了原始索引列,确保在重置索引后不保留它。
然后,调用 head()
方法显示了经过重置索引后的 top1000
数据框的前几行,以查看出生人数最多的前5名。
#使用reset_index()函数对top1000 DataFrame 进行重置索引,并丢弃原始索引。设置drop=True可以移除原始索引列,以便在重置索引后不保留它。
top1000 = top1000.reset_index(drop=True)
top1000.head()#显示出生人数最多的前5名
使用条件语句将 top1000
数据框按照 "sex" 列的值分为两个子数据集。其中,boys
数据集包含性别为男孩("M")的记录,girls
数据集包含性别为女孩("F")的记录。
接下来,您使用 pivot_table()
函数对 top1000
数据框进行数据透视,以计算每个名字在不同年份下的出生数总和。在透视表中,"births" 列作为值,"year" 列作为索引,"name" 列作为列,并使用 sum
函数进行聚合计算。
这样,您得到了一个新的名为 total_births
的数据框,它显示了每个名字在不同年份下的出生数总和。
#代码根据 "sex" 列的值将 top1000 DataFrame 分为男孩("M")和女孩("F")两个子数据集。
boys = top1000[top1000["sex"] == "M"]
girls = top1000[top1000["sex"] == "F"]
#使用 pivot_table() 函数对 top1000 DataFrame 进行数据透视,计算了每个名字在不同年份下的出生数总和
total_births = top1000.pivot_table("births", index="year",
columns="name",
aggfunc=sum)
表格有点长,用截图展示了
首先使用 info()
方法来获取有关 total_births
数据框的详细信息。这将显示数据框的概要,包括列名、每列的非空值数量以及每列的数据类型等。
然后,创建了一个名为 subset
的新数据框,其中只包含 "John"、"Harry"、"Mary" 和 "Marilyn" 这四个名字的列。通过选择这些列,您可以更加关注和分析这些特定的名字在不同年份下的出生数总和。
接下来,调用 plot()
方法来对 subset
数据框进行绘图。设置 subplots=True
参数会将每个名字的出生数总和作为独立的子图进行绘制。通过设置 figsize=(12, 10)
参数,您可以控制绘图的大小。最后,您设置了图表的标题为 "Number of births per year"。
这样,将得到一个包含四个子图的图表,每个子图显示了每个名字随年份变化的出生数总和。
#码使用 info() 方法打印出 total_births DataFrame 的信息,然后从中选择了 "John"、"Harry"、"Mary" 和 "Marilyn" 四个名字的列,
#并绘制了一个子图展示每年的出生数。
total_births.info()
#选择这四个名字进行绘制
subset = total_births[["John", "Harry", "Mary", "Marilyn"]]
#使用 plot() 方法对 subset DataFrame 进行绘图,设置 subplots=True 以绘制子图,figsize=(12, 10) 用于设置图形的大小
subset.plot(subplots=True, figsize=(12, 10),
title="Number of births per year")
使用 pivot_table()
函数计算了 top1000
数据框中每年男性和女性的出生率总和。"prop"
列被用作值,"year" 列被用作索引,"sex" 列被用作列。聚合函数 sum
被用于计算每年的出生率总和。
使用 plot()
方法绘制了一个折线图,展示了每年男性和女性的出生率关系。图表的标题设置为 "Sum of table1000.prop by year and sex"。yticks
参数被设置为 np.linspace(0, 1.2, 13)
,以控制 y 轴刻度的范围和间隔。
这样,将得到一个显示每年男性和女性出生率总和的折线图。
import matplotlib.pyplot as plt#创建一个新的画布。
plt.figure()
#使用 pivot_table() 函数计算了 top1000 DataFrame 中 的出生率总和
table = top1000.pivot_table("prop", index="year",
columns="sex", aggfunc=sum)
#使用 plot() 方法绘制了一个折线图,展示了每年男女出生率关系
table.plot(title="Sum of table1000.prop by year and sex",
yticks=np.linspace(0, 1.2, 13))
从名为 boys
的数据框中选择了 "year" 列等于 2010 的行,并将结果保存在名为 df
的新数据框中。
通过这个操作,得到了一个名为 df
的数据框,其中包含了 2010 年男孩的出生人数表。这个数据框包含了以下列:年份 ("year")、姓名 ("name")、性别 ("sex")、出生人数 ("births") 和出生率 ("prop") 等信息,下面进一步查看 df
数据框
df = boys[boys["year"] == 2010]#2010年男孩出生人数表
df
首先对 df
数据框中的 "prop" 列进行了排序,并计算了累计和。这通过使用 sort_values(ascending=False)
方法对 "prop" 列进行降序排序,然后使用 cumsum()
方法计算累计和,并将结果保存在名为 prop_cumsum
的变量中。
接下来,调用了 prop_cumsum[:10]
来展示累计和的前10个值。这将显示 prop_cumsum
变量的前10个元素,它们表示排序后的 "prop" 列累计和的前10个值。
最后,使用 searchsorted(0.5)
方法来找到累计和达到 0.5 时的索引位置。searchsorted()
方法返回第一个大于等于指定值的元素的索引,在这里即是累计和超过或等于 0.5 时的索引位置。
#对 DataFrame 中的 "prop" 列进行排序,并计算累计和。然后,展示了累计和的前10个值,
#并使用 searchsorted() 方法找到累计和达到 0.5 时的索引位置。
prop_cumsum = df["prop"].sort_values(ascending=False).cumsum()
prop_cumsum[:10]
prop_cumsum.searchsorted(0.5)
116
从名为 boys
的 DataFrame 中选择了年份为 1900 的数据,并将结果保存在名为 df
的新数据框中。
接下来,对 df
数据框按 "prop" 列进行降序排序,使用 sort_values("prop", ascending=False)
方法实现。排序后,您计算了累计和,通过使用 cumsum()
方法对 "prop" 列进行累计求和,并将结果保存在名为 in1900
的变量中。
最后,使用 in1900.searchsorted(0.5) + 1
找到累计和达到 0.5 时的索引位置,并在结果上加上 1。searchsorted()
方法返回第一个大于等于指定值的元素的索引,加上 1 即为累计和超过或等于 0.5 时的位置索引。
#从名为 boys 的 DataFrame 中选择了年份为 1900 的数据,并对该子数据集按 "prop" 列进行降序排序。
#然后,计算累计和,并使用 searchsorted() 方法找到累计和达到 0.5 时的索引位置,最后加上 1。
df = boys[boys.year == 1900]
in1900 = df.sort_values("prop", ascending=False).prop.cumsum()
in1900.searchsorted(0.5) + 1
25
定义一个名为 get_quantile_count
的函数。该函数接收一个分组作为参数,并按照该分组中 "prop" 列的值进行降序排序。
在函数内部,首先对传入的 group
分组数据框按照 "prop" 列进行降序排序,使用 sort_values("prop", ascending=False)
方法实现。排序后,计算累计和,通过使用 cumsum()
方法对 "prop" 列进行累计求和,并将结果保存在 group.prop.cumsum()
中。
接下来,使用 searchsorted(q)
方法找到累计和达到给定分位数 q
时的位置索引。searchsorted()
方法返回第一个大于等于指定值的元素的索引,这里即为累计和超过或等于给定分位数 q
时的位置索引。最后,将结果上加 1,以得到符合直觉的位置索引。
接下来,使用 top1000.groupby(["year", "sex"]).apply(get_quantile_count)
对 top1000
数据框按年份和性别进行分组,并对每个分组应用 get_quantile_count
函数。最终,将结果保存在名为 diversity
的新数据框中。
最后,使用 diversity.unstack()
将 diversity
数据框进行重塑,将性别作为列索引,年份作为行索引,以重新排列数据框的结构。
#定义了一个名为 get_quantile_count 的函数。该函数接收一个分组,并按照 "prop" 列的值进行降序排序。然后,计算累计和,
#并使用 searchsorted() 方法找到累计和达到给定分位数 q 时的位置,最后加上 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
的图表对象。
接下来,调用 diversity.head()
方法显示了 diversity
数据框的前几行数据。
然后,使用 diversity.plot(title="Number of popular names in top 50%")
方法绘制图表。该图表的标题为 "Number of popular names in top 50%",并展示了每个年份和性别组合中达到前50%的名字数量的变化情况。
fig = plt.figure()
diversity.head()
#使用 plot() 方法绘制了一个图表,标题为 "Number of popular names in top 50%"。图表展示了每个年份和性别组合中达到前50%的名字数量。
diversity.plot(title="Number of popular names in top 50%")
定义了一个名为 get_last_letter
的函数。该函数接收一个字符串 x
,并返回该字符串的最后一个字母。函数内部通过使用索引 -1
来获取字符串的最后一个字符。
接下来,使用 map()
方法将 get_last_letter
函数应用于 names
数据框的 "name" 列,目的是将每个名字的最后一个字母提取出来。提取的结果保存在一个新的 Series 对象中,命名为 last_letters
。
然后,通过对 last_letters
Series 对象设置 name 属性为 "last_letter",将其命名为 "last_letter"。
最后,使用 pivot_table()
函数对 names
数据框进行数据透视操作。将 "last_letters" 作为行索引,将 ["sex", "year"] 作为列索引,计算根据最后一个字母进行分组的出生数总和。计算结果保存在名为 table
的新数据框中。
#定义了一个名为 get_last_letter 的函数。该函数接收一个字符串 x,并返回字符串的最后一个字母。
def get_last_letter(x):
return x[-1]
#使用 map() 方法将 get_last_letter 函数应用于 names DataFrame 的 "name" 列,将每个名字的最后一个字母提取出来
last_letters = names["name"].map(get_last_letter)
last_letters.name = "last_letter"
#使用 pivot_table() 函数对 names DataFrame 进行数据透视,计算每个年份和性别组合中,根据最后一个字母进行分组的出生数总和
table = names.pivot_table("births", index=last_letters,
columns=["sex", "year"], aggfunc=sum)
#将展示按照特定年份(1910、1960 和 2010)的出生数数据,并且按照性别和最后一个字母的分布。
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 |
#展示每个年份和性别组合中每个字母的比例,以及它们在对应年份的出生数总和的占比。
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 库绘制了一个包含两个子图的图形窗口,每个子图展示了不同性别的字母比例数据
fig, axes = plt.subplots(2, 1, figsize=(10, 8))
#在第一个子图中绘制了一个垂直柱状图。kind="bar" 表示绘制柱状图,rot=0 表示不旋转 x 轴标签,ax=axes[0] 表示绘制在第一个子图上,title="Male" 设置了子图的标题为 "Male",即男性。
letter_prop["M"].plot(kind="bar", rot=0, ax=axes[0], title="Male")
#在第二个子图中绘制了一个垂直柱状图。kind="bar" 表示绘制柱状图,rot=0 表示不旋转 x 轴标签,ax=axes[1] 表示绘制在第二个子图上,
#title="Female" 设置了子图的标题为 "Female",即女性。legend=False 表示不显示图例。
letter_prop["F"].plot(kind="bar", rot=0, ax=axes[1], title="Female",
legend=False)
plt.subplots_adjust(hspace=0.25) # 调整子图之间的垂直间距
letter_prop = table / table.sum() # 计算每个字母在每年出生人数中的比例
dny_ts = letter_prop.loc[["d", "n", "y"], "M"].T # 从letter_prop中选择字母"d", "n", "y"在男性出生人数中的比例,并进行转置操作
dny_ts.head() # 显示dny_ts DataFrame的前几行数据
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") # 关闭所有打开的图形窗口
fig = plt.figure() # 创建一个新的Figure对象
dny_ts.plot() # 对dny_ts DataFrame进行折线图的可视化
all_names = pd.Series(top1000["name"].unique()) # 从top1000 DataFrame的"name"列获取唯一的姓名,并将结果存储在all_names变量中
lesley_like = all_names[all_names.str.contains("Lesl")] # 选择all_names中包含"Lesl"的姓名,并将结果赋值给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)] # 根据top1000 DataFrame中的"name"列与lesley_like中的姓名进行匹配,筛选出匹配的行数据,并将结果赋值给filtered变量
filtered.groupby("name")["births"].sum() # 对filtered DataFrame按姓名进行分组,计算每个姓名的出生人数总和,并显示结果
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") # 根据年份和性别对filtered DataFrame进行透视,计算每个年份和性别的出生人数总和,并将结果存储在table变量中
table = table.div(table.sum(axis="columns"), axis="index") # 对table DataFrame进行行归一化,即每行的总和作为除数,计算每个年份和性别的归一化比例
table.tail() # 显示table DataFrame的最后几行数据,即归一化后的比例结果
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() # 创建一个新的Figure对象
table.plot(style={"M": "k-", "F": "k--"}) # 对table DataFrame进行折线图的可视化,男性使用黑色实线,女性使用黑色虚线
3.美国农业部视频数据库
美国农业部提供了食物营养信息数据库。每种事务都有一些识别属性以及两份营养元素和营养比例的列表。这种形式的数据不适合分析,所以需要做一些工作将数据转换成更好的形式。
以下为代码实例
首先使用 open()
函数打开名为 "datasets/usda_food/database.json" 的 JSON 文件,并将其加载到 db
变量中。这里使用 json.load()
方法来读取 JSON 数据,并通过 open()
函数打开对应的文件。
接下来,使用 len(db)
来获取 db
数据库中的条目数量。len()
函数用于返回给定对象的长度或项目的数量。
import json
db = json.load(open("datasets/usda_food/database.json"))
# 计算对象db的长度,即列表中元素的数量
len(db)
6636
db
是一个包含JSON数据的列表。
db[0].keys()
返回列表中第一个字典元素的所有键。
db[0]["nutrients"][0]
获取了第一个字典元素中 "nutrients" 键对应的值的第一个元素。
接下来,根据第一个字典元素中 "nutrients" 键对应的值创建了一个名为 nutrients
的 pandas DataFrame 对象。
最后,使用 head(7)
方法显示了 nutrients
DataFrame 的前7行数据。
# 获取db列表中索引为0的元素的所有键
db[0].keys()
# 从db列表中索引为0的元素中获取键为"nutrients"的值的列表,并返回列表中的第一个元素
db[0]["nutrients"][0]
# *注意*将db列表中索引为0的元素中的"nutrients"值转换为Pandas DataFrame对象
nutrients = pd.DataFrame(db[0]["nutrients"])
# 显示nutrients DataFrame的前7行数据
nutrients.head(7)
将索引为0的元素中的"nutrients"值转换为Pandas DataFrame对象的目的是为了方便对该数据进行进一步的分析和处理。
数据库中的"nutrients"字段可能包含多个营养信息,每个营养信息都具有不同的属性(如名称、单位、值等)。将其转换为DataFrame对象后,可以更方便地应用Pandas库提供的各种功能和方法来处理和分析这些数据。
DataFrame是Pandas库中最常用的数据结构之一,它可以提供灵活的行列操作、数据筛选、聚合计算、可视化等功能。通过将"nutrients"字段转换为DataFrame,可以轻松地利用Pandas提供的各种函数和方法来探索和分析这些营养信息数据。
首先定义了一个名为 info_keys
的列表,其中包含要从数据库中提取的信息的键。
接下来,使用 pd.DataFrame()
函数将 db
数据库中的数据以及 info_keys
列表作为参数,创建了一个名为 info
的 Pandas DataFrame 对象。columns=info_keys
参数用于指定列名,确保新创建的 DataFrame 对象的列与 info_keys
中的键对应。
然后,使用 head()
方法显示了 info
DataFrame 的前几行数据,默认显示前5行数据。
最后,使用 info()
方法显示了 info
DataFrame 的基本信息,包括列名、每列的非空值数量、每列的数据类型等。
info_keys = ["description", "group", "id", "manufacturer"] # 包含要从数据库中提取的信息的键的列表
info = pd.DataFrame(db, columns=info_keys) # 使用info_keys作为列名,创建包含db数据的Pandas DataFrame对象,并将其存储在info变量中
info.head() # 显示info DataFrame的前几行数据
info.info() # 显示info DataFrame的基本信息,包括列名、每列的非空值数量、每列的数据类型等
<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
info["group"]
是 info
DataFrame 中 "group" 列的数据。使用 pd.value_counts()
函数对该列进行计数,并且使用切片操作符指定只显示前10个计数结果。
pd.value_counts(info["group"])
返回一个包含不同组别及其对应计数的 Series 对象。
[:10]
则是用于切片操作,表示只显示前10行计数结果。
pd.value_counts(info["group"])[:10]
'''
info["group"]:从DataFrame info 中选择了名为 "group" 的列,该列包含了食物的分组信息。
pd.value_counts():对选定列中的每个唯一值进行计数,并返回计数结果。
[:10]:取计数结果中的前 10 个值,即返回出现次数最多的前 10 个分组
'''
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
首先创建了一个空列表 nutrients
用于存储营养信息。
然后,使用 for
循环遍历 db
中的每个记录。对于每个记录,使用 pd.DataFrame()
创建一个名为 fnuts
的 DataFrame 对象,其中包含该记录的营养信息。
接下来,使用 fnuts["id"] = rec["id"]
将一个名为 "id" 的列添加到 fnuts
DataFrame 中,并将该记录的 id 值赋给该列的每个元素。这样可以将每个记录的 id 与营养信息关联起来。
然后,使用 nutrients.append(fnuts)
将每个记录的营养信息 DataFrame 添加到 nutrients
列表中。
最后,使用 pd.concat(nutrients, ignore_index=True)
将 nutrients
列表中的所有 DataFrame 对象合并为一个大的 DataFrame,并重新索引行号。将合并后的结果重新赋值给 nutrients
变量。
nutrients = [] # 创建一个空列表用于存储营养信息
for rec in db:
fnuts = pd.DataFrame(rec["nutrients"]) # 为每个记录创建一个包含营养信息的DataFrame对象
fnuts["id"] = rec["id"] # 添加一个名为"id"的列,将记录的id值赋给该列的每个元素
nutrients.append(fnuts) # 将每个记录的营养信息DataFrame添加到nutrients列表中
nutrients = pd.concat(nutrients, ignore_index=True) # 将nutrients列表中的DataFrame对象合并为一个大的DataFrame,并重新索引行号
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()
统计营养信息 DataFrame 中重复行的数量。
然后,使用 nutrients = nutrients.drop_duplicates()
删除营养信息 DataFrame 中的重复行。
接下来,使用字典 col_mapping
定义了两个列名映射关系,将 "description" 列重命名为 "food",将 "group" 列重命名为 "fgroup"。
使用 info = info.rename(columns=col_mapping, copy=False)
将 info DataFrame 的列名按照映射关系进行重命名,其中 copy=False
表示直接在原地修改。
使用 info.info()
显示 info DataFrame 的基本信息,包括列名、每列的非空值数量、每列的数据类型等。
接着,使用字典 col_mapping
定义了另外两个列名映射关系,将 "description" 列重命名为 "nutrient",将 "group" 列重命名为 "nutgroup"。
使用 nutrients = nutrients.rename(columns=col_mapping, copy=False)
将 nutrients DataFrame 的列名按照映射关系进行重命名,其中 copy=False
表示直接在原地修改。
最后,通过执行 nutrients
显示重命名后的 nutrients DataFrame,即显示具有重命名列的营养信息 DataFrame。
nutrients.duplicated().sum() # 统计重复行的数量
nutrients = nutrients.drop_duplicates() # 删除重复的行
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
首先,使用 pd.merge(nutrients, info, on="id")
基于 "id" 列将 nutrients 和 info 两个 DataFrame 进行合并,并将结果存储在 ndata 中。
然后,使用 ndata.info()
显示 ndata DataFrame 的基本信息,包括列名、每列的非空值数量、每列的数据类型等。
接着,使用 ndata.iloc[30000]
获取 ndata DataFrame 中索引为 30000 的行的数据,并将其显示出来。这将显示索引为 30000 的行的所有列的值。
ndata = pd.merge(nutrients, info, on="id") # 基于"id"列将nutrients和info两个DataFrame进行合并,并将结果存储在ndata中
ndata.info() # 显示ndata DataFrame的基本信息
ndata.iloc[30000] # 获取ndata DataFrame中索引为30000的行的数据
value 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()
创建一个新的空白 Figure 对象,并将其赋值给变量 fig。
然后,使用 ndata.groupby(["nutrient", "fgroup"])["value"].quantile(0.5)
根据 "nutrient" 和 "fgroup" 列进行分组,计算 "value" 列的中位数,并将结果存储在 result 变量中。这将得到一个以 "nutrient" 和 "fgroup" 为索引的 Pandas Series 对象。
接下来,使用 result["Zinc, Zn"].sort_values().plot(kind="barh")
从 result 中选择 "Zinc, Zn" 列的数据,对数据进行排序,然后使用水平条形图进行可视化。这将显示出以 "Zinc, Zn" 为横轴、中位数值为纵轴的条形图。
fig = plt.figure() # 创建一个新的空白Figure对象,并将其赋值给变量fig
result = ndata.groupby(["nutrient", "fgroup"])["value"].quantile(0.5) # 根据"nutrient"和"fgroup"列进行分组,计算"value"列的中位数,并将结果存储在result变量中
result["Zinc, Zn"].sort_values().plot(kind="barh") # 从result中选择"Zinc, Zn"列的数据,对数据进行排序,然后使用水平条形图进行可视化
首先,使用 by_nutrient = ndata.groupby(["nutgroup", "nutrient"])
根据 "nutgroup" 和 "nutrient" 列进行分组,将结果存储在 by_nutrient 变量中。这将得到一个按照 "nutgroup" 和 "nutrient" 进行分组的 GroupBy 对象。
接下来,定义了一个函数 get_maximum(x)
,用于获取每个分组中 "value" 列取得最大值的行。函数内部使用了 x.loc[x.value.idxmax()]
,通过找到对应最大值的索引,从原始数据中选择相应的行。
然后,使用 by_nutrient.apply(get_maximum)[["value", "food"]]
对每个分组应用 get_maximum
函数,获取 "value" 列最大值所对应的行,并选择 "value" 和 "food" 两列。这将得到一个包含每个分类下取得最大值的食物名称和对应的最大值的 DataFrame。
接着,使用 max_foods["food"] = max_foods["food"].str[:50]
将 "food" 列的字符串长度截取为最多 50 个字符。这将修改 "food" 列中的字符串,使其最多包含 50 个字符。
最后,使用 max_foods.loc["Amino Acids"]["food"]
从 max_foods DataFrame 中选择索引为 "Amino Acids" 的行,返回一个包含该行数据的 Series。然后从该 Series 中选择名为 "food" 的列,返回 "Amino Acids" 分类下食物名称的数据。
by_nutrient = ndata.groupby(["nutgroup", "nutrient"]) # 根据"nutgroup"和"nutrient"列进行分组,将结果存储在by_nutrient变量中
def get_maximum(x):
return x.loc[x.value.idxmax()] # 定义一个函数get_maximum,用于获取每个分组中"value"列取得最大值的行
max_foods = by_nutrient.apply(get_maximum)[["value", "food"]] # 对每个分组应用get_maximum函数,获取"value"列最大值所对应的行,并选择"value"和"food"两列
max_foods["food"] = max_foods["food"].str[:50] # 将"food"列的字符串长度截取为最多50个字符
max_foods.loc["Amino Acids"]["food"] # 从 max_foods DataFrame 中选择索引为 "Amino Acids" 的行,返回一个包含该行数据的 Series。从该 Series 中选择名为 "food" 的列,返回 "Amino Acids" 分类下食物名称的数据。
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年联邦选举委员会数据库
美国联邦选举委员会公布了有关政治运动贡献的数据。这些数据包括捐赠者姓名、职业和雇主、地址和缴费金额。你可以尝试做以下分析:
1.按职业和雇主的捐赠统计;2.按捐赠金额统计;3.按州进行统计。
以下是代码实例
fec.info()
是一个用于显示 DataFrame 基本信息的方法。它将显示有关 DataFrame 的列数、每列的名称、非空值的数量以及每列的数据类型等信息
fec = pd.read_csv("datasets/fec/P00000001-ALL.csv", low_memory=False) # 从CSV文件中读取数据,并将结果存储在fec变量中,low_memory参数设置为False以确保读取所有数据
fec.info() # 显示fec DataFrame的基本信息
<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+ MB
fec.iloc[]
返回指定行和列位置索引上的数据。如果只提供 row_index
参数,则返回整行的数据;如果同时提供 row_index
和 column_index
参数,则返回指定行和列交叉位置上的数据。
尝试想获取某一行的值
fec.iloc[123456]
unique_cands = fec["cand_nm"].unique()
这一行代码获取了名为 fec
的 DataFrame 中 "cand_nm"
列中唯一的候选人姓名,并将结果存储在名为 unique_cands
的变量中。
unique_cands
是一个数组,包含了唯一的候选人姓名列表。
unique_cands[2]
表示获取 unique_cands
数组中索引为 2 的元素,即第三个候选人的姓名。请注意,索引是从 0 开始的,因此 unique_cands[2]
表示获取第三个候选人的姓名。
unique_cands = fec["cand_nm"].unique() # 从fec DataFrame的"cand_nm"列获取唯一的候选人姓名,将结果存储在unique_cands变量中
unique_cands # 显示unique_cands数组,即唯一的候选人姓名列表
unique_cands[2] # 获取unique_cands数组中索引为2的元素,即第三个候选人的姓名
'Obama, Barack'
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"}
# 设置党派
fec["cand_nm"][123456:123461] # 获取fec DataFrame中"cand_nm"列索引为123456到123460的行的数据
fec["cand_nm"][123456:123461].map(parties) # 对索引为123456到123460的"cand_nm"列的数据应用parties字典,将候选人姓名映射为对应的党派
fec["party"] = fec["cand_nm"].map(parties) # 将通过parties字典映射后的党派信息添加为fec DataFrame的一个新列,列名为"party"
fec["party"].value_counts() # 统计"party"列中每个党派的数量,并返回计数结果
Democrat 593746 Republican 407985 Name: party, dtype: int64
(fec["contb_receipt_amt"] > 0)
返回一个布尔值 Series,其中对于大于 0 的值为 True,小于等于 0 的值为 False。
.value_counts()
对该布尔值 Series 进行统计,返回每个唯一值的数量
(fec["contb_receipt_amt"] > 0).value_counts() # 统计"contb_receipt_amt"列中大于0的值的数量和小于等于0的值的数量
True 991475 False 10256 Name: contb_receipt_amt, dtype: int64
fec = fec[fec["contb_receipt_amt"] > 0]
:从 fec
DataFrame 中筛选出 "contb_receipt_amt" 列大于 0 的行,并将结果重新赋值给 fec
变量。这一行代码用于过滤掉贡献金额小于等于0的行。
fec_mrbo = fec[fec["cand_nm"].isin(["Obama, Barack", "Romney, Mitt"])]
:从 fec
DataFrame 中筛选出 "cand_nm" 列包含 "Obama, Barack" 或 "Romney, Mitt" 的行,并将结果赋值给 fec_mrbo
变量。这一行代码用于创建一个新的 DataFrame,其中只包含 Obama 和 Romney 的相关数据。
fec["contbr_occupation"].value_counts()[:10]
:统计 "contbr_occupation" 列中各个职业的数量,并返回前 10 个结果。这一行代码会返回出现频次最高的前 10 个职业及其对应的数量。
fec = fec[fec["contb_receipt_amt"] > 0] # 从fec DataFrame中筛选出"contb_receipt_amt"列大于0的行,并将结果重新赋值给fec变量
fec_mrbo = fec[fec["cand_nm"].isin(["Obama, Barack", "Romney, Mitt"])] # 从fec DataFrame中筛选出"cand_nm"列包含"Obama, Barack"或"Romney, Mitt"的行,并将结果赋值给fec_mrbo变量
fec["contbr_occupation"].value_counts()[:10] # 统计"contbr_occupation"列中各个职业的数量,并返回前10个结果
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 是一个字典,用于将 "contbr_occupation" 列中的某些职业名称进行映射。其中,键是需要映射的原始职业名称,值是映射后的职业名称。
get_occ(x) 是一个函数,用于接受一个输入 x(即职业名称),并根据 occ_mapping 字典进行映射。如果 x 在 occ_mapping 中有对应的映射值,则返回映射后的职业名称,否则返回 x 本身。
fec["contbr_occupation"].map(get_occ) 将 "contbr_occupation" 列中的值应用 get_occ 函数进行映射。这一行代码将会对 "contbr_occupation" 列中的每个职业名称进行映射处理,并将结果赋值回 "contbr_occupation" 列。
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 函数将 "contbr_occupation" 列中的值进行映射
emp_mapping
是一个字典,用于将 "contbr_employer" 列中的某些雇主名称进行映射。其中,键是需要映射的原始雇主名称,值是映射后的雇主名称。
get_emp(x)
是一个函数,用于接受一个输入 x
(即雇主名称),并根据 emp_mapping
字典进行映射。如果 x
在 emp_mapping
中有对应的映射值,则返回映射后的雇主名称,否则返回 x
本身。
fec["contbr_employer"].map(get_emp)
将 "contbr_employer" 列中的值应用 get_emp
函数进行映射。这一行代码将会对 "contbr_employer" 列中的每个雇主名称进行映射处理,并将结果赋值回 "contbr_employer" 列。
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 函数将 "contbr_employer" 列中的值进行映射
fec.pivot_table()
是一个透视表函数,用于根据指定的行、列和聚合函数对数据进行透视。在这段代码中,使用 "contb_receipt_amt" 列作为值进行透视,使用 "contbr_occupation" 列作为行索引,使用 "party" 列作为列索引,使用 "sum" 聚合函数对值进行求和。
by_occupation
是透视后的结果,它是一个包含职业和党派作为行列索引的数据表,以 "contb_receipt_amt" 作为值。
over_2mm = by_occupation[by_occupation.sum(axis="columns") > 2000000]
选择了总和大于2000000的行,并将结果赋值给变量 over_2mm
。这行代码使用了布尔索引,通过计算每行的总和并判断是否大于2000000来选择行。
over_2mm
是一个 DataFrame,其中包含了总和大于2000000的职业和党派的数据。
by_occupation = fec.pivot_table("contb_receipt_amt", # 使用"contb_receipt_amt"列作为值进行透视
index="contbr_occupation", # 使用"contbr_occupation"列作为行索引
columns="party", # 使用"party"列作为列索引
aggfunc="sum") # 对值进行求和聚合
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 |
#对over_2mm DataFrame进行水平条形图的可视化
plt.figure() # 创建一个新的空白Figure对象
over_2mm.plot(kind="barh") # 对over_2mm DataFrame进行水平条形图的可视化
get_top_amounts()
是一个自定义函数,接受三个参数 group
、key
和 n
。在这个函数中,首先对 group
中的数据按照 key
进行分组,然后计算每个分组中 "contb_receipt_amt" 列的总和。最后返回总和最大的前 n
个组。
grouped = fec_mrbo.groupby("cand_nm")
对 DataFrame fec_mrbo
根据 "cand_nm"(候选人姓名)进行分组,并将分组结果赋值给 grouped
变量。
grouped.apply(get_top_amounts, "contbr_occupation", n=7)
对分组后的数据应用自定义函数 get_top_amounts
,其中 key
为 "contbr_occupation"(捐助者职业),限制返回每个组中前 7 个总和最大的组。
grouped.apply(get_top_amounts, "contbr_employer", n=10)
对分组后的数据应用自定义函数 get_top_amounts
,其中 key
为 "contbr_employer"(捐助者雇主),限制返回每个组中前 10 个总和最大的组。
def get_top_amounts(group, key, n=5):
totals = group.groupby(key)["contb_receipt_amt"].sum() # 对group中的数据按key进行分组,计算每个组中"contb_receipt_amt"列的总和
return totals.nlargest(n) # 返回总和最大的前n个组
grouped = fec_mrbo.groupby("cand_nm") # 根据候选人姓名对fec_mrbo DataFrame进行分组
grouped.apply(get_top_amounts, "contbr_occupation", n=7) # 对分组后的数据应用get_top_amounts函数,按"contbr_occupation"列获取每个组的前7个最大总和
grouped.apply(get_top_amounts, "contbr_employer", n=10) # 对分组后的数据应用get_top_amounts函数,按"contbr_employer"列获取每个组的前10个最大总和
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
bins = np.array([0, 1, 10, 100, 1000, 10000, 100_000, 1_000_000, 10_000_000])
定义了一个包含分箱边界值的 NumPy 数组。这个数组将被用来把 "contb_receipt_amt" 列的值分成不同的区间。
labels = pd.cut(fec_mrbo["contb_receipt_amt"], bins)
使用 pd.cut()
函数将 "contb_receipt_amt" 列的值根据指定的分箱边界进行分箱,并返回一个包含对应区间标签的 Series。
labels
是一个包含了每个 "contb_receipt_amt" 值所属的区间标签的 Series。
bins = np.array([0, 1, 10, 100, 1000, 10000, 100_000, 1_000_000, 10_000_000]) # 定义一个包含分箱边界值的NumPy数组,用于将"contb_receipt_amt"列的值分成不同的区间
labels = pd.cut(fec_mrbo["contb_receipt_amt"], bins) # 使用pd.cut函数根据指定的分箱边界将"contb_receipt_amt"列的值进行分箱,并返回一个包含对应区间标签的Series
labels # 显示labels Series,即包含了每个"contb_receipt_amt"值所属的区间标签
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])
根据 "cand_nm"(候选人姓名)和 labels
对 DataFrame fec_mrbo
进行分组。这意味着数据将按照候选人姓名和区间标签进行分组。
grouped.size().unstack(level=0)
首先使用 size()
方法计算每个分组的大小,即每个候选人在不同区间标签下的数据量。然后使用 unstack()
方法将结果转换为宽格式,即以候选人姓名为列。最后,显示转换后的结果。
grouped = fec_mrbo.groupby(["cand_nm", labels]) # 根据候选人姓名和labels对fec_mrbo DataFrame进行分组
grouped.size().unstack(level=0) # 计算每个候选人在不同区间标签下的数据量,并将结果转换为宽格式(以候选人姓名为列),并显示该结果
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 | 0 |
plt.figure()
创建一个新的空白 Figure 对象,用于绘制图形。
bucket_sums = grouped["contb_receipt_amt"].sum().unstack(level=0)
计算每个候选人在不同区间标签下的 "contb_receipt_amt" 列的总和,并将结果转换为宽格式(以候选人姓名为列)。
normed_sums = bucket_sums.div(bucket_sums.sum(axis="columns"), axis="index")
对每个候选人在不同区间标签下的总和进行归一化,即计算每个候选人在每个区间的比例。使用 div()
方法,将每行的总和作为除数,进行归一化计算。
normed_sums
是归一化后的比例结果。
normed_sums[:-2].plot(kind="barh")
对前面除去最后两行的归一化比例结果进行水平条形图的可视化。使用 plot()
方法,设置 kind="barh"
表示绘制水平条形图。
plt.figure() # 创建一个新的空白Figure对象
bucket_sums = grouped["contb_receipt_amt"].sum().unstack(level=0) # 计算每个候选人在不同区间标签下的"contb_receipt_amt"列的总和,并转换为宽格式(以候选人姓名为列)
normed_sums = bucket_sums.div(bucket_sums.sum(axis="columns"), axis="index") # 对每个候选人在不同区间标签下的总和进行归一化,以每行的总和作为除数,计算归一化后的比例
normed_sums # 显示归一化后的比例结果
normed_sums[:-2].plot(kind="barh") # 对前面除去最后两行的归一化比例结果进行水平条形图的可视化
grouped = fec_mrbo.groupby(["cand_nm", "contbr_st"])
根据 "cand_nm"(候选人姓名)和 "contbr_st"(捐赠者所在州)对 DataFrame fec_mrbo
进行分组。这意味着数据将按照候选人姓名和捐赠者所在州进行分组。
totals = grouped["contb_receipt_amt"].sum().unstack(level=0).fillna(0)
计算每个候选人在不同州的总捐款金额,并将结果转换为宽格式(以候选人姓名为列)。使用 sum()
方法计算总和,然后使用 unstack()
方法将结果转换为宽格式。最后,使用 fillna(0)
方法用 0 填充缺失值。
totals = totals[totals.sum(axis="columns") > 100000]
筛选出总捐款金额超过 100,000 的行。使用 sum(axis="columns")
方法计算每行的总和,再使用条件判断 totals.sum(axis="columns") > 100000
进行筛选。
totals.head(10)
显示前 10 行的 totals
DataFrame。
grouped = fec_mrbo.groupby(["cand_nm", "contbr_st"]) # 根据候选人姓名和捐赠者所在州(contbr_st)对fec_mrbo DataFrame进行分组
totals = grouped["contb_receipt_amt"].sum().unstack(level=0).fillna(0) # 计算每个候选人在不同州的总捐款金额,将结果转换为宽格式(以候选人姓名为列),并用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")
对每个州的总捐款金额进行归一化,即计算每个州的捐款金额在总捐款金额中的比例。使用 div()
方法,将每行的总和作为除数,进行归一化计算。
percent.head(10)
显示前 10 行的 percent
DataFrame,即每个州的归一化比例结果。
percent = totals.div(totals.sum(axis="columns"), axis="index") # 对每个州的总捐款金额进行归一化,以每行的总和作为除数,计算归一化后的比例
percent.head(10) # 显示前10行的percent DataFrame,即每个州的归一化比例结果
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 |
四个实例就到此结束了
大家可以尝试回答以下问题,来检验自己是否掌握相关函数
#假设有以下DataFrame df:
df = pd.DataFrame({'Name': ['Alice', 'Bob', 'Charlie',
'Alice', 'Bob', 'Charlie', 'Alice'],
'Category': ['A', 'B', 'B', 'A', 'B', 'B', 'A'],
'Value': [10, 20, 30, 40, 50, 60, 70]})
1.若使用
pivot_table()
函数对df
进行操作,并以'Name'
为行索引,'Category'
为列索引,对'Value'
进行平均聚合计算,则结果DataFrame的形状将是:A. 2行 × 2列 B. 3行 × 2列
C. 2行 × 3列 D. 3行 × 3列
2.在以下错误示例代码中,哪个会导致创建新列失败?
A)
mean_ratings["diff"] = mean_ratings["column1"] + mean_ratings["column2"]
B)
mean_ratings["diff"] = "column1" - "column2"
C)
mean_ratings["diff"] = mean_ratings.column1 - mean_ratings.column2
3.当使用
sort_values()
函数进行降序排序时,以下哪个选项是正确的?A.
sort_values(ascending=True)
B.
sort_values(descending=True)
C.
sort_values(ascending=False)
D.
sort_values(order='desc')
答案 1.B
2.B、C
3.C