pandas数据处理练习(基础且详细 二十岁老汉在线扣字)


前言

在学习pandas以及matplotlib库用法的过程中,尝试了对数据进行处理以及可视化,在此记录下近期实例,以期复习使用


一、包的导入

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np

本文内容主要使用以上库,并进行了缩写,以下开始分题讲解

二、MoviesLens 1M数据集

1.数据集概述:

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

2.文件代码及解读:

unames = ["user_id", "gender", "age", "occupation", "zip"]
users = pd.read_table("datachuli\movielens\users.dat", sep="::",
                      header=None, names=unames, engine="python")

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

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

首先定义三个列表,分别是关于用户、数据比率,电影,然后对应三个列表元素作为索引读入关于三者的文件,并将列表元素作为索引,生成三个二维的DataFrame。

users.head(5)
ratings.head(5)
movies.head(5)
ratings

其次利用head()去读这三个DataFrame的头五个元素,得如下结果:
在这里插入图片描述

data = pd.merge(pd.merge(ratings, users), movies)
data
data.iloc[0]

使用merge函数将三个表合并成一个表,data然后打印第0行数据。
在这里插入图片描述

mean_ratings = data.pivot_table("rating", index="title",
                               columns="gender", aggfunc="mean")
.mean_ratings.head(5)

将电影名称作为索引,以性别为列计算每个电影的比率的均值,并且查看前五个。
在这里插入图片描述

ratings_by_title = data.groupby("title").size()
ratings_by_title.head()
active_titles = ratings_by_title.index[ratings_by_title >= 250]
active_titles

将数据集按照电影名称分组,然后查看评分数量的前几个结果,然后用 active_titles去记录评分数量大于等于250.
在这里插入图片描述

mean_ratings = mean_ratings.loc[active_titles]
mean_ratings

使用loc方法mean_ratingsDataFrame中选择active_titles的行。然后,您通过打印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()

重命名mean_ratingsDataFrame中的一个索引并将其重命名为"Seven Samurai (Shichinin no samurai) (1954)"然后,使用sort_values()方法根据女性评分(“F”)对 mean_ratings进行排序,并使用head()方法查看前几行结果。
在这里插入图片描述

mean_ratings["diff"] = mean_ratings["M"] - mean_ratings["F"]
sorted_by_diff = mean_ratings.sort_values("diff")
sorted_by_diff.head()

将男女评分的差距写在新列中,并且排序并输出前几行。
在这里插入图片描述

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()

表逆序排列。
将数据集按照电影名字分组并计算比率的方差,然后输出前几行
在这里插入图片描述

rating_std_by_title.sort_values(ascending=False)[:10]

将之前的数据集排序并输出前十行
在这里插入图片描述

movies["genres"].head()
movies["genres"].head().str.split("|")
movies["genre"] = movies.pop("genres").str.split("|")
movies.head()

处理movies的数据集,将其genres列按|分裂,然后储存到新列genre中
在这里插入图片描述

movies_exploded = movies.explode("genre")
movies_exploded[:10]

将movies的genre列展开成多行,并输出前十列。
在这里插入图片描述

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进行合并,然后,通过使用.iloc[0]打印第一行数据。使用groupby()函数按genre和age对ratings_with_genre进行分组,计算每组中rating列的均值,并使用.unstack(“age”)进行数据重塑,将age作为列索引。最后,使用[:10]打印前10行结果。
在这里插入图片描述

3.可视化拓展:

genre_ratings.plot(kind="bar", stacked=True, figsize=(10, 6))
plt.title("Average Ratings by Genre and Age")
plt.xlabel("Genre")
plt.ylabel("Average Rating")
plt.show()

根据分析出来的各个年龄层之间的对电影中类类型的数据做了统计图
在这里插入图片描述

三、美国1880-2010年的婴儿名字

1.数据集概述:

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

2.代码解读及演示:

2.1导包

与最初相同 若从头开始不必查看

#!head -n 10 datasets/babynames/yob1880.txt
import numpy as np
import pandas as pd

2.2 读取数据

names=["name", "sex", "births"])
names1880

在这里插入图片描述

2.3 数据处理:

names1880.groupby("sex")["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"])#读取从1880到2010婴儿出生数据

    # Add a column for the year
    frame["year"] = year
    #display(frame)
    pieces.append(frame)#合成大dataframe集合

# Concatenate everything into a single DataFrame
names = pd.concat(pieces, ignore_index=True)#合成一个dataframe
#pieces
#names

在这里插入图片描述

total_births = names.pivot_table("births", index="year",
                                 columns="sex", aggfunc=sum)#求不同year条件下不同sex的婴儿出生人数
