本篇文章给大家谈谈用python做数据分析案例,以及python数据分析案例教程,希望对各位有所帮助,不要忘了收藏本站喔。
Source code download: 本文相关源码
1.1数据简介:
GroupLens实验室提供了一些从MoviesLens用户那里收集的20世纪90年代末到21世纪初的电影评分数据的集合。浙西额数据提供了电影的评分、流派、年份和观众数据(年龄、邮编、性别、职业)用python代码画雪人。
MovisLens1M数据集包含6000个用户对4000部电影的100万个评分。数据分布在三个表格之中:分别包含评分、用户信息和电影信息。
1.2代码(我是anaconda和jupyter两个软件联合进行的编码)
1.2.1python包的引用
import matplotlib.pyplot as plt import numpy as np import pandas as pd import matplotlib %matplotlib inline #在jupyter notebook中需要这一行,在pycharm中不需要 |
这是我在数据分析的过程中所运用到的python包。
1.2.2数据的调入
unames = ["user_id", "gender", "age", "occupation", "zip"] rnames = ["user_id", "movie_id", "rating", "timestamp"] mnames = ["movie_id", "title", "genres"] |
使用pandas库中的pd.read_table()
函数从MovieLens数据集的三个文件中读取数据。这些文件包括users.dat
、ratings.dat
和movies.dat
。
1.2.3数据的处理
users.head(5) ratings.head(5) movies.head(5) ratings #jupyter notebook 不用print也能有图像 |
可以使用head()
函数来查看数据框的前几行。
data = pd.merge(pd.merge(ratings, users), movies) data data.iloc[0] |
这段代码将合并ratings
、users
和movies
三个数据框,并将结果存储在data
变量中。通过打印data
,您可以查看合并后的数据框的内容。要访问data
中的特定行,可以使用.iloc[]
方法。
mean_ratings = data.pivot_table("rating", index="title", columns="gender", aggfunc="mean") mean_ratings.head(5) |
在使用pivot_table()
函数计算基于性别的电影评分的平均值,
pivot_table()
函数用于创建一个透视表,其中"rating"列作为值,"title"列作为行索引,"gender"列作为列索引,并使用"mean"聚合函数计算平均值。
通过打印mean_ratings.head(5)
,您可以查看计算得到的透视表的前5行,其中显示了每个电影标题的不同性别的平均评分。
ratings_by_title = data.groupby("title").size() ratings_by_title.head() active_titles = ratings_by_title.index[ratings_by_title >= 250] active_titles |
groupby()
函数对data
数据框按照电影标题("title")进行分组,并使用size()
函数计算每个电影标题的出现次数。.head()
方法打印出计算得到的分组结果的前几行。ratings_by_title >= 250
来创建一个布尔索引,筛选出评分次数至少为250次的电影标题。然后,使用.index
属性获取这些电影标题的索引,并将结果存储在active_titles
变量中。通过打印active_titles
,您可以查看筛选得到的活跃电影标题。mean_ratings = mean_ratings.loc[active_titles] mean_ratings |
这段代码使用.loc[]
索引器根据活跃电影标题的索引,从mean_ratings
数据框中选择相应的行。
通过打印mean_ratings
,您将得到筛选后的mean_ratings
数据框,其中只包含活跃电影标题,并显示了每个电影标题的不同性别的平均评分。
mean_ratings = mean_ratings.rename(index={"Seven Samurai (The Magnificent Seven) (Shichinin no samurai) (1954)": top_female_ratings = mean_ratings.sort_values("F", ascending=False) |
.rename()
方法用于重命名索引,将"Seven Samurai (The Magnificent Seven) (Shichinin no samurai) (1954)"修改为"Seven Samurai (Shichinin no samurai) (1954)",以便更好地匹配索引值。
然后,使用.sort_values()
方法按照女性评分("F")对mean_ratings
数据框进行降序排序,并将结果存储在top_female_ratings
变量中。
通过打印top_female_ratings.head()
,您可以查看按照女性评分排序后的前几行数据,这些行显示了女性对电影的评分情况。
mean_ratings["diff"] = mean_ratings["M"] - mean_ratings["F"] sorted_by_diff = mean_ratings.sort_values("diff") |
通过计算男性评分("M")与女性评分("F")之间的差异,创建了一个新的名为"diff"的列,并将结果存储在mean_ratings
数据框中。
然后,使用.sort_values()
方法按照"diff"列的值对mean_ratings
数据框进行排序,并将结果存储在sorted_by_diff
变量中。
通过打印sorted_by_diff.head()
,您可以查看按照差异值排序后的前几行数据,这些行显示了男性评分与女性评分之间差异最大的电影。
sorted_by_diff[::-1].head() |
在这段代码中,[::-1]
用于对sorted_by_diff
数据框进行逆序操作,即将数据框的行顺序反转。
通过打印sorted_by_diff[::-1].head()
,您将得到逆序后的前几行数据,这些行显示了女性评分高于男性评分的电影。
rating_std_by_title = data.groupby("title")["rating"].std() rating_std_by_title = rating_std_by_title.loc[active_titles] rating_std_by_title.head() |
,首先使用groupby()
函数对data
数据框按照电影标题("title")进行分组,并计算每个电影标题的评分("rating")的标准差,将结果存储在rating_std_by_title
变量中。
然后,使用.loc[]
索引器根据活跃电影标题的索引,从rating_std_by_title
中选择相应的行。
通过打印rating_std_by_title.head()
,您可以查看计算得到的活跃电影标题的评分标准差的前几行数据。
rating_std_by_title.sort_values(ascending=False)[:10] |
.sort_values()
方法用于按照评分标准差进行降序排序。
通过打印rating_std_by_title.sort_values(ascending=False)[:10]
,您将得到按照评分标准差降序排序的前10个电影,这些电影具有最高的评分标准差。
movies["genres"].head() movies["genres"].head().str.split("|") movies["genre"] = movies.pop("genres").str.split("|") movies.head() |
首先通过movies["genres"].head()
打印出"genres"列的前几行数据,以便查看原始数据。
接下来,使用.str.split("|")
将"genres"列中的每个元素按照"|"进行拆分,返回一个包含拆分后结果的Series对象。
然后,使用movies["genre"] = movies.pop("genres").str.split("|")
将拆分后的结果存储到一个新的列"genre"中,并从原始数据框中删除"genres"列。
最后,通过打印movies.head()
,您将得到包含新的"genre"列的数据框,显示了每个电影的多个分类。
movies_exploded = movies.explode("genre") movies_exploded[:10] |
使用.explode()
方法对"genre"列进行展开操作,将每个电影的每个分类单独显示。展开后的结果存储在新的数据框movies_exploded
中。
通过打印movies_exploded[:10]
,您将得到展开后的前10行数据,每行显示一个电影的一个分类。
ratings_with_genre = pd.merge(pd.merge(movies_exploded, ratings), users) ratings_with_genre.iloc[0] genre_ratings = (ratings_with_genre.groupby(["genre", "age"]) ["rating"].mean() .unstack("age")) genre_ratings[:10] |
pd.merge()
函数将展开后的movies_exploded
、ratings
和users
数据框进行合并,以创建包含电影分类的评分数据框ratings_with_genre
。.iloc[0]
索引器来获取ratings_with_genre
数据框中的第一行数据。groupby()
函数按照分类和年龄进行分组,并计算每个分类和年龄组的平均评分。.unstack("age")
将年龄作为列索引重新排列数据框。2.1数据简介
美国社会保障局(SSA)提供了从1880年至现在的婴儿姓名频率的数据。可以使用这些数据做很多事情:
根据给定的名字对婴儿名字随时间的比例进行可视化
确定一个名字的相对排位
确定每年最受欢迎的名字,或者流行程度最高或最低的名字
2.2代码
2.2.1数据读入
names1880 = pd.read_csv("datasets/babynames/yob1880.txt", names=["name", "sex", "births"]) names1880 |
将读取名为"datasets/babynames/yob1880.txt"的文件,并将列名分别指定为"name"、"sex"和"births"。结果将存储在names1880
数据框中。
通过打印names1880
,您将获得读取的文件中的数据,其中包含每个名字、性别和出生数。
names1880.groupby("sex")["births"].sum() |
使用.groupby()
函数按性别("sex")对names1880
数据框进行分组,然后通过索引器["births"]
选择"births"列,并使用.sum()
函数计算每个性别的出生总数。
pieces = [] # Add a column for the year # Concatenate everything into a single DataFrame names |
循环遍历从1880年到2010年的年份,构建每个年份对应的文件路径,然后使用pd.read_csv()
函数读取每个文件,并为各列指定列名为"name"、"sex"和"births"。接着,为每个数据框添加一个名为"year"的列,其值为对应的年份。
最后,使用pd.concat()
函数将所有数据框拼接成一个单独的数据框names
,并使用ignore_index=True
忽略原始数据框的索引,生成一个新的连续索引。
通过运行上述代码,您将得到一个名为names
的数据框,其中包含了从1880年到2010年的所有年份的姓名、性别、出生数和年份信。
total_births = names.pivot_table("births", index="year", columns="sex", aggfunc=sum) total_births.tail() total_births.plot(title="Total births by sex and year") |
使用pivot_table()
函数计算每年每个性别的总出生数。将"births"作为值,"year"作为行索引,"sex"作为列索引,并使用sum
聚合函数计算总出生数。结果存储在total_births
数据框中。
通过打印total_births.tail()
,您将查看total_births
数据框的最后几行,显示了每年每个性别的总出生数。
接下来,使用.plot()
函数绘制出每年总出生数的图表,标题为"Total births by sex and year"。
def add_prop(group): names |
add_prop
函数将每个分组中的"births"列除以该分组中的出生总数,计算每个名字在该年份和性别组合中的比例,并将结果存储在"prop"列中。
接下来,使用groupby()
函数对names
数据框按年份和性别进行分组,并通过.apply(add_prop)
应用add_prop
函数,将每个分组应用到函数上,以添加"prop"列。
通过打印names
,您将得到已经添加了"prop"列的names
数据框,其中包含每个名字在对应年份和性别组合中的比例。
names.groupby(["year", "sex"])["prop"].sum() |
使用groupby()
函数按照年份("year")和性别("sex")对names
数据框进行分组,并选择"prop"列。然后,使用.sum()
函数计算每个分组中"prop"列的总和。
def get_top1000(group): return group.sort_values("births", ascending=False)[:1000] grouped = names.groupby(["year", "sex"]) top1000 = grouped.apply(get_top1000) top1000.head() |
top1000 = top1000.reset_index(drop=True) top1000.head() |
get_top1000
函数接收一个分组,并按照"births"列的值降序排序。然后,使用[:1000]
选择排序后的前1000个记录。
接下来,使用groupby()
函数对names
数据框按年份和性别进行分组,并通过.apply(get_top1000)
应用get_top1000
函数,将每个分组应用到函数上,以获取每个组合中的前1000个记录。
通过打印top1000.head()
,您将得到按年份和性别获取的前1000个记录,这些记录是按照出生数降序排序的。
boys = top1000[top1000["sex"] == "M"] total_births = top1000.pivot_table("births", index="year", total_births.info() |
根据"sex"列的值,将top1000
数据框拆分为boys
和girls
两个数据框,分别包含男孩和女孩的记录。
然后,使用pivot_table()
函数计算每年每个名字的总出生数。将"births"作为值,"year"作为行索引,"name"作为列索引,并使用sum
聚合函数计算总出生数。结果存储在total_births
数据框中。
通过打印total_births.info()
,您将查看total_births
数据框的相关信息,包括列名和非空值的数量。
接下来,选择部分名字的列,包括"John"、"Harry"、"Mary"和"Marilyn",存储在subset
数据框中。
最后,使用.plot()
方法绘制subset
数据框的子图,设置图形大小为(12, 10),标题为"Number of births per year"。
plt.figure() table = top1000.pivot_table("prop", index="year", |
plt.figure()
用于创建一个新的图形窗口。
接下来,使用pivot_table()
函数对top1000
数据框进行透视,计算每年每个性别的"prop"列的总和。将"prop"作为值,"year"作为行索引,"sex"作为列索引,并使用sum
聚合函数计算总和。结果存储在table
数据框中。
然后,使用.plot()
方法绘制透视表的图表。设置标题为"Sum of top1000.prop by year and sex",设置y轴刻度为0到1.2之间的13个均匀间隔刻度。
df = boys[boys["year"] == 2010] df |
选择了boys
数据框中"year"列等于2010的记录,并将结果存储在名为df
的新数据框中。
prop_cumsum = df["prop"].sort_values(ascending=False).cumsum() df = boys[boys.year == 1900] def get_quantile_count(group, q=0.5): diversity = top1000.groupby(["year", "sex"]).apply(get_quantile_count) fig = plt.figure() diversity.head() |
首先计算了df["prop"]
列按降序排序后的累积和,并存储在prop_cumsum
中。然后,使用prop_cumsum[:10]
查看前10个累积和的值,并使用prop_cumsum.searchsorted(0.5)
查找累积和大于等于0.5的索引位置。
接下来,选择了年份为1900的男孩名字数据,并按照"prop"列的值降序排序,计算了累积和,并使用in1900.searchsorted(0.5) + 1
查找累积和大于等于0.5的索引位置并加1。
然后,定义了一个名为get_quantile_count
的函数,用于计算每个分组中累积和大于等于指定分位数的个数。
使用top1000.groupby(["year", "sex"]).apply(get_quantile_count)
应用该函数,对top1000
数据框按年份和性别进行分组,计算每个分组中累积和大于等于指定分位数的个数。然后,使用.unstack()
将结果转换为透视表形式。
创建一个新的图形窗口fig = plt.figure()
。
通过打印diversity.head()
,您将查看转换后的diversity
数据框的前几行数据。
最后,使用.plot()
方法绘制diversity
数据框的图表,设置标题为"Number of popular names in top 50%"。
def get_last_letter(x): last_letters = names["name"].map(get_last_letter) table = names.pivot_table("births", index=last_letters, subtable = table.reindex(columns=[1910, 1960, 2010], level="year") |
定义了一个名为get_last_letter
的函数,用于获取给定字符串的最后一个字母。然后,您将names
数据框中的"name"列应用该函数,得到一个包含名字最后一个字母的Series对象,并将其命名为"last_letter"。
接下来,您使用pivot_table()
函数计算了根据名字最后一个字母、性别和年份的出生数的透视表,并将结果存储在table
中。
然后,使用reindex()
方法选择特定的年份列(1910、1960和2010),并重新按照"year"级别对透视表进行索引重排,结果存储在subtable
中。
subtable.sum() letter_prop = subtable / subtable.sum() letter_prop |
调用subtable.sum()
,您计算了subtable
中每个名字最后一个字母、性别和年份组合的出生数的总和。
接下来,使用除法操作符/
,您计算了subtable
中每个组合的占比,并将结果存储在letter_prop
中。这个操作会将subtable
中的每个值除以对应列的总和。
通过打印subtable.sum()
,您将查看subtable
中每个组合的出生数总和。
通过打印letter_prop
,您将查看每个组合的占比情况,其中每个值表示对应组合的出生数占列总和的比例。
import matplotlib.pyplot as plt fig, axes = plt.subplots(2, 1, figsize=(10, 8)) |
plt.subplots(2, 1, figsize=(10, 8))
创建了一个包含两个子图的图形窗口,其中第一个数字2表示行数,第二个数字1表示列数。figsize=(10, 8)
指定了图形窗口的大小。
然后,使用.plot(kind="bar", rot=0, ax=axes[0], title="Male")
在第一个子图中绘制了男性名字最后一个字母占比的条形图。rot=0
设置了x轴标签的旋转角度为0度,ax=axes[0]
指定了绘图的目标子图,title="Male"
设置了子图的标题为"Male"。
接下来,使用.plot(kind="bar", rot=0, ax=axes[1], title="Female", legend=False)
在第二个子图中绘制了女性名字最后一个字母占比的条形图。rot=0
设置了x轴标签的旋转角度为0度,ax=axes[1]
指定了绘图的目标子图,title="Female"
设置了子图的标题为"Female",legend=False
禁用了图例的显示。
通过运行上述代码,您将获得一个包含两个子图的图形窗口,每个子图都显示了男性或女性名字最后一个字母占比的条形图。
plt.subplots_adjust(hspace=0.25) letter_prop = table / table.sum() dny_ts = letter_prop.loc[["d", "n", "y"], "M"].T |
使用plt.subplots_adjust(hspace=0.25)
,您调整了子图之间的垂直间距,使得它们之间的间距为0.25个单位。
然后,更新了letter_prop
数据框,将table
中每个值除以对应列的总和,以计算名字占比。
接下来,使用.loc[["d", "n", "y"], "M"].T
选择了"letter_prop"数据框中名字最后一个字母为"d"、"n"和"y"的男性名字占比,并进行转置操作,以使每个字母成为列。结果存储在dny_ts
数据框中。
通过打印dny_ts.head()
,您将查看dny_ts
数据框的前几行数据,显示了名字最后一个字母为"d"、"n"和"y"的男性名字占比情况。
plt.close("all") fig = plt.figure() dny_ts.plot() |
通过调用plt.close("all")
,关闭了所有的图形窗口,以确保开始一个新的空白图形窗口。
然后,使用plt.figure()
创建了一个新的图形窗口fig
。
最后,使用dny_ts.plot()
绘制了dny_ts
数据框的折线图。
all_names = pd.Series(top1000["name"].unique()) lesley_like = all_names[all_names.str.contains("Lesl")] lesley_like |
通过top1000["name"].unique()
获取了top1000
数据框中所有唯一的名字,并创建了一个名为all_names
的Series。
接下来,使用all_names.str.contains("Lesl")
筛选出包含"Lesl"的名字,将结果存储在lesley_like
中。str.contains("Lesl")
表示通过字符串匹配判断是否包含"Lesl"。
通过打印lesley_like
,您将得到包含"Lesl"的名字的列表。
filtered = top1000[top1000["name"].isin(lesley_like)] filtered.groupby("name")["births"].sum() |
使用top1000["name"].isin(lesley_like)
筛选出top1000
数据框中名字包含在lesley_like
列表中的记录,将结果存储在filtered
中。
然后,使用.groupby("name")["births"].sum()
对filtered
数据框进行分组,按名字("name")列进行分组,并计算每个名字的总出生数("births")。
通过打印上述代码的结果,您将得到按名字分组的每个名字的总出生数。
table = filtered.pivot_table("births", index="year", columns="sex", aggfunc="sum") table = table.div(table.sum(axis="columns"), axis="index") table.tail() |
使用filtered.pivot_table("births", index="year", columns="sex", aggfunc="sum")
创建了一个透视表table
,计算了每年每个性别的出生数。
接下来,使用.div(table.sum(axis="columns"), axis="index")
将透视表的每个值除以对应行的总和,以计算每年每个性别的比例。table.sum(axis="columns")
计算了每行的总和,axis="index"
表示按行进行除法运算。
通过打印table.tail()
,您将查看透视表table
的最后几行,显示了每年每个性别的出生数和比例。
fig = plt.figure() table.plot(style={"M": "k-", "F": "k--"}) |
使用plt.figure()
创建了一个新的图形窗口fig
。
然后,使用.plot()
方法绘制了table
数据框中的男性和女性出生数的折线图。通过style={"M": "k-", "F": "k--"}
指定了男性线条的样式为黑色实线("k-"
),女性线条的样式为黑色虚线("k--"
)。
通过运行上述代码,您将获得一个包含男性和女性出生数的折线图的图形窗口。
3.1数据简介
美国农业部提供了食物营养信息数据库。每种事务都有一些识别属性以及两份营养元素和营养比例的列表。这种形式的数据不适合分析,所以需要做一些工作将数据转换成更好的形式。
3.2.1数据引用
import json db = json.load(open("datasets/usda_food/database.json")) len(db) |
3.2.2数据处理
db[0].keys() db[0]["nutrients"][0] nutrients = pd.DataFrame(db[0]["nutrients"]) nutrients.head(7) |
db[0].keys()
用于获取db
中第一个元素的所有键,即该元素的属性名称。
接下来,db[0]["nutrients"][0]
用于获取db
中第一个元素的"nutrients"键的第一个元素的值。
然后,使用pd.DataFrame()
将db[0]["nutrients"]
转换为DataFrame,并将结果存储在名为nutrients
的变量中。
最后,使用.head(7)
打印nutrients
DataFrame的前7行数据。
info_keys = ["deion", "group", "id", "manufacturer"] info = pd.DataFrame(db, columns=info_keys) info.head() info.info() |
info_keys
是一个列表,包含了要从db
中提取的属性名称。
然后,使用pd.DataFrame(db, columns=info_keys)
创建了一个DataFrame info
,其中db
是作为数据源,columns=info_keys
指定了要包含的列。这样,info
DataFrame将仅包含指定的属性列,并且数据将来自db
。
接下来,使用.head()
打印info
DataFrame的前几行数据。
最后,使用.info()
打印info
DataFrame的基本信息,包括列名、非空值数量以及每列的数据类型等。
pd.value_counts(info["group"])[:10] |
info["group"]
选择了info
DataFrame中的"group"列。
然后,使用pd.value_counts()
对"group"列的值进行计数,返回一个Series对象,其中索引是唯一的"group"值,而值是每个"group"值出现的次数。
通过[:10]
选择了计数最高的前10个组,以便查看它们的计数结果。
nutrients = [] for rec in db: nutrients = pd.concat(nutrients, ignore_index=True) nutrients |
首先创建了一个空列表nutrients
,用于存储每个食物元素的营养信息。
然后,使用for
循环遍历db
列表中的每个元素。对于每个元素,使用pd.DataFrame(rec["nutrients"])
将其中的"nutrients"信息转换为一个DataFrame,并存储在名为fnuts
的临时DataFrame中。
接下来,通过fnuts["id"] = rec["id"]
为临时DataFrame添加一个"id"列,该列的值为当前食物元素的"id"。
然后,将临时DataFrame对象fnuts
添加到nutrients
列表中。
最后,使用pd.concat(nutrients, ignore_index=True)
将nutrients
列表中的DataFrame对象合并为一个单独的DataFrame,通过ignore_index=True
重新生成索引,以确保索引是连续的。
通过打印nutrients
,您将获得合并后的DataFrame,其中包含所有食物元素的营养信息。
nutrients.duplicated().sum() # number of duplicates col_mapping = {"deion" : "food", |
nutrients.duplicated().sum()
计算了nutrients
DataFrame中的重复行数,并返回该数量。
然后,使用.drop_duplicates()
方法从nutrients
DataFrame中删除重复的行。
接下来,您使用col_mapping
字典将info
DataFrame中的列名进行重命名。info.rename(columns=col_mapping, copy=False)
将"deion"列重命名为"food",将"group"列重命名为"fgroup"。
然后,通过info.info()
查看info
DataFrame的基本信息,包括列名、非空值数量以及每列的数据类型等。
接着,您使用col_mapping
字典将nutrients
DataFrame中的列名进行重命名。nutrients.rename(columns=col_mapping, copy=False)
将"deion"列重命名为"nutrient",将"group"列重命名为"nutgroup"。
通过以上操作,您对nutrients
DataFrame进行了重复行的处理,并对info
和nutrients
DataFrame中的列名进行了重命名。
ndata = pd.merge(nutrients, info, on="id") ndata.info() ndata.iloc[30000] |
pd.merge(nutrients, info, on="id")
将nutrients
和info
DataFrame根据"id"列进行合并。通过指定on="id"
,您告诉pd.merge()
函数使用"id"列进行匹配合并。
将合并后的结果存储在名为ndata
的新DataFrame中。
接下来,使用.info()
查看ndata
DataFrame的基本信息,包括列名、非空值数量以及每列的数据类型等。
最后,使用.iloc[30000]
访问ndata
DataFrame中的第30000行数据。
fig = plt.figure() result = ndata.groupby(["nutrient", "fgroup"])["value"].quantile(0.5) |
plt.figure()
创建了一个新的图形窗口fig
。
然后,使用ndata.groupby(["nutrient", "fgroup"])["value"].quantile(0.5)
对ndata
DataFrame进行分组操作。通过指定["nutrient", "fgroup"]
作为分组依据,以及["value"]
作为要计算中位数的列,使用.quantile(0.5)
计算了"value"列的中位数。
接下来,通过result["Zinc, Zn"]
选择了"Zinc, Zn"营养成分的中位数结果。
最后,使用.sort_values().plot(kind="barh")
对中位数结果进行排序,并绘制了水平条形图。
by_nutrient = ndata.groupby(["nutgroup", "nutrient"]) def get_maximum(x): max_foods = by_nutrient.apply(get_maximum)[["value", "food"]] # make the food a little smaller max_foods.loc["Amino Acids"]["food"] |
ndata.groupby(["nutgroup", "nutrient"])
对ndata
DataFrame进行分组操作,根据营养成分的分类和具体成分进行分组,将结果存储在by_nutrient
中。
然后,定义了一个函数get_maximum(x)
,该函数接收一个分组x
,并返回该分组中具有最大值的行。通过x.loc[x.value.idxmax()]
获取具有最大值的行。
接下来,通过by_nutrient.apply(get_maximum)[["value", "food"]]
应用get_maximum
函数到每个分组,并选择"value"和"food"列,将结果存储在max_foods
中。
通过max_foods["food"].str[:50]
将"food"列中的食物名称截取为最多50个字符,以便稍微缩小长度。
最后,通过max_foods.loc["Amino Acids"]["food"]
获取"Amino Acids"分类下的食物名称。
4.1数据简介
美国联邦选举委员会公布了有关政治运动贡献的数据。这些数据包括捐赠者姓名、职业和雇主、地址和缴费金额。你可以尝试做一下的分析:
按职业和雇主的捐赠统计
按捐赠金额统计
按州进行统计
4.2数据引用
fec = pd.read_csv("datasets/fec/P00000001-ALL.csv", low_memory=False) fec.info() |
4.3数据处理
fec.iloc[123456] |
使用.info()
方法打印fec
DataFrame的基本信息,包括列名、非空值数量以及每列的数据类型等。
unique_cands = fec["cand_nm"].unique() unique_cands unique_cands[2] |
fec["cand_nm"]
选择了fec
DataFrame中的"cand_nm"列,即候选人名称列。
然后,使用.unique()
获取候选人名称列的唯一值,将结果存储在名为unique_cands
的变量中。
接下来,通过打印unique_cands
,您将获得唯一候选人名称的列表。
最后,使用unique_cands[2]
选择了索引为2的候选人名称,以获取该候选人的名称。
fec["cand_nm"][123456:123461] fec["cand_nm"][123456:123461].map(parties) # Add it as a column fec["party"] = fec["cand_nm"].map(parties) fec["party"].value_counts() |
fec["cand_nm"][123456:123461]
选择了索引从123456到123460的候选人名称。
然后,使用.map(parties)
将这些候选人名称通过parties
映射函数进行映射。这里假设parties
是一个映射函数,用于将候选人名称映射到各自的党派。
接着,通过将映射结果作为新的列添加到fec
DataFrame中,使用fec["party"] = fec["cand_nm"].map(parties)
的方式。
最后,使用.value_counts()
计算"party"列中各个党派的计数,以获取各个党派的出现次数。
(fec["contb_receipt_amt"] > 0).value_counts() |
(fec["contb_receipt_amt"] > 0)
表示对"contb_receipt_amt"列的每个元素进行条件比较,判断是否大于0。结果将是一个由布尔值组成的Series。
然后,使用.value_counts()
计算布尔值Series中每个唯一值的计数。这将返回一个新的Series,其中索引为唯一的布尔值,而值为相应布尔值的计数。
通过以上操作,您可以获得"contb_receipt_amt"列中大于0和不大于0的值的计数。
fec = fec[fec["contb_receipt_amt"] > 0] fec_mrbo = fec[fec["cand_nm"].isin(["Obama, Barack", "Romney, Mitt"])] fec["contbr_occupation"].value_counts()[:10] |
fec[fec["contb_receipt_amt"] > 0]
对fec
DataFrame进行了过滤操作,保留了"contb_receipt_amt"列中大于0的行,并将结果重新赋值给fec
DataFrame。
接着,fec[fec["cand_nm"].isin(["Obama, Barack", "Romney, Mitt"])]
选择了fec
DataFrame中"Obama, Barack"和"Romney, Mitt"两位候选人的数据,并将结果赋值给fec_mrbo
DataFrame。
最后,使用.value_counts()[:10]
计算"contbr_occupation"列中各个职业的计数,并选择了计数最高的前10个职业。
occ_mapping = { def get_occ(x): fec["contbr_occupation"] = fec["contbr_occupation"].map(get_occ) emp_mapping = { def get_emp(x): fec["contbr_employer"] = fec["contbr_employer"].map(get_emp) by_occupation = fec.pivot_table("contb_receipt_amt", |
occ_mapping
和emp_mapping
是用于职业和雇主映射的字典。
get_occ
函数接收一个职业名称,并返回映射后的职业名称,如果没有提供映射,则返回原始职业名称。
get_emp
函数接收一个雇主名称,并返回映射后的雇主名称,如果没有提供映射,则返回原始雇主名称。
通过fec["contbr_occupation"].map(get_occ)
和fec["contbr_employer"].map(get_emp)
,分别对"contbr_occupation"和"contbr_employer"列应用了映射函数。
接下来,使用pivot_table()
方法计算了"contb_receipt_amt"列的总捐款金额,按照"contbr_occupation"和政党("party")进行分组聚合。
然后,通过by_occupation.sum(axis="columns") > 2000000
筛选出总捐款金额超过2000000的职业,并将结果存储在名为over_2mm
的DataFrame中。
plt.figure() over_2mm.plot(kind="barh") |
plt.figure()
创建了一个新的图形窗口。
然后,使用over_2mm.plot(kind="barh")
绘制了over_2mm
DataFrame的水平条形图。根据DataFrame的结构,将每个职业作为水平条形图的一个条目,并使用条形高度表示捐款金额。
def get_top_amounts(group, key, n=5): grouped = fec_mrbo.groupby("cand_nm") |
get_top_amounts
函数接受一个分组group
和一个键key
,首先使用group.groupby(key)["contb_receipt_amt"].sum()
对分组后的DataFrame按键key
进行分组,并计算每组的捐款金额总和。然后,使用.nlargest(n)
获取捐款金额总和的前n个最大值。
接下来,通过fec_mrbo.groupby("cand_nm")
对fec_mrbo
DataFrame按照"cand_nm"进行分组,将结果存储在grouped
中。
然后,使用.apply(get_top_amounts, "contbr_occupation", n=7)
应用get_top_amounts
函数到每个分组,传递"contbr_occupation"作为键,并设置n
参数为7。这将返回每个候选人的"contbr_occupation"中捐款金额前7个最大值。
接着,使用.apply(get_top_amounts, "contbr_employer", n=10)
应用get_top_amounts
函数到每个分组,传递"contbr_employer"作为键,并设置n
参数为10。这将返回每个候选人的"contbr_employer"中捐款金额前10个最大值。
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) labels |
np.array([0, 1, 10, 100, 1000, 10000, 100_000, 1_000_000, 10_000_000])
创建了一个包含分箱边界的数组bins
。
然后,使用pd.cut(fec_mrbo["contb_receipt_amt"], bins)
将"contb_receipt_amt"列的值划分为不同的区间,并返回一个包含对应区间标签的Series。这些标签表示每个捐款金额所属的区间。
最后,将标签存储在名为labels
的变量中。
grouped = fec_mrbo.groupby(["cand_nm", labels]) grouped.size().unstack(level=0) |
fec_mrbo.groupby(["cand_nm", labels])
对fec_mrbo
DataFrame按照候选人名称和之前创建的labels
进行分组,并将结果存储在grouped
中。
接下来,使用.size()
方法计算每个分组的大小,即每个候选人和区间的组合出现的次数。这将返回一个包含候选人和区间组合计数的Series。
最后,使用.unstack(level=0)
将候选人名称作为列索引,将Series重塑为以候选人名称为列的DataFrame,其中每个单元格包含候选人和区间组合的计数。
plt.figure() bucket_sums = grouped["contb_receipt_amt"].sum().unstack(level=0) |
plt.figure()
创建了一个新的图形窗口。
然后,使用grouped["contb_receipt_amt"].sum().unstack(level=0)
计算了每个候选人和区间组合的捐款金额总和,并使用.unstack(level=0)
将结果重塑为以候选人名称为列的DataFrame,并将结果存储在bucket_sums
中。
接下来,使用.div(bucket_sums.sum(axis="columns"), axis="index")
将bucket_sums
DataFrame的每行值除以该行的总和,计算了每个组合在总捐款金额中的比例,并将结果存储在normed_sums
中。
最后,使用.plot(kind="barh")
绘制了normed_sums[:-2]
DataFrame的水平条形图,表示每个候选人和区间组合的捐款金额比例。注意,这里使用[:-2]
是为了排除最后两个组合,因为它们可能会导致图形不够清晰。
grouped = fec_mrbo.groupby(["cand_nm", "contbr_st"]) totals = grouped["contb_receipt_amt"].sum().unstack(level=0).fillna(0) totals = totals[totals.sum(axis="columns") > 100000] totals.head(10) |
fec_mrbo.groupby(["cand_nm", "contbr_st"])
对fec_mrbo
DataFrame按照候选人名称和捐款者所在州("contbr_st")进行分组,并将结果存储在grouped
中。
接下来,使用grouped["contb_receipt_amt"].sum().unstack(level=0)
计算了每个候选人和州的捐款金额总和,并使用.unstack(level=0)
将结果重塑为以候选人名称为列的DataFrame,并将结果存储在totals
中。
然后,使用.fillna(0)
方法将缺失值填充为0。
接着,使用.sum(axis="columns") > 100000
筛选出总捐款金额大于100000的行,并将结果存储在totals
中。
最后,显示了totals
DataFrame的前10行。
percent = totals.div(totals.sum(axis="columns"), axis="index") percent.head(10) |
.div(totals.sum(axis="columns"), axis="index")
将totals
DataFrame的每行值除以该行的总和,计算了每个候选人和州的捐款金额在总捐款金额中的比例,并将结果存储在percent
中。
最后,显示了percent
DataFrame的前10行。