Pandas-网络对抗赛题目

文章展示了如何使用Python进行数据分析,包括读取MoviesLens1M数据集,对电影评分进行分组、合并和可视化,以及探索不同性别对电影的评分差异。此外,还分析了美国1880-2010年间名字的流行趋势,以及联邦选举委员会数据库中政治捐款的数据,涉及数据清洗、聚合和可视化过程。
摘要由CSDN通过智能技术生成

《利用Python进行数据分析》示例数据

请结合提供的示例数据,分析代码的功能,并进行数据分析与可视化拓展

1.MoviesLens 1M数据集

GroupLens实验室提供了一些从MoviesLens用户那里收集的20世纪90年代末到21世纪初的电影评分数据的集合。这些数据提供了电影的评分、流派、年份和观众数据(年龄、邮编、性别、职业)。
MovisLens1M数据集包含6000个用户对4000部电影的100万个评分。数据分布在三个表格之中:分别包含评分、用户信息和电影信息。

unames = ["user_id", "gender", "age", "occupation", "zip"]    #观看电影的用户的信息
users = pd.read_table("datasets/movielens/users.dat", sep="::",
                      header=None, names=unames, engine="python")   #用pandas的read_table方法读取users.dat的数据。
                                                                    #该文件使用"::"作为分隔符,没有表头行,因此通过names参数指定了列名。
rnames = ["user_id", "movie_id", "rating", "timestamp"]   #定义了评分信息表的列名
ratings = pd.read_table("datasets/movielens/ratings.dat", sep="::",
                        header=None, names=rnames, engine="python")   #使用pd.read_table函数从"ratings.dat"文件中读取数据

mnames = ["movie_id", "title", "genres"]   #电影信息表的列名
movies = pd.read_table("datasets/movielens/movies.dat", sep="::",
                       header=None, names=mnames, engine="python")  #使用pd.read_table函数从"movies.dat"文件中读取数据
users.head(5)   #显示users DataFrame的前5行
ratings.head(5) #显示ratings DataFrame的前5行
movies.head(5)  #显示movies DataFrame的前5行
ratings   #显示完整的ratings DataFrame
user_idmovie_idratingtimestamp
0111935978300760
116613978302109
219143978301968
3134084978300275
4123555978824291
...............
1000204604010911956716541
1000205604010945956704887
100020660405625956704746
1000207604010964956715648
1000208604010974956715569

1000209 rows × 4 columns

data = pd.merge(pd.merge(ratings, users), movies)   #用merge方法将ratings和users两个DataFrame根据user_id列进行合并,再将合并结果与movies DataFrame根据movie_id列进行合并
data
data.iloc[0]  #通过iloc属性,获取data DataFrame中的第一行数据,并将其显示出来。
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
mean_ratings = data.pivot_table("rating", index="title",
                                columns="gender", aggfunc="mean")   #使用pivot_table计算了每部电影的平均评分,“rating”表示从rating这张表找。index是行标题,用电影名做行。用性别划分每一列。F为女性,M为男性,aggfunc="mean"表示pivot函数根据平均值聚合。
mean_ratings.head(5)  #显示前五行的数据
genderFM
title
$1,000,000 Duck (1971)3.3750002.761905
'Night Mother (1986)3.3888893.352941
'Til There Was You (1997)2.6756762.733333
'burbs, The (1989)2.7934782.962085
...And Justice for All (1979)3.8285713.689024
ratings_by_title = data.groupby("title").size() #使用groupby()函数按照电影标题("title"列)进行分组,并使用size()函数计算每个分组中的元素数量。这样就得到了每部电影的评分数量,并将结果存储在ratings_by_title变量中。
ratings_by_title.head() #计算得到的每部电影的评分数量的前几行。它使用head()函数来显示Series的前几行,其中每行表示一部电影的评分数量。
active_titles = ratings_by_title.index[ratings_by_title >= 250]#筛选出评分数量大于等于250的活跃电影标题。它使用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 = mean_ratings.loc[active_titles]#使用.loc属性根据活跃电影的标题列表active_titles来筛选出平均评分数据中对应的行。它会返回一个新的DataFrame,其中只包含活跃电影的平均评分数据。
mean_ratings #显示筛选后的平均评分数据
genderFM
title
'burbs, The (1989)2.7934782.962085
10 Things I Hate About You (1999)3.6465523.311966
101 Dalmatians (1961)3.7914443.500000
101 Dalmatians (1996)3.2400002.911215
12 Angry Men (1957)4.1843974.328421
.........
Young Guns (1988)3.3717953.425620
Young Guns II (1990)2.9347832.904025
Young Sherlock Holmes (1985)3.5147063.363344
Zero Effect (1998)3.8644073.723140
eXistenZ (1999)3.0985923.289086

1216 rows × 2 columns

mean_ratings = mean_ratings.rename(index={"Seven Samurai (The Magnificent Seven) (Shichinin no samurai) (1954)":
                           "Seven Samurai (Shichinin no samurai) (1954)"})
