求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Model Center   Code  
会员   
要资料
 
 

利用python进行数据分析
搭建python环境
统计 1880-2010 年间 全美婴儿姓名的趋势
Ipython & Ipython Notebook
NumPy Basics: Arrays and Vectorized Computation
Pandas(Python Data Analysis Library)
数据加载、储存与文件格式
绘图和可视化(Matplotlib)
时间序列
经济,金融数据应用
补充例子
国王与囚徒
利用python进行科学计算
分形与混沌之-Mandelbrot集合
分形与混沌之-迭代函数系统(IFS)
分形与混沌之-蔡氏电路模拟
对于μ子实验数据进行快速处理与分析
37%法则 - "非诚勿扰" 中的博弈
关于时间/日期的转换
深入研究
一切从游戏开始:完整的一个 python to hack 实例!
习题:扑克牌发牌
 
 

统计 1880-2010 年间 全美婴儿姓名的趋势
1760 次浏览
9次  

统计 1880-2010 年间 全美婴儿姓名的趋势

美国社会保障总署(SSA)提供了一个1880-2010 年间 全美婴儿姓名频率的数据(names文件在这里下载)。

我们可以根据这一个数据统计做很多事情,比如:

1.计算特定名字的年度比例 (谁是最受欢迎的男女性名字?)

2.计算特定名字的相对排名

3.计算增长或者减少最快的名字

4.分析姓名趋势:元音,辅音,长度,总体多样性,拼写变化,首位字母等等。。

5.圣经中的名字,名人效应,人口结构变化等等

数据格式

比如用文本编辑器打开文件yob1880.txt,可以看到:

Mary,F,7065
Anna,F,2604
Emma,F,2003
Elizabeth,F,1939
Minnie,F,1746
Margaret,F,1578
Ida,F,1472
Alice,F,1414
Bertha,F,1320
。。。

上述是一个非常标准的都和分隔开的文本格式,可以利用 pandas.read_csv 指令将其加载到DataFrame 中:

什么?文件找不到? 利用pwd指令可以看看你的工作目录在哪里哦~, 可以通过cd 指令切换工作目录哦。。

Windows 里面用import os, os.chdir(“……”)

In [11]: cd "d:\\Desktop"
d:\Desktop
In [12]: pwd
Out[12]: u'D:\\Desktop'
In [13]: names1880 = pd.read_csv('names/yob1880.txt', names= ['name', 'sex', 'births'])

In [14]: names1880
Out[14]:
<class 'pandas.core.frame.DataFrame'>
Int64Index: 2000 entries, 0 to 1999
Data columns (total 3 columns):
name 2000 non-null values
sex 2000 non-null values
births 2000 non-null values
dtypes: int64(1), object(2)

我们来统计一下当年的男女数量:

In [16]: names1880.groupby('sex').births.sum()
Out[16]:
sex
F 90993
M 110493
Name: births, dtype: int64

如何对于所有1880-2010 年的数据统一处理?

显然单个文件和多个文件的复杂程度不同,为了避免你们反复打错,你需要利用文件编辑器将着一些代码编辑好了,复制过去。

#1880 - 2010 的数据统计
years = range(1880, 2011 )

pieces = []
columns = names= ['name', 'sex', 'births']

for year in years:
path = 'names/yob%d.txt' % year
frame = pd.read_csv(path, names = columns)
frame['year'] = year
pieces.append(frame)

#利用pd.concat 连接数据,将所有数据整合到单个DataFrame中
#注意利用ignore_index = True 可以忽略read_csv 所返回的原始行号
names = pd.concat(pieces, ignore_index = True)

现在看一下names 就很庞大了。。。

In [36]: names
Out[36]:
<class 'pandas.core.frame.DataFrame'>
Int64Index: 1690784 entries, 0 to 1690783
Data columns (total 4 columns):
name 1690784 non-null values
sex 1690784 non-null values
births 1690784 non-null values
year 1690784 non-null values
dtypes: int64(2), object(2)

有了以上这些数据以后,我们可以用groupby 或者pivot_table 在year 和sex 级别上面对其进行聚合(SUM)

#观察下按照sex & year 统计的出生数量
total_births = names.pivot_table('births', rows= 'year', cols='sex', aggfunc=sum)
total_births.tail()

#来,我们画个图看看是否重男轻女?
total_births.plot(title='Total births by sex and year')

我们再插入一个prop列,记录指定婴儿数量相对于总出生人数的比例,我们将按year&sex分组以后进行累加计算比例后新增加到每个分组中,便于以后使用。

#我们再插入一个prop列,记录指定婴儿数量相对于总出生人数的比例,我们将按year&sex分组以后进行累加计算比例后新增加到每个分组中
def add_prop(group):
#按照整数除法会出事。。。
births = group.births.astype(float)
group['prop']=births /births.sum()
return group

names = names.groupby(['year', 'sex']).apply(add_prop)

显然,我们希望拿出比较小的一部分数据快速处理,比如每年排名前1000的姓名做一个统计(即 sex/year 的前1000名),这是一个分组操作

