说明:本文章为Python数据处理学习日志,主要内容来自书本《利用Python进行数据分析》,Wes McKinney著,机械工业出版社。
1880-2010年间全美婴儿姓名
所需文件在Day2中下载,接下来要用到的一些文件的文件格式如下:
yob1880.txt-yob2010.txt
Mary,F,7065
Anna,F,2604
Emma,F,2003
整合数据
可以看到.txt文件中各个记录字段都以都好‘,’隔开,可以用pandas.read_csv将其加载到DataFrame中:
import pandas as pd
import os
path='E:\\Enthought\\book\\ch02\\names'
os.chdir(path)
names1880 = pd.read_csv('yob1880.txt',names=['name','sex','births'])
names1880[:5]
Out[8]:
name sex births
0 Mary F 7065
1 Anna F 2604
2 Emma F 2003
3 Elizabeth F 1939
4 Minnie F 1746
这些文件中仅含有当年出现超过5次的名字。为简单起见,可以用births列的sex分组小计表示该年度的births总计:
names1880.groupby('sex').births.sum()
Out[11]:
sex
F 90993
M 110493
Name: births, dtype: int64
由于该数据集按年度被分隔成多个文件,所以第一件事情就死要将所有数据都组装到一个DataFrame里面,并加上一个year字段。使用pandas.connect即可达到这个目的:
years = range(1880,2011)
pieces = []
columns = ['names', 'sex','births']
for year in years:
path = 'yob%d.txt' % year
frame = pd.read_csv(path, names=columns)
frame['year'] = year
pieces.append(frame)
names = pd.concat(pieces, ignore_index=True)
#将所有数据整合到单个DataFrame数据里面
names[:5]
Out[25]:
names sex births year
0 Mary F 7065 1880
1 Anna F 2604 1880
2 Emma F 2003 1880
3 Elizabeth F 1939 1880
4 Minnie F 1746 1880
需要注意的有两点:
- concat默认是按行将多个DataFrame组合到一起。
- 必须指定ignore_index=True,因为我们不希望保留read_csv所返回的原始行号。
分析基本特征
现在我们得到一个非常大的DataFrame,它包含全部的名字数据。有了这些数据之后,我们就可以利用groupby或pivot_table在year和sex级别上对其进行聚合了:
total_births = names.pivot_table('births',index='year',columns='sex',aggfunc=sum)
total_births.tail() #查询最后5行数据
Out[36]:
sex F M
year
2006 1896468 2050234
2007 1916888 2069242
2008 1883645 2032310
2009 1827643 1973359
2010 1759010 1898382
绘图:
total_births.plot(title='Total births by sex and year')
Out[37]: <matplotlib.axes._subplots.AxesSubplot at 0x16485d68>
结果:
下面我们来插入一个prop列,用于存放指定名字的婴儿数相对于总出生数的比例。prop值为0.02表示每100个婴儿中有2个取了当前的名字。因此,我们先按year和sex分组,然后再将新列加到哥哥分组上:
def add_prop(group):
births = group.births
#births = group.births.astype(float)
#如果不是python3则要进行类型转换,因为整数除法回向下圆整
group['prop'] = births/births.sum()
return group
names = names.groupby(['year','sex']).apply(add_prop)
names[:5]
Out[42]:
names sex births year prop
0 Mary F 7065 1880 0.077643
1 Anna F 2604 1880 0.028618
2 Emma F 2003 1880 0.022013
3 Elizabeth F 1939 1880 0.021309
4 Minnie F 1746 1880 0.019188
在执行这样的分组处理时,一般都应该做一些有效性检查,比如验证所有分组的prop的总和是否为1。由于这是一个浮点数类型,所以我们用np.allclose来检查这个分总计值是