当前位置:   article > 正文

《利用Python进行数据分析》示例数据_基于python的数据分析案例

基于python的数据分析案例

1.MoviesLens 1M数据集

        1.1数据简介:

        GroupLens实验室提供了一些从MoviesLens用户那里收集的20世纪90年代末到21世纪初的电影评分数据的集合。浙西额数据提供了电影的评分、流派、年份和观众数据(年龄、邮编、性别、职业)。
        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"]
users = pd.read_table("datasets/movielens/users.dat", sep="::",
                      header=None, names=unames, engine="python")

rnames = ["user_id", "movie_id", "rating", "timestamp"]
ratings = pd.read_table("datasets/movielens/ratings.dat", sep="::",
                        header=None, names=rnames, engine="python")

mnames = ["movie_id", "title", "genres"]
movies = pd.read_table("datasets/movielens/movies.dat", sep="::",
                       header=None, names=mnames, engine="python")

             

 使用pandas库中的pd.read_table()函数从MovieLens数据集的三个文件中读取数据。这些文件包括users.datratings.datmovies.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]

这段代码将合并ratingsusersmovies三个数据框,并将结果存储在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
  1. 使用groupby()函数对data数据框按照电影标题("title")进行分组,并使用size()函数计算每个电影标题的出现次数。
  2. 使用.head()方法打印出计算得到的分组结果的前几行。
  3. 使用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)":
                           "Seven Samurai (Shichinin no samurai) (1954)"})

top_female_ratings = mean_ratings.sort_values("F", ascending=False)
top_female_ratings.head()

                 

.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")
sorted_by_diff.head()

通过计算男性评分("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]
  1. 使用pd.merge()函数将展开后的movies_explodedratingsusers数据框进行合并,以创建包含电影分类的评分数据框ratings_with_genre
  2. 使用.iloc[0]索引器来获取ratings_with_genre数据框中的第一行数据。
  3. 使用groupby()函数按照分类和年龄进行分组,并计算每个分类和年龄组的平均评分。
  4. 使用.unstack("age")将年龄作为列索引重新排列数据框。

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

        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 = []
for year in range(1880, 2011):
    path = f"datasets/babynames/yob{year}.txt"
    frame = pd.read_csv(path, names=["name", "sex", "births"])

    # Add a column for the year
    frame["year"] = year
    pieces.append(frame)

# Concatenate everything into a single DataFrame
names = pd.concat(pieces, ignore_index=True)

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):
    group["prop"] = group["births"] / group["births"].sum()
    return group
names = names.groupby(["year", "sex"], group_keys=False).apply(add_prop)

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"]
girls = top1000[top1000["sex"] == "F"]

total_births = top1000.pivot_table("births", index="year",
                                   columns="name",
                                   aggfunc=sum)

total_births.info()
subset = total_births[["John", "Harry", "Mary", "Marilyn"]]
subset.plot(subplots=True, figsize=(12, 10),
            title="Number of births per year")

根据"sex"列的值,将top1000数据框拆分为boysgirls两个数据框,分别包含男孩和女孩的记录。

然后,使用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",
                            columns="sex", aggfunc=sum)
table.plot(title="Sum of table1000.prop by year and sex",
           yticks=np.linspace(0, 1.2, 13))

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()
prop_cumsum[:10]
prop_cumsum.searchsorted(0.5)

df = boys[boys.year == 1900]
in1900 = df.sort_values("prop", ascending=False).prop.cumsum()
in1900.searchsorted(0.5) + 1

def get_quantile_count(group, q=0.5):
    group = group.sort_values("prop", ascending=False)
    return group.prop.cumsum().searchsorted(q) + 1

diversity = top1000.groupby(["year", "sex"]).apply(get_quantile_count)
diversity = diversity.unstack()

fig = plt.figure()

diversity.head()
diversity.plot(title="Number of popular names in top 50%")

首先计算了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):
    return x[-1]

last_letters = names["name"].map(get_last_letter)
last_letters.name = "last_letter"

table = names.pivot_table("births", index=last_letters,
                          columns=["sex", "year"], aggfunc=sum)

subtable = table.reindex(columns=[1910, 1960, 2010], level="year")
subtable.head()

定义了一个名为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))
letter_prop["M"].plot(kind="bar", rot=0, ax=axes[0], title="Male")
letter_prop["F"].plot(kind="bar", rot=0, ax=axes[1], title="Female",
                      legend=False)

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
dny_ts.head()

使用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.美国农业部视频数据库

        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 = ["description", "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:
    fnuts = pd.DataFrame(rec["nutrients"])
    fnuts["id"] = rec["id"]
    nutrients.append(fnuts)

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
nutrients = nutrients.drop_duplicates()

col_mapping = {"description" : "food",
               "group"       : "fgroup"}
info = info.rename(columns=col_mapping, copy=False)
info.info()
col_mapping = {"description" : "nutrient",
               "group" : "nutgroup"}
nutrients = nutrients.rename(columns=col_mapping, copy=False)
nutrients

nutrients.duplicated().sum()计算了nutrients DataFrame中的重复行数,并返回该数量。

然后,使用.drop_duplicates()方法从nutrients DataFrame中删除重复的行。

接下来,您使用col_mapping字典将info DataFrame中的列名进行重命名。info.rename(columns=col_mapping, copy=False)将"description"列重命名为"food",将"group"列重命名为"fgroup"。

然后,通过info.info()查看info DataFrame的基本信息,包括列名、非空值数量以及每列的数据类型等。

接着,您使用col_mapping字典将nutrients DataFrame中的列名进行重命名。nutrients.rename(columns=col_mapping, copy=False)将"description"列重命名为"nutrient",将"group"列重命名为"nutgroup"。

通过以上操作,您对nutrients DataFrame进行了重复行的处理,并对infonutrients DataFrame中的列名进行了重命名。

 

ndata = pd.merge(nutrients, info, on="id")
ndata.info()
ndata.iloc[30000]

pd.merge(nutrients, info, on="id")nutrientsinfo 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)
result["Zinc, Zn"].sort_values().plot(kind="barh")

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):
    return x.loc[x.value.idxmax()]

max_foods = by_nutrient.apply(get_maximum)[["value", "food"]]

# make the food a little smaller
max_foods["food"] = max_foods["food"].str[:50]

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.2012年联邦选举委员会数据库

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 = {
   "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)

fec["contbr_occupation"] = fec["contbr_occupation"].map(get_occ)

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)

fec["contbr_employer"] = fec["contbr_employer"].map(get_emp)

by_occupation = fec.pivot_table("contb_receipt_amt",
                                index="contbr_occupation",
                                columns="party", aggfunc="sum")
over_2mm = by_occupation[by_occupation.sum(axis="columns") > 2000000]
over_2mm

occ_mappingemp_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):
    totals = group.groupby(key)["contb_receipt_amt"].sum()
    return totals.nlargest(n)

grouped = fec_mrbo.groupby("cand_nm")
grouped.apply(get_top_amounts, "contbr_occupation", n=7)
grouped.apply(get_top_amounts, "contbr_employer", n=10)

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)
normed_sums = bucket_sums.div(bucket_sums.sum(axis="columns"),
                              axis="index")
normed_sums
normed_sums[:-2].plot(kind="barh")

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行。

        ​​​​​​​        ​​​​​​​        ​​​​​​​        

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/运维做开发/article/detail/803125
推荐阅读
相关标签
  

闽ICP备14008679号