#这里供大家偷懒,我写了,大家可以粘贴过去运行, **后面就不赘述了。。 **
def get_top1k(group):
return group.sort_index(by = 'births', ascending = False)[:1000]

grouped = names.groupby(['year', 'sex'])
top1k = grouped.apply(get_top1k)

#粘贴过去运行是这个样子的:
In [37]: def get_top1k(group):
....: return group.sort_index(by = 'births', ascending = False)[:1000]

....:

In [38]: grouped = names.groupby(['year', 'sex'])

In [39]: top1k = grouped.apply(get_top1k)

In [40]: top1k
Out[40]:
<class 'pandas.core.frame.DataFrame'>
MultiIndex: 261877 entries, (1880, F, 0) to (2010, M, 1677643)
Data columns (total 4 columns):
name 261877 non-null values
sex 261877 non-null values
births 261877 non-null values
year 261877 non-null values
dtypes: int64(2), object(2)

分析一下命名趋势

#首先我们将前1000的名字分成男女两部分
boys = top1k[top1k.sex == 'M']
girls = top1k[top1k.sex == 'F']

#按照year & name 统计的总出生数透视表格
total_births = top1k.pivot_table('births', rows= 'year', cols = 'name', aggfunc = sum)

#整理以后可以利用DataFrame 的plot方法绘制几个名字的曲线图
subset = total_births[['John', 'Harry', 'Mary', 'Marilyn' ]]
subset.plot(subplots=True, figsize = (12,10), grid= False, title='Number of births per year')

很神奇的我们就可以拿到下面的图片。

数据说明有些名字在美国人民中的风光在20世纪中叶达到顶峰。。。是否在现在就风光不再了呢?

评估一下命名的多样性的增长

上图反映的情况是否 说明父母愿意给小孩起常见名字的越来越少了?

我们怎么通过数据去验证这个假定呢?

一种办法是通过计算最流行的1000个名字在总数中所占的比例。

table = top1k.pivot_table('prop', rows='year', cols='sex', aggfunc = sum)
table.plot(title='Sum of table1k.prop by year & sex', yticks=np.linspace(0, 1.2, 13), xticks= range(1880, 2020, 10))

这一讲就到这里了。。。为了给各位同学再多一个偷懒的机会,全部代码统一贴在下面了啊。。。。。

什么?还不会用?? 打开 pylab, ctrl-c ,ctrl-v,所有的数据和图片都有了啊。。。当然你要把names 目录copy到工作目录下面,比如你的桌面上!

** 反正我在Win7下,ctrl-v没有用,要右键再粘贴才可以完整复制Codes

import pandas as pd;import numpy as np
#1880 - 2010 的数据统计
years = range(1880, 2011 )

pieces = []
columns = names= ['name', 'sex', 'births']

for year in years:
path = 'names/yob%d.txt' % year
frame = pd.read_csv(path, names = columns)
frame['year'] = year
pieces.append(frame)

#利用pd.concat 连接数据,将所有数据整合到单个DataFrame中
#注意利用ignore_index = True 可以忽略read_csv 所返回的原始行号
names = pd.concat(pieces, ignore_index = True)

#观察下按照sex & year 统计的出生数量
total_births = names.pivot_table('births', rows= 'year', cols='sex', aggfunc=sum) //应该改为total_births = names.pivot_table('births', 'year', 'sex', aggfunc=sum)
total_births.tail()

#来,我们画个图看看是否重男轻女?
total_births.plot(title='Total births by sex and year')

#我们再插入一个prop列,记录指定婴儿数量相对于总出生人数的比例,我们将按year&sex分组以后进行累加计算比例后新增加到每个分组中
def add_prop(group):
#按照整数除法会出事。。。
births = group.births.astype(float)
group['prop']=births /births.sum()
return group

names = names.groupby(['year', 'sex']).apply(add_prop)


#top 1k 分组
def get_top1k(group):
return group.sort_index(by = 'births', ascending = False)[:1000]

grouped = names.groupby(['year', 'sex'])
top1k = grouped.apply(get_top1k)

#首先我们将前1000的名字分成男女两部分
boys = top1k[top1k.sex == 'M']
girls = top1k[top1k.sex == 'F']

#按照year & name 统计的总出生数透视表格
total_births = top1k.pivot_table('births', rows= 'year', cols = 'name', aggfunc = sum)

#整理以后可以利用DataFrame 的plot方法绘制几个名字的曲线图
subset = total_births[['John', 'Harry', 'Mary', 'Marilyn' ]]
subset.plot(subplots=True, figsize = (12,10), grid= False, title='Number of births per year')

table = top1k.pivot_table('prop', rows='year', cols='sex', aggfunc = sum)
table.plot(title='Sum of table1k.prop by year & sex', yticks=np.linspace(0, 1.2, 13), xticks= range(1880, 2020, 10))

您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码: 验证码,看不清楚?请点击刷新验证码 必填



1760 次浏览
9次
 捐助