total_births.tail()#取样
total_births.plot(title="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.groupby(["year", "sex"])["prop"].sum()

在这里插入图片描述

def get_top1000(group):
    return group.sort_values("births", ascending=False)[:1000]#返回排序后的1000行数据
grouped = names.groupby(["year", "sex"])
top1000 = grouped.apply(get_top1000)
top1000.index

在这里插入图片描述

p1000 = top1000.reset_index(drop=True)#启用新索引,删除旧索引
top1000.head()
#top1000.tail()

在这里插入图片描述

boys = top1000[top1000["sex"] == "M"]#男女数据分类
girls = top1000[top1000["sex"] == "F"]
boys

在这里插入图片描述

#top1000=top1000.rename_axis('year_id')
total_births = top1000.pivot_table("births",
                                   columns="name",
                                   index='year',
                                   aggfunc=sum)#按照出生年份不同展示各个名字的出生人数

total_births

在这里插入图片描述

total_births.info()#表信息
subset = total_births[["John", "Harry", "Mary", "Marilyn"]]
subset.plot(subplots=True, figsize=(12, 10),#分开展示四个名字的变化趋势
            title="Number of births per year")

在这里插入图片描述

plt.figure()

table = top1000.pivot_table("prop", index="year",
                            columns="sex", aggfunc=sum)#以年为索引,展示各个性别的出生人数比例
table
table.plot(title="Sum of table1000.prop by year and sex",
           yticks=np.linspace(0, 1.2, 13))
df = boys[boys["year"] == 2010]#2010 boy相关数据
df

在这里插入图片描述

prop_cumsum = df["prop"].sort_values(ascending=False).cumsum()#累积求和
prop_cumsum[:10]
prop_cumsum.searchsorted(0.5)#看比例达到0.5的有几个

输出116

df = boys[boys.year == 1900]
in1900 = df.sort_values("prop", ascending=False).prop.cumsum()
in1900.searchsorted(0.5) + 1#看1900累积达到0.5的有几

输出25

def get_quantile_count(group, q=0.5):
    group = group.sort_values("prop", ascending=False)
    return group.prop.cumsum().searchsorted(q) + 1#计算累积达到0.5比例的有几个

diversity = top1000.groupby(["year", "sex"]).apply(get_quantile_count)#看各年份达到0.5的有几个
diversity = diversity.unstack()#转化二维

fig = plt.figure()

diversity.head()
diversity.plot(title="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.head()

在这里插入图片描述

subtable.sum()
letter_prop = subtable / subtable.sum()
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)#直方图分析名字最后一个字母的比例

在这里插入图片描述

letter_prop = table / table.sum()

dny_ts = letter_prop.loc[["d", "n", "y"], "M"].T#选择d,n,y行,M列
dny_ts.head()

在这里插入图片描述

all_names = pd.Series(top1000["name"].unique())
lesley_like = all_names[all_names.str.contains("Lesl")]#包含某一字段的所有名字
lesley_like

在这里插入图片描述

filtered = top1000[top1000["name"].isin(lesley_like)]
filtered.groupby("name")["births"].sum()#这些名字的婴儿一共出生多少

在这里插入图片描述

table = filtered.pivot_table("births", index="year",
                             columns="sex", aggfunc="sum")#这些名字的婴儿按年龄,分性别表示出生人数
table = table.div(table.sum(axis="columns"), axis="index")
table.tail()

在这里插入图片描述

fig = plt.figure()
table.plot(style={"M": "k-", "F": "k--"})

在这里插入图片描述

四、美国农业部视频数据库

1.数据集概述:

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

2.代码解读及演示:

import json
import pandas as pd
import matplotlib.pyplot as plt
db = json.load(open("datasets/usda_food/database.json"))
len(db)#导入文件 查看文件长度

通过json获得数据文件,并查看长度,长度为6636

db[0].keys()#获取键值
db[0]["nutrients"][0]#获取营养标签下的第一个部分
nutrients = pd.DataFrame(db[0]["nutrients"])#将全体内容传入新的表格中
nutrients.head(7)#查看前七行

得如下结果:
在这里插入图片描述

info_keys = ["description", "group", "id", "manufacturer"]#设置信息种类
info = pd.DataFrame(db, columns=info_keys)#重写表格 修改键值
info.head()

数据格式不佳,重写表格并修改键值,设立id为之后使用进行铺垫
在这里插入图片描述

info.info()#显示信息
pd.value_counts(info["group"])[: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)#确认索引连续  

以营养成分为组织索引进行表格的建立
在这里插入图片描述

print(nutrients.duplicated().sum())  #计算重复行的数量
nutrients = nutrients.drop_duplicates()#移除重复行 

通过duplicated函数查看重复行以及将重复的行移除,在通过查看确认移除成功
在这里插入图片描述

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#查看列表       

分别对两个dateframe进行索引的重命名,重命名方法为建立字典并使用rename进行。查看确认
在这里插入图片描述

ndata = pd.merge(nutrients, info, on="id")#以id为主键对其进行合并
ndata.info()#查看ndata信息
ndata.iloc[30000]#返回第三千行的信息   

通过id将其表格进行合并,以期望在一个表格中得到更多的信息。
查看结果
在这里插入图片描述

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]#取前五十
print(max_foods["food"])     

