利用python进行数据分析第十四章实战三
前言
同样的,本节适用于对利用python进行数据分析这本书代码不是很理解的同学,适合初学者,里面含有代码解析。如果是想看完整的书,可以去 https://zhuanlan.zhihu.com/p/68487640
数据下载
参见我的博客实战一里面的下载问题
美国1880-2010年的婴儿名字
1.看一下1880年的数据并初处理一下
提供了1880-2010年的数据,每个都为一个txt文件。一部分截图如下
看一下文件里面的原数据格式
!type -10 "D:\pycsv\babynames\yob1880.txt"
可见它已经以逗号分隔的形式出现,用read_csv将其加载到dataframe中
import pandas as pd
names1880 =pd.read_csv('D:/pycsv/babynames/yob1880.txt',names=['name', 'sex', 'births'])
names1880
前半部分数据如下
通过聚合性别这一项来看1880年男女各多少人
names1880.groupby('sex').births.sum()
#sum()函数是求和的
#names1880.groupby('sex')['births'].sum()代码意思一样
2.对1880-210年的文件进行dataframe合并
import pandas as pd
years=range(1880,2011)
pieces=[]
columns=['name','sex','births']
for year in years:
path="D:/pycsv/b/babynames/yob"+str(year)+".txt"
frame=pd.read_csv(path,names=columns)
frame['year']=year
pieces.append(frame)#将frame添加到列表pieces中
#所有frame接到一个列表中
pieces
每一个dataframe作为列表的一个元素
再通过concat函数把存在列表pieces中的dataframe纵向拼接
names=pd.concat(pieces,ignore_index=True)
names
concat函数的具体可参考:https://blog.csdn.net/zzpdbk/article/details/79232661
数据的后半部分:
以年为索引,性别为列,出生数为值,统计每年的男女出生总数
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')
按性别和年份进行分组聚合,每个婴儿名字的占比。插入prop列存占比
def add_prop(group):
group['prop'] = group.births / group.births.sum()
return group
names = names.groupby(['year', 'sex']).apply(add_prop)
names
部分截图
验证一下,每组prop的总和为1
names.groupby(['year','sex']).prop.sum()
部分截图
看每个性别,年份组合的前1000名,
def get_top1000(group):
return group.sort_values(by='births', ascending=False)[:1000]
grouped = names.groupby(['year', 'sex'])
top1000 = grouped.apply(get_top1000)
top1000.reset_index(inplace=True, drop=True)
top1000
分析名字的趋势
首先,将top1000的名字分成男孩和女孩两部分。
boys=top1000[top1000.sex=='M']
girls=top1000[top1000.sex=='F']
按年份和名字形成出生总数的数据透视表
total_births = top1000.pivot_table('births', index='year',columns='name',aggfunc=sum)
total_births.head()
‘John’,‘Harry’,‘Marry’,'Marilyn’名字的趋势
subset=total_births[['John','Harry','Marry','Marilyn']]
subset.plot(subplots=True,figsize=(12,10),grid=False,title='Number of births per year')
plt.show()
计算命名的多样性,如何判断多样性呢,在热门名字的出现程度下降即可意味着其他名字的出现,命名的多样性。所以可以求top1000名字的占比变化趋势
import numpy as np
table = top1000.pivot_table('prop', index='year',columns='sex', aggfunc=sum)
#注意这里是top1000的prop加起来
table
再画图
table.plot(title='Sum of table1000.prop by year and sex',yticks=np.linspace(0, 1.2, 13), xticks=range(1880, 2020, 10))
另一个有趣的趋势是,较早流行的男孩名字已经随着时间的推移变成了女孩子的名字,一个例子是lesley或leslie的名字
计算lesl开头的名字的列表
all_names=pd.Series(top1000.name.unique())
all_names
数据后半部分
包含lesl的
lesley_like=all_names[all_names.str.lower().str.contains('lesl')]
lesley_like
filtered=top1000[top1000.name.isin(lesley_like)]
filtered
#每一年中 男女名字中包含lesl的
部分数据
filtered.groupby('name').births.sum()
#这么多年来这些lesl名字的总和
按性别和年份进行聚合,并在年内进行标准化
table=table.div(table.sum(1),axis=0)
table.tail()
table.plot(style={'M':'k-','F':'k--'})
书中还有一些分析,如男孩女孩最后一个字母的比例,不过我没有做这个