使用rename()函数来重命名mean_ratings DataFrame的索引。通过index参数指定要重命名的索引名称和对应的新名称。
在这个例子中,将"Seven Samurai (The Magnificent Seven) (Shichinin no samurai) (1954)"的索引名称更改为
"Seven Samurai (Shichinin no samurai) (1954)"
top_female_ratings = mean_ratings.sort_values("F", ascending=False)#使用sort_values()函数根据"F"列(女性观众的平均评分)对mean_ratings DataFrame进行排序。参数ascending=False表示按照降序排列,即最高评分排在前面。
top_female_ratings.head()
genderFM
title
Close Shave, A (1995)4.6444444.473795
Wrong Trousers, The (1993)4.5882354.478261
Sunset Blvd. (a.k.a. Sunset Boulevard) (1950)4.5726504.464589
Wallace & Gromit: The Best of Aardman Animation (1996)4.5631074.385075
Schindler's List (1993)4.5626024.491415
mean_ratings["diff"] = mean_ratings["M"] - mean_ratings["F"]#新建一个列表示女性和男性评分的差值
sorted_by_diff = mean_ratings.sort_values("diff")#根据差值对ratings进行排序。
sorted_by_diff.head()
genderFMdiff
title
Dirty Dancing (1987)3.7903782.959596-0.830782
Jumpin' Jack Flash (1986)3.2547172.578358-0.676359
Grease (1978)3.9752653.367041-0.608224
Little Women (1994)3.8705883.321739-0.548849
Steel Magnolias (1989)3.9017343.365957-0.535777
sorted_by_diff[::-1].head()#用[::-1]降序排序
genderFMdiff
title
Good, The Bad and The Ugly, The (1966)3.4949494.2213000.726351
Kentucky Fried Movie, The (1977)2.8787883.5551470.676359
Dumb & Dumber (1994)2.6979873.3365950.638608
Longest Day, The (1962)3.4117654.0314470.619682
Cable Guy, The (1996)2.2500002.8637870.613787
rating_std_by_title = data.groupby("title")["rating"].std()#使用groupby()函数按照电影标题("title"列)对评分数据进行分组,并使用std()函数计算每个分组中评分的标准差
rating_std_by_title = rating_std_by_title.loc[active_titles]#筛选出评分数量大于等于250的活跃电影的评分标准差数据。它使用.loc属性根据活跃电影的标题列表active_titles来筛选出评分标准差数据中对应的行,并将结果重新赋值给rating_std_by_title变量。
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
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
movies["genres"].head()#显示电影数据集中的"genres"列的前几行内容。它用于查看原始数据,以便进行后续的处理操作
movies["genres"].head().str.split("|")#将"genres"列的每个元素(电影的类型)按照"|"进行拆分,并返回一个包含拆分后结果的Series对象。这样可以查看拆分后的结果,但不会对原始数据进行更改。
movies["genre"] = movies.pop("genres").str.split("|")#将原始的"genres"列进行拆分,并将拆分后的结果存储在新的"genre"列中。它使用pop()函数将"genres"列从DataFrame中删除,并返回被删除的列作为Series对象。然后,使用str.split("|")将每个元素按照"|"进行拆分,并将结果赋值给新的"genre"列。
movies.head()
movie_idtitlegenre
01Toy Story (1995)[Animation, Children's, Comedy]
12Jumanji (1995)[Adventure, Children's, Fantasy]
23Grumpier Old Men (1995)[Comedy, Romance]
34Waiting to Exhale (1995)[Comedy, Drama]
45Father of the Bride Part II (1995)[Comedy]
movies_exploded = movies.explode("genre")#使用explode()函数对电影数据集中的"genre"列进行展开操作。展开操作将每个电影的多个类型拆分成单独的行,生成一个新的DataFrame,其中包含了展开后的所有行。
movies_exploded[:10]#显示展开后的电影数据集的前几行。通过切片操作[:10],它仅显示展开后的DataFrame的前10行,以便查看展开后的结果。
movie_idtitlegenre
01Toy Story (1995)Animation
01Toy Story (1995)Children's
01Toy Story (1995)Comedy
12Jumanji (1995)Adventure
12Jumanji (1995)Children's
12Jumanji (1995)Fantasy
23Grumpier Old Men (1995)Comedy
23Grumpier Old Men (1995)Romance
34Waiting to Exhale (1995)Comedy
34Waiting to Exhale (1995)Drama
ratings_with_genre = pd.merge(pd.merge(movies_exploded, ratings), users)#将展开后的电影数据集(movies_exploded)与评分数据集(ratings)和用户数据集(users)进行合并,得到包含电影类型的评分数据集(ratings_with_genre)。通过使用pd.merge()函数将三个数据集按照共同的列(例如"user_id"和"movie_id")进行合并。
ratings_with_genre.iloc[0]#显示ratings_with_genre数据集中的第一行数据。它使用.iloc[0]选择索引为0的行(即第一行),并显示其内容。
genre_ratings = (ratings_with_genre.groupby(["genre", "age"])
                 ["rating"].mean()
                 .unstack("age"))#对ratings_with_genre数据集按照"genre"(电影类型)和"age"(年龄段)进行分组,并计算不同电影类型和年龄段的平均评分。使用groupby()函数按照指定的列进行分组,然后使用["rating"].mean()计算平均评分。最后,使用.unstack("age")将年龄段作为列索引展开,生成一个新的DataFrame,其中每一列表示不同年龄段的平均评分。
genre_ratings[:10]
age1182535455056
genre
Action3.5063853.4470973.4533583.5381073.5285433.6113333.610709
Adventure3.4499753.4085253.4431633.5152913.5289633.6281633.649064
Animation3.4761133.6240143.7012283.7405453.7348563.7800203.756233
Children's3.2416423.2942573.4268733.5184233.5275933.5565553.621822
Comedy3.4974913.4604173.4903853.5619843.5917893.6468683.650949
Crime3.7101703.6680543.6803213.7337363.7506613.8106883.832549
Documentary3.7307693.8658653.9466903.9537473.9665213.9081083.961538
Drama3.7947353.7219303.7264283.7825123.7843563.8784153.933465
Fantasy3.3176473.3537783.4524843.4823013.5324683.5815703.532700
Film-Noir4.1454553.9973684.0587254.0649104.1053764.1754014.125932

2.美国1880-2010年的婴儿名字

美国社会保障局(SSA)提供了从1880年至现在的婴儿姓名频率的数据。可以使用这些数据做很多事情:
根据给定的名字对婴儿名字随时间的比例进行可视化
确定一个名字的相对排位
确定每年最受欢迎的名字,或者流行程度最高或最低的名字

!head -n 10 datasets/babynames/yob1880.txt  #获取yob1880.txt的前十行内容
'head' 不是内部或外部命令,也不是可运行的程序
或批处理文件。
names1880 = pd.read_csv("datasets/babynames/yob1880.txt",
                        names=["name", "sex", "births"])#names=["name", "sex", "births"]指定了DataFrame的列名为"name"(名字)、"sex"(性别)和"births"(出生数)。
names1880
namesexbirths
0MaryF7065
1AnnaF2604
2EmmaF2003
3ElizabethF1939
4MinnieF1746
............
1995WoodieM5
1996WorthyM5
1997WrightM5
1998YorkM5
1999ZachariahM5

2000 rows × 3 columns

names1880.groupby("sex")["births"].sum()#使用groupby()函数将names1880 DataFrame按照性别("sex"列)进行分组。然后,通过["births"]选择"births"列,并使用sum()函数计算每个性别的出生数总和。
sex
F     90993
M    110493
Name: births, dtype: int64
pieces = []
for year in range(1880, 2011):  #使用循环遍历从1880年到2010年(不包括2011年)的年份。
    path = f"datasets/babynames/yob{year}.txt"  #使用f-string格式化生成基于年份的文件路径。
    frame = pd.read_csv(path, names=["name", "sex", "births"])  3调用pd.read_csv()函数来读取位于生成的路径的CSV文件。它为DataFrame的列分配了列名"name""sex""births"# 为DataFrame添加一个名为"year"的新列,其值为当前的年份。
    frame["year"] = year
    pieces.append(frame) #将当前DataFrame添加到pieces列表中

# 循环结束后,使用pd.concat()函数将pieces列表中的所有DataFrame沿垂直方向合并为一个单独的DataFrame。
names = pd.concat(pieces, ignore_index=True)
names
namesexbirthsyear
0MaryF70651880
1AnnaF26041880
2EmmaF20031880
3ElizabethF19391880
4MinnieF17461880
...............
1690779ZymaireM52010
1690780ZyonneM52010
1690781ZyquariusM52010
1690782ZyranM52010
1690783ZzyzxM52010

1690784 rows × 4 columns

total_births = names.pivot_table("births", index="year",
                                 columns="sex", aggfunc=sum)#使用pivot_table()函数创建一个透视表,其中"births"列被用作值(要计算的数据),"year"列作为透视表的索引,"sex"列作为透视表的列,sum作为聚合函数,用于计算每年每个性别的总出生人数。结果将被赋值给total_births变量。
total_births.tail()#显示透视表的最后几行
total_births.plot(title="Total births by sex and year")#使用plot()函数绘制总出生人数按性别和年份的图表。title="Total births by sex and year"用于设置图表的标题为"Total births by sex and year"。
<AxesSubplot:title={'center':'Total births by sex and year'}, xlabel='year'>

在这里插入图片描述

def add_prop(group): #定义了一个名为add_prop的函数,该函数接收一个group参数,代表一个分组。
    group["prop"] = group["births"] / group["births"].sum() #计算每个分组中每个名字的出生比例,并将结果存储在group分组的一个新列"prop"中。出生比例的计算是通过将每个名字的出生数除以该分组中所有名字的总出生数来实现。
    return group
names = names.groupby(["year", "sex"], group_keys=False).apply(add_prop)  #使用groupby()函数对names DataFrame 进行分组,分组的依据是"year"和"sex"两列。group_keys=False参数用于禁止为结果添加额外的分组键。然后,使用apply()函数将add_prop函数应用到每个分组上,计算每个分组中每个名字的出生比例,并将结果更新到原始的names DataFrame。
names
namesexbirthsyearprop
0MaryF706518800.077643
1AnnaF260418800.028618
2EmmaF200318800.022013
3ElizabethF193918800.021309
4MinnieF174618800.019188
..................
1690779ZymaireM520100.000003
1690780ZyonneM520100.000003
1690781ZyquariusM520100.000003
1690782ZyranM520100.000003
1690783ZzyzxM520100.000003

1690784 rows × 5 columns

names.groupby(["year", "sex"])["prop"].sum()#根据年份对每个名字的出生比例进行求和,并根据性别分行。显而易见,每一年的比例加一起应为1.实际也是如此。
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
def get_top1000(group): #定义了一个名为get_top1000的函数,该函数接收一个group参数,代表一个分组。
    return group.sort_values("births", ascending=False)[:1000] #对每个分组按照"births"列进行降序排序,然后选取排序后的前1000行作为结果,即获取每个分组中出生人数最高的前1000个名字。
grouped = names.groupby(["year", "sex"]) #使用groupby()函数对names DataFrame 进行分组,分组的依据是"year"和"sex"两列,并将结果赋值给grouped变量。
top1000 = grouped.apply(get_top1000)  #将get_top1000函数应用到每个分组上,获取每个分组中出生人数最高的前1000个名字,并将结果存储在top1000 DataFrame 中。
top1000.head()
namesexbirthsyearprop
yearsex
1880F0MaryF706518800.077643
1AnnaF260418800.028618
2EmmaF200318800.022013
3ElizabethF193918800.021309
4MinnieF174618800.019188
top1000 = top1000.reset_index(drop=True)#使用reset_index()函数对top1000 DataFrame 进行索引重置操作。drop=True参数用于丢弃原来的索引,而不保留为新的一列
top1000.head()
namesexbirthsyearprop
0MaryF706518800.077643
1AnnaF260418800.028618
2EmmaF200318800.022013
3ElizabethF193918800.021309
4MinnieF174618800.019188
boys = top1000[top1000["sex"] == "M"] #显示男性前1000的名字
girls = top1000[top1000["sex"] == "F"]#显示女性前1000的名字
total_births = top1000.pivot_table("births", index="year",
                                   columns="name",
                                   aggfunc=sum)  
#使用pivot_table()函数创建一个透视表。透视表的数据是top1000 DataFrame 中的"births"列,索引是"year"列,列是"name"列,聚合函数是sum,
#用于计算每年每个名字在前1000个名字中的总出生人数。
total_births.info()
subset = total_births[["John", "Harry", "Mary", "Marilyn"]]
subset.plot(subplots=True, figsize=(12, 10),
            title="Number of births per year")
#画出四个名字每年的出生人数的图
<class 'pandas.core.frame.DataFrame'>
Int64Index: 131 entries, 1880 to 2010
Columns: 6868 entries, Aaden to Zuri
dtypes: float64(6868)
memory usage: 6.9 MB





array([<AxesSubplot:xlabel='year'>, <AxesSubplot:xlabel='year'>,
       <AxesSubplot:xlabel='year'>, <AxesSubplot:xlabel='year'>],
      dtype=object)

在这里插入图片描述

plt.figure()
<Figure size 1000x600 with 0 Axes>




<Figure size 1000x600 with 0 Axes>
table = top1000.pivot_table("prop", index="year",
                            columns="sex", aggfunc=sum)
table.plot(title="Sum of table1000.prop by year and sex",
           yticks=np.linspace(0, 1.2, 13))
#使用数据透视表的 "plot" 方法进行绘图。设置了标题为 "Sum of table1000.prop by year and sex"(按年份和性别汇总的 table1000.prop 总和)。
#同时,通过设置 "yticks" 参数,将 y 轴刻度设置为从 0 到 1.2,共 13 个刻度。画出前一千个名字的比例总和
<AxesSubplot:title={'center':'Sum of table1000.prop by year and sex'}, xlabel='year'>

在这里插入图片描述

df = boys[boys["year"] == 2010]#列出2010年的男性名字比例排行。
df
namesexbirthsyearprop
260877JacobM2187520100.011523
260878EthanM1786620100.009411
260879MichaelM1713320100.009025
260880JaydenM1703020100.008971
260881WilliamM1687020100.008887
..................
261872CamiloM19420100.000102
261873DestinM19420100.000102
261874JaquanM19420100.000102
261875JaydanM19420100.000102
261876MaxtonM19320100.000102

1000 rows × 5 columns

prop_cumsum = df["prop"].sort_values(ascending=False).cumsum()#使用 cumsum() 方法计算累积总和
prop_cumsum[:10]#打印出 "prop_cumsum" 的前 10 个元素
prop_cumsum.searchsorted(0.5)#使用 searchsorted() 方法在累积总和数组 "prop_cumsum" 中搜索值为 0.5 的位置
116
df = boys[boys.year == 1900]#选择出出生年份为 1900 年的数据
in1900 = df.sort_values("prop", ascending=False).prop.cumsum() #对 "prop" 列进行降序排序,使用 cumsum() 方法计算累积总和
in1900.searchsorted(0.5) + 1 #使用 searchsorted() 方法在累积总和数组 "in1900" 中搜索值为 0.5 的位置,结果加 1 表示排名
25
def get_quantile_count(group, q=0.5):  #定义了一个名为 "get_quantile_count" 的函数
    group = group.sort_values("prop", ascending=False)  #对分组对象按 "prop" 列进行降序排序,并使用 cumsum() 方法计算累积总和
    return group.prop.cumsum().searchsorted(q) + 1  #加 1 表示排名

diversity = top1000.groupby(["year", "sex"]).apply(get_quantile_count)  #对 "top1000" DataFrame 进行按年份和性别的分组,应用定义的函数 "get_quantile_count"
diversity = diversity.unstack()#使用 unstack() 方法对 "diversity" 对象进行重塑,将性别作为列名,年份作为索引。这样可以得到一个以年份为索引,性别为列名的新的 DataFrame,其中包含了每年每个性别的分位数排名。
fig = plt.figure()#创建了一个名为 "fig" 的新图形对象,使用 matplotlib.pyplot 中的 plt.figure() 函数进行创建。
<Figure size 1000x600 with 0 Axes>
diversity.head()
diversity.plot(title="Number of popular names in top 50%")#使用 "plot" 方法绘制 "diversity" DataFrame 中的数据。通过设置 "title" 参数,指定图形的标题为 "Number of popular names in top 50%"(前50%中受欢迎的名字数量)。这将根据数据自动生成相应的图形。
<AxesSubplot:title={'center':'Number of popular names in top 50%'}, xlabel='year'>

在这里插入图片描述

def get_last_letter(x):#定义了一个名为 "get_last_letter" 的函数,该函数接受一个字符串 "x",并返回该字符串的最后一个字母。
    return x[-1]

last_letters = names["name"].map(get_last_letter) #使用 "names" DataFrame 的 "name" 列调用 "map" 方法,并传入定义的 "get_last_letter" 函数。这将返回一个 Series 对象,其中包含了每个名字的最后一个字母。然后,通过将该 Series 的名称设置为 "last_letter",创建了一个新的 Series 对象 "last_letters"
last_letters.name = "last_letter"

table = names.pivot_table("births", index=last_letters,
                          columns=["sex", "year"], aggfunc=sum)#使用 "pivot_table" 方法基于 "last_letters" 列和性别、年份的组合来计算 "births" 列的总和。结果保存在名为 "table" 的新 DataFrame 中,其中 "last_letters" 列被用作索引,性别和年份被用作列。
subtable = table.reindex(columns=[1910, 1960, 2010], level="year")
subtable.head()  
#调用 "reindex" 方法,代码创建了一个名为 "subtable" 的新 DataFrame。在 "reindex" 方法中,通过指定 "columns" 参数为 [1910, 1960, 2010],并设置 "level" 参数为 "year",将 "subtable" 重新索引为只包含这三个特定年份的列。
sexFM
year191019602010191019602010
last_letter
a108376.0691247.0670605.0977.05204.028438.0
bNaN694.0450.0411.03912.038859.0
c5.049.0946.0482.015476.023125.0
d6750.03729.02607.022111.0262112.044398.0
e133569.0435013.0313833.028655.0178823.0129012.0
subtable.sum() #对 "subtable" 进行求和操作,计算了每个字母在三个特定年份中的总出生数
letter_prop = subtable / subtable.sum() #计算了每个字母在每个年份中的出生数占该年份总出生数的比例。通过将 "subtable" 除以 "subtable.sum()",得到了一个名为 "letter_prop" 的新 DataFrame,其中包含了每个字母在各年份中的相对比例。
letter_prop
sexFM
year191019602010191019602010
last_letter
a0.2733900.3418530.3812400.0050310.0024400.014980
bNaN0.0003430.0002560.0021160.0018340.020470
c0.0000130.0000240.0005380.0024820.0072570.012181
d0.0170280.0018440.0014820.1138580.1229080.023387
e0.3369410.2151330.1784150.1475560.0838530.067959
.....................
vNaN0.0000600.0001170.0001130.0000370.001434
w0.0000200.0000310.0011820.0063290.0077110.016148
x0.0000150.0000370.0007270.0039650.0018510.008614
y0.1109720.1525690.1168280.0773490.1609870.058168
z0.0024390.0006590.0007040.0001700.0001840.001831

26 rows × 6 columns

import matplotlib.pyplot as plt

fig, axes = plt.subplots(2, 1, figsize=(10, 8))#通过调用 plt.subplots() 方法创建了一个具有两个子图的图形对象。将返回的图形对象保存在 "fig" 中,并返回的子图对象保存在 "axes" 中。设置了图形的大小为 (10, 8)。
letter_prop["M"].plot(kind="bar", rot=0, ax=axes[0], title="Male")#使用子图对象 "axes" 进行绘图。在第一个子图中,通过调用 "letter_prop["M"].plot(kind="bar", rot=0, ax=axes[0], title="Male")" 绘制了 "letter_prop" DataFrame 中 "M" 列的条形图。设置了参数 "kind" 为 "bar",表示绘制条形图;"rot" 参数为 0,表示不旋转 x 轴的刻度标签;"ax" 参数指定了绘制图形的子图对象;"title" 参数设置了子图的标题为 "Male"。
letter_prop["F"].plot(kind="bar", rot=0, ax=axes[1], title="Female",
                      legend=False)#在第二个子图中,通过调用 "letter_prop["F"].plot(kind="bar", rot=0, ax=axes[1], title="Female", legend=False)" 绘制了 "letter_prop" DataFrame 中 "F" 列的条形图。设置了相应的参数,包括绘制类型、刻度标签的旋转角度、子图对象和标题等。
<AxesSubplot:title={'center':'Female'}, xlabel='last_letter'>

在这里插入图片描述

plt.subplots_adjust(hspace=0.25)#调整子图之间的垂直间距
<Figure size 1000x600 with 0 Axes>
letter_prop = table / table.sum()#首先计算了每个字母在所有年份和性别中的出生数占总出生数的比例。通过将 "table" 除以 "table.sum()",得到一个名为 "letter_prop" 的新 DataFrame,其中包含了每个字母在各年份和性别中的相对比例。

dny_ts = letter_prop.loc[["d", "n", "y"], "M"].T #使用 "loc" 方法从 "letter_prop" DataFrame 中选择了字母为 "d"、"n" 和 "y" 的行,并选择了性别为 "M" 的列。结果为一个新的 DataFrame,命名为 "dny_ts"。通过 ".T" 转置操作,将 "dny_ts" DataFrame 进行转置,使字母成为索引,年份成为列。
dny_ts.head()#调用 "dny_ts.head()" 可以打印出 "dny_ts" 的前几行数据,显示了选定字母在男性中的相对出生数比例。
last_letterdny
year
18800.0830550.1532130.075760
18810.0832470.1532140.077451
18820.0853400.1495600.077537
18830.0840660.1516460.079144
18840.0861200.1499150.080405
plt.close("all")
fig = plt.figure()
<Figure size 1000x600 with 0 Axes>
dny_ts.plot()
<AxesSubplot:xlabel='year'>

在这里插入图片描述

all_names = pd.Series(top1000["name"].unique())  #创建了一个名为 "all_names" 的 Series 对象,其中包含了 "top1000" DataFrame 中 "name" 列中的唯一值。
lesley_like = all_names[all_names.str.contains("Lesl")]  #调用 "str.contains()" 方法,筛选出包含子字符串 "Lesl" 的名字,并将结果保存在 "lesley_like" 中。这将返回一个包含所有类似于 "Lesl" 的名字的 Series 对象。
lesley_like
632     Leslie
2294    Lesley
4262    Leslee
4728     Lesli
6103     Lesly
dtype: object
filtered = top1000[top1000["name"].isin(lesley_like)]#使用 "isin()" 方法筛选出 "top1000" DataFrame 中名字在 "lesley_like" Series 中出现的行,并将结果保存在 "filtered" DataFrame 中。
filtered.groupby("name")["births"].sum()#使用 "groupby()" 方法按照 "name" 列进行分组,并对 "births" 列进行求和。这将得到一个以名字为索引,出生数总和为值的 Series 对象。
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") #使用 "pivot_table()" 方法根据 "filtered" DataFrame 中的 "year" 列作为索引,"sex" 列作为列,并计算 "births" 列的总和。结果保存在名为 "table" 的新 DataFrame 中。
table = table.div(table.sum(axis="columns"), axis="index") #使用 "div()" 方法将 "table" DataFrame 中的每行按照列方向的和进行归一化。通过将 "table.sum(axis='columns')" 作为除数,可以将每行的值除以该行的总和。参数 "axis='index'" 表示按行方向进行归一化操作。
table.tail()#使用 "tail()" 方法打印出 "table" DataFrame 的最后几行数据,显示了归一化后的出生数数据。
sexFM
year
20061.0NaN
20071.0NaN
20081.0NaN
20091.0NaN
20101.0NaN
fig = plt.figure()
<Figure size 1000x600 with 0 Axes>
table.plot(style={"M": "k-", "F": "k--"})#设置 "style" 参数为 {"M": "k-", "F": "k--"},指定了不同性别的线条样式。"M" 代表男性,使用黑色实线 "k-" 绘制;"F" 代表女性,使用黑色虚线 "k--" 绘制。
<AxesSubplot:xlabel='year'>

在这里插入图片描述

3.美国农业部视频数据库

美国农业部提供了食物营养信息数据库。每种事务都有一些识别属性以及两份营养元素和营养比例的列表。这种形式的数据不适合分析,所以需要做一些工作将数据转换成更好的形式。

import json
db = json.load(open("datasets/usda_food/database.json"))
len(db)
6636
db[0].keys() #返回第一个对象的所有键,显示JSON对象的键名称列表。
db[0]["nutrients"][0] #返回第一个对象的“nutrients”键中的第一个元素,是一个具有特定营养信息的字典。
nutrients = pd.DataFrame(db[0]["nutrients"]) #把第一个对象的“nutrients”键的值转换为一个数据框(DataFrame),这是一个用于处理表格数据的数据结构。
nutrients.head(7)
valueunitsdescriptiongroup
025.18gProteinComposition
129.20gTotal lipid (fat)Composition
23.06gCarbohydrate, by differenceComposition
33.28gAshOther
4376.00kcalEnergyEnergy
539.28gWaterComposition
61573.00kJEnergyEnergy
info_keys = ["description", "group", "id", "manufacturer"]  #定义键
info = pd.DataFrame(db, columns=info_keys) #以键为列定义info为df
info.head() 
info.info() #显示关于数据框的一些基本信息,包括每列的名称、非空值的数量以及每列的数据类型
<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"列的值的频数,并按频数降序排序。显示前十行
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 rec in db:
    fnuts = pd.DataFrame(rec["nutrients"])
    fnuts["id"] = rec["id"]
    nutrients.append(fnuts)
#使用循环遍历db中的每个对象。对于每个对象,将其"nutrients"键的值转换为一个数据框,并添加一个名为"id"的列,该列的值为该对象的"id"键的值。然后将该数据框添加到nutrients列表中。
nutrients = pd.concat(nutrients, ignore_index=True) #将nutrients列表中的所有数据框合并为一个大的数据框,并使用ignore_index=True重新索引所有的行,以确保行索引是唯一的。
nutrients
valueunitsdescriptiongroupid
025.180gProteinComposition1008
129.200gTotal lipid (fat)Composition1008
23.060gCarbohydrate, by differenceComposition1008
33.280gAshOther1008
4376.000kcalEnergyEnergy1008
..................
3893500.000mcgVitamin B-12, addedVitamins43546
3893510.000mgCholesterolOther43546
3893520.072gFatty acids, total saturatedOther43546
3893530.028gFatty acids, total monounsaturatedOther43546
3893540.041gFatty acids, total polyunsaturatedOther43546

389355 rows × 5 columns

nutrients.duplicated().sum()  # 计算nutrients数据框中的重复行数
nutrients = nutrients.drop_duplicates() #从nutrients数据框中删除重复的行
col_mapping = {"description" : "food",
               "group"       : "fgroup"}
info = info.rename(columns=col_mapping, copy=False)
info.info()  #将 "description" 列重命名为 "food",将 "group" 列重命名为 "fgroup"。
col_mapping = {"description" : "nutrient",
               "group" : "nutgroup"}  #将 "description" 列重命名为 "nutrient",将 "group" 列重命名为 "nutgroup"。
nutrients = nutrients.rename(columns=col_mapping, copy=False)
nutrients  #获取更新后 info 数据框的基本信息。
<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
valueunitsnutrientnutgroupid
025.180gProteinComposition1008
129.200gTotal lipid (fat)Composition1008
23.060gCarbohydrate, by differenceComposition1008
33.280gAshOther1008
4376.000kcalEnergyEnergy1008
..................
3893500.000mcgVitamin B-12, addedVitamins43546
3893510.000mgCholesterolOther43546
3893520.072gFatty acids, total saturatedOther43546
3893530.028gFatty acids, total monounsaturatedOther43546
3893540.041gFatty acids, total polyunsaturatedOther43546

375176 rows × 5 columns

ndata = pd.merge(nutrients, info, on="id") #使用"id"列作为键将nutrients和info两个数据框进行合并
ndata.info()#显示关于ndata数据框的基本信息,包括每列的名称、非空值的数量以及每列的数据类型。
ndata.iloc[30000] #返回ndata数据框中第30000行的内容。这将提供该行的所有列值
<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+ MB





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 size 1000x600 with 0 Axes>
result = ndata.groupby(["nutrient", "fgroup"])["value"].quantile(0.5)
result["Zinc, Zn"].sort_values().plot(kind="barh") #绘制水平条形图,其中显示了"Zinc, Zn"营养物质的中位数结果,并按从小到大的顺序进行排序。
<AxesSubplot:ylabel='fgroup'>

在这里插入图片描述

by_nutrient = ndata.groupby(["nutgroup", "nutrient"])

def get_maximum(x): 
    return x.loc[x.value.idxmax()]
#定义了一个名为get_maximum的函数来获取每个分组中具有最大值的行
max_foods = by_nutrient.apply(get_maximum)[["value", "food"]]
#得到一个新的数据框max_foods,其中包含每个分组中具有最大值的行的"value"和"food"列。
# make the food a little smaller
max_foods["food"] = max_foods["food"].str[:50] #使用.str[:50]将"food"列的文本截断为最多50个字符
max_foods.loc["Amino Acids"]["food"]#获取该营养物质组中具有最大值的食物的名称。
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, ORIGINAL RE
Isoleucine        Soy protein isolate, PROTEIN TECHNOLOGIES INTERNAT
Leucine           Soy protein isolate, PROTEIN TECHNOLOGIES INTERNAT
Lysine            Seal, bearded (Oogruk), meat, dried (Alaska Native
Methionine                     Fish, cod, Atlantic, dried and salted
Phenylalanine     Soy protein isolate, PROTEIN TECHNOLOGIES INTERNAT
Proline                            Gelatins, dry powder, unsweetened
Serine            Soy protein isolate, PROTEIN TECHNOLOGIES INTERNAT
Threonine         Soy protein isolate, PROTEIN TECHNOLOGIES INTERNAT
Tryptophan          Sea lion, Steller, meat with fat (Alaska Native)
Tyrosine          Soy protein isolate, PROTEIN TECHNOLOGIES INTERNAT
Valine            Soy protein isolate, PROTEIN TECHNOLOGIES INTERNAT
Name: food, dtype: object

4.2012年联邦选举委员会数据库

美国联邦选举委员会公布了有关政治运动贡献的数据。这些数据包括捐赠者姓名、职业和雇主、地址和缴费金额。你可以尝试做一下的分析:
按职业和雇主的捐赠统计
按捐赠金额统计
按州进行统计

fec = pd.read_csv("datasets/fec/P00000001-ALL.csv", low_memory=False)
fec.info()
<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[123456]#返回在索引位置123456处的行数据。
cmte_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" 数据框中 "cand_nm" 列中唯一的候选人姓名
unique_cands #显示所有唯一的候选人姓名
unique_cands[2]#返回数组中索引为2的元素,即第3个唯一候选人的姓名
'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] #返回在索引位置123456到123460之间的行中的 "cand_nm" 列的值
fec["cand_nm"][123456:123461].map(parties) #对这些行中的候选人姓名应用名为 parties 的函数
# Add it as a column
fec["party"] = fec["cand_nm"].map(parties) #根据候选人姓名映射政党
fec["party"].value_counts() #计算 "party" 列中每个政党的频数,并返回一个包含每个政党及其频数的结果。
Democrat      593746
Republican    407985
Name: party, dtype: int64
(fec["contb_receipt_amt"] > 0).value_counts() #计算 "contb_receipt_amt" 列中大于0的值的频数
True     991475
False     10256
Name: contb_receipt_amt, dtype: int64
fec = fec[fec["contb_receipt_amt"] > 0] #筛选出 "contb_receipt_amt" 列中值大于0的行
fec_mrbo = fec[fec["cand_nm"].isin(["Obama, Barack", "Romney, Mitt"])]#筛选出 "cand_nm" 列中候选人姓名为 "Obama, Barack" 和 "Romney, Mitt" 的行。
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 = {
   "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):
    # If no mapping provided, return x
    return occ_mapping.get(x, x)
#将职业名称进行映射转换。如果职业名称在 occ_mapping 中有映射值,则返回映射后的值;否则,返回原始值。
fec["contbr_occupation"] = fec["contbr_occupation"].map(get_occ)
#更新 "fec" 数据框中的 "contbr_occupation" 列,将其中的职业名称进行映射转换。
emp_mapping = {
   "INFORMATION REQUESTED PER BEST EFFORTS" : "NOT PROVIDED",
   "INFORMATION REQUESTED" : "NOT PROVIDED",
   "SELF" : "SELF-EMPLOYED",
   "SELF EMPLOYED" : "SELF-EMPLOYED",
}

def get_emp(x):
    # If no mapping provided, return x
    return emp_mapping.get(x, x)
#将雇主名称进行映射转换。如果雇主名称在 emp_mapping 中有映射值,则返回映射后的值;否则,返回原始值。
fec["contbr_employer"] = fec["contbr_employer"].map(get_emp)
#应用 get_emp 函数到 "contbr_employer" 列,fec["contbr_employer"] = fec["contbr_employer"].map(get_emp) 将更新 "fec" 数据框中的 "contbr_employer" 列,将其中的雇主名称进行映射转换。
by_occupation = fec.pivot_table("contb_receipt_amt",
                                index="contbr_occupation",
                                columns="party", aggfunc="sum") #计算了每个职业在每个政党下的捐赠总额。职业作为索引,政党作为列,"contb_receipt_amt" 列的值被聚合为总和。
over_2mm = by_occupation[by_occupation.sum(axis="columns") > 2000000]  #使用 sum(axis="columns") > 2000000 来计算每个职业的总捐赠额,并与2000000进行比较,返回布尔值的结果。获取总捐赠额超过2000000的职业
over_2mm
partyDemocratRepublican
contbr_occupation
ATTORNEY11141982.977477194.43
CEO2074974.794211040.52
CONSULTANT2459912.712544725.45
ENGINEER951525.551818373.70
EXECUTIVE1355161.054138850.09
HOMEMAKER4248875.8013634275.78
INVESTOR884133.002431768.92
LAWYER3160478.87391224.32
MANAGER762883.221444532.37
NOT PROVIDED4866973.9620565473.01
OWNER1001567.362408286.92
PHYSICIAN3735124.943594320.24
PRESIDENT1878509.954720923.76
PROFESSOR2165071.08296702.73
REAL ESTATE528902.091625902.25
RETIRED25305116.3823561244.49
SELF-EMPLOYED672393.401640252.54
plt.figure()
<Figure size 1000x600 with 0 Axes>




<Figure size 1000x600 with 0 Axes>
over_2mm.plot(kind="barh")#绘制一个水平条形图,显示 over_2mm 数据透视表中的职业及其在每个政党下的捐赠总额。
<AxesSubplot:ylabel='contbr_occupation'>

在这里插入图片描述

def get_top_amounts(group, key, n=5): 
    totals = group.groupby(key)["contb_receipt_amt"].sum()#使用 group.groupby(key) 将分组按键进行分组。对每个分组,使用 .sum() 对 contb_receipt_amt 列进行求和,得到每个键的总金额。
    return totals.nlargest(n) #使用 .nlargest(n) 选择总金额前 n 个最大的键值对。
grouped = fec_mrbo.groupby("cand_nm")
grouped.apply(get_top_amounts, "contbr_occupation", n=7) #调用了自定义函数 get_top_amounts,并将 "contbr_occupation" 列作为键,设置参数 n=7 来获取每个候选人下出现金额最多的前 7 个职业。
grouped.apply(get_top_amounts, "contbr_employer", n=10) #使用 grouped.apply(get_top_amounts, "contbr_employer", n=10) 调用了 get_top_amounts 函数,并将 "contbr_employer" 列作为键,设置参数 n=10 来获取每个候选人下出现金额最多的前 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
Name: contb_receipt_amt, dtype: float64
bins = np.array([0, 1, 10, 100, 1000, 10000,
                 100_000, 1_000_000, 10_000_000])  #定义了将捐赠金额划分为不同范围的箱子。
labels = pd.cut(fec_mrbo["contb_receipt_amt"], bins) #使用 pd.cut() 函数将 "fec_mrbo" 数据框中的 "contb_receipt_amt" 列中的数值根据指定的边界进行分箱,并为每个数值分配对应的箱子标签。
labels
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]) #对 "fec_mrbo" 数据框按照 "cand_nm" 和 labels 进行分组,并将结果存储在名为 "grouped" 的对象中。
grouped.size().unstack(level=0) #使用 .size() 方法计算每个分组的大小(即计数),并使用 .unstack(level=0) 将多级索引的结果重塑为以 "cand_nm" 为列的形式。
cand_nmObama, BarackRomney, Mitt
contb_receipt_amt
(0, 1]49377
(1, 10]400703681
(10, 100]37228031853
(100, 1000]15399143357
(1000, 10000]2228426186
(10000, 100000]21
(100000, 1000000]30
(1000000, 10000000]40
plt.figure()
<Figure size 1000x600 with 0 Axes>




<Figure size 1000x600 with 0 Axes>
bucket_sums = grouped["contb_receipt_amt"].sum().unstack(level=0) #计算了每个分组中 "contb_receipt_amt" 列的总和,并使用 .unstack(level=0) 将多级索引的结果重塑为以候选人为列的形式
normed_sums = bucket_sums.div(bucket_sums.sum(axis="columns"),
                              axis="index") #将总捐赠金额除以每个行(每个捐赠金额范围)上的总和,以计算每个候选人在每个捐赠金额范围内的捐赠金额的相对比例
normed_sums #显示标准化后的捐赠金额比例,其中每个行代表不同的捐赠金额范围,每个列代表不同的候选人。
normed_sums[:-2].plot(kind="barh") #绘制一个水平条形图,显示标准化后的捐赠金额比例。这将显示不同捐赠金额范围内的候选人之间的比较,但排除了最后两个候选人。
<AxesSubplot:ylabel='contb_receipt_amt'>

在这里插入图片描述

grouped = fec_mrbo.groupby(["cand_nm", "contbr_st"]) #对 "fec_mrbo" 数据框按照 "cand_nm" 和 "contbr_st" 进行分组
totals = grouped["contb_receipt_amt"].sum().unstack(level=0).fillna(0) #计算了每个分组中 "contb_receipt_amt" 列的总和,并使用 .unstack(level=0) 将多级索引的结果重塑为以候选人为列的形式。然后,使用 .fillna(0) 填充缺失值为0。
totals = totals[totals.sum(axis="columns") > 100000] #筛选出总捐赠金额超过100000的行。
totals.head(10) #显示前10行的结果
cand_nmObama, BarackRomney, Mitt
contbr_st
AK281840.1586204.24
AL543123.48527303.51
AR359247.28105556.00
AZ1506476.981888436.23
CA23824984.2411237636.60
CO2132429.491506714.12
CT2068291.263499475.45
DC4373538.801025137.50
DE336669.1482712.00
FL7318178.588338458.81
percent = totals.div(totals.sum(axis="columns"), axis="index") #将每个州内每个候选人的捐赠金额除以该州的总和,计算了每个州内每个候选人的捐赠金额在该州总捐赠金额中的比例。
percent.head(10)
cand_nmObama, BarackRomney, Mitt
contbr_st
AK0.7657780.234222
AL0.5073900.492610
AR0.7729020.227098
AZ0.4437450.556255
CA0.6794980.320502
CO0.5859700.414030
CT0.3714760.628524
DC0.8101130.189887
DE0.8027760.197224
FL0.4674170.532583
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值