通过索引进行组织,并建立最值函数,依次确认最大的值并进行查看
在这里插入图片描述

max_foods.loc["Amino Acids"]["food"]#获取amino acids 对应的食物列

得到其中一种营养素对应的食物信息
在这里插入图片描述

3.可视化拓展:

fig = plt.figure()#创建画布
result = ndata.groupby(["nutrient", "fgroup"])["value"].quantile(0.5)
result["Zinc, Zn"].sort_values().plot(kind="barh")

对 ndata进行分组操作,并计算每个组合中 value的中位数,结果存储在result 选择了 “Zinc, Zn”,对其排序以水平条形图绘制。
找到了含锌较多的食物
在这里插入图片描述

五、2012年联邦选举委员会数据库

5.1处理

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

首先我们先导入数据并查看一下数据的基本信息

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函数将所有的候选人的信息唯一的存取下来。

unique_cands = fec["cand_nm"].unique()
unique_cands
unique_cands[2]

使用上面的代码可以看到第三个候选人的名字,当然,我们也可以使用print(unique_cands)来看到所有候选人的名字

如果我们想要知道在这张表里美国各个党派的候选人所出现的次数,我们还需要一张记录候选人以及候选人所属党派的表。表单如下(使用parties来存储这个信息):

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["party"] = fec["cand_nm"].map(parties)#映射
fec["party"].value_counts()#计算次数

通过value_counts()这个函数的功能我们还可以统计捐款超过0元的次数(返还金额的时候捐款金额即为负数),即(fec[“contb_receipt_amt”] > 0) .value_counts()

通过isin()函数我们还能找到所有符合条件的行,比如,如果我们想要查找候选人为"Obama, Barack"和"Romney, Mitt"的行,我们可以使用fec_mrbo = fec[fec[“cand_nm”].isin([“Obama, Barack”, “Romney, Mitt”])]来找到所有符合条件的行。

5.2统计各个职业的捐款信息

首先我们需要通过透视表来获得各个职业的捐款金额,并通过透视表显示出来,代码如下:

by_occupation = fec.pivot_table("contb_receipt_amt",
                                index="contbr_occupation",
                                columns="party", aggfunc="sum")
fec.pivot_table("contb_receipt_amt", index="contbr_occupation", columns="party", aggfunc="sum")

将数据集进行透视操作,以 “contbr_occupation” 作为行索引(index),“party” 作为列索引(columns),“contb_receipt_amt” 作为值(values),使用 “sum” 作为聚合函数(aggfunc)。透视表将统计每个职业在不同政党下的捐款总金额。
接下来进一步进行处理

over_2mm = by_occupation[by_occupation.sum(axis="columns") > 2000000]

通过这一步操作,我们可以根据上一步得到的透视表 by_occupation,对每个职业的捐款金额进行行求和,然后筛选出总捐款金额超过200万美元的职业。将符合条件的结果存储在名为 over_2mm 的新变量中。
在这里插入图片描述

over_2mm.plot(kind="barh")

然后我们通过绘图就可以直观的得到各个职业在各个政党的捐款情况
在这里插入图片描述

5.3统计候选人里雇主和职业的捐款信息

因为捐款信息过于的多,所以我们需要将捐款信息只保留前N高的捐款信息即可,此处我们定义一个函数

def get_top_amounts(group, key, n=5):
    totals = group.groupby(key)["contb_receipt_amt"].sum()
    return totals.nlargest(n)

通过这个函数,我们能对group进行分组并在key上进行累加捐款金额并返回前n大的值,接下来我妹妹就可以通过调用这个函数来返回对应的信息了

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

通过上面的代码,我们可以返回候选人旗下的职业和雇主的捐款最多的前n个数据。

5.4统计各个区间的捐款情况并按州统计

我们还可以统计各个区间的捐款金额
生成一个numpy数组,分割各个捐款的区间

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)

通过捐款的区间进行分组,并计算每个组的大小,最后,.unstack(level=0)将结果重新排列成一个新的数据框,其中每个唯一的"cand_nm"值成为列的名称,每个组的大小成为相应的值。

grouped = fec_mrbo.groupby(["cand_nm", labels])
grouped.size().unstack(level=0)

绘制图案便于直观观察

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

在这里插入图片描述
选出totals中大于100000的数据(州里捐款总额大于100000的)并重新排列成新的数据框

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)

在这里插入图片描述
求和后展示前十行

percent = totals.div(totals.sum(axis="columns"), axis="index")
percent.head(10)

在这里插入图片描述

后记

感谢多位小伙伴的支持,若有资料代码等问题,可于留言区探讨。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值