美文网首页
14_3_美国1880_2010年的婴儿名字

14_3_美国1880_2010年的婴儿名字

作者: 弦好想断 | 来源:发表于2020-05-11 13:58 被阅读0次
    more babynames\yob1880.txt
    

    more命令直接在文本编辑器中打开。

    import pandas as pd
    import numpy as np
    names1880=pd.read_csv('babynames\yob1880.txt',names=['name','sex','births'])
    names1880.head()
    
    names1880.groupby('sex').sum()#婴儿的出生总数
    names1880.groupby('sex').size()#名字的个数
    

    因为原数据的每份文件都分散地按年的存储为很多个TXT文件,这里将所有数据集集中到一个DataFrame中,然后再添加一个对应的年份字段。

    years = range(1880,2011)
    pieces = []
    columns = ['name','sex','births']
    for year in years:
       path = 'babynames\yob%d.txt' % year#这里匹配的是%d对应的值
       frame = pd.read_csv(path,names=columns)
       frame['year']=year
       pieces.append(frame)
    names = pd.concat(pieces,ignore_index=True)#concat默认情况下将DataFrame对象以逐行方式联合在一起。
    names#传递ignore_index=True,不保留原始索引
    

    透视表的方法取出每年的出生人数按性别求和

    total_births=names.pivot_table(values='births',index='year',columns='sex',aggfunc=sum)
    total_births.head()
    

    画个图

    total_births.plot(title='Total borths 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
    

    进行完整性检查

    names.groupby(['year','sex']).prop.sum()
    year  sex
    1880  F      1.0
          M      1.0
    1881  F      1.0
          M      1.0
    1882  F      1.0
                ... 
    2008  M      1.0
    2009  F      1.0
          M      1.0
    2010  F      1.0
          M      1.0
    Name: prop, Length: 262, dtype: float64
    

    每个性别/年份组合的前1000名(认真看传入参数)

    #受欢迎的名字的前1000名(通过起名的个数进行排序)
    def get_top1000(group):
        return group.sort_values(by='births',ascending=False)[:1000]
    top1000 = names.groupby(['year','sex'],group_keys=False).apply(get_top1000)
    #重置索引
    top1000.reset_index(inplace=True,drop=True)
    top1000
    
    #使用DIY方式
    pieces = []
    for year,group in names.groupby(['year','sex']):
        pieces.append(group.sort_values(by='births',ascending=False)[:1000])
    top1000 = pd.concat(pieces,ignore_index=True)
    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
    

    绘制少数名称的数据透视表

    #一些男孩名字和女孩名字随时间变化的趋势
    subset=total_births[['John','Harry','Mary','Marilyn']]
    subset.plot(subplots=True,figsize=(12,10),grid=False,title='Number of births per year')
    

    起常用名字(前1000)的概率随时间的变化

    #受欢迎的名字在每一年的出现概率
    table = top1000.pivot_table('prop',index='year',columns='sex',aggfunc=sum)
    #受欢迎(前1000)的名字出现概率随时间变化
    table.plot(title='Sum of top1000.prop by year and sex',xticks=range(1880,2010,10),yticks=np.linspace(0,1.2,13))
    

    我们看看2010年男孩的名字

    df2010 = boys[boys.year==2010]
    df2010
    
    in2010 = df2010.sort_values(by='prop',ascending=False).prop.cumsum()#按降序,累加求和
    in2010
    260877    0.011523
    260878    0.020934
    260879    0.029959
    260880    0.038930
    260881    0.047817
                ...   
    261872    0.842748
    261873    0.842850
    261874    0.842953
    261875    0.843055
    261876    0.843156
    Name: prop, Length: 1000, dtype: float64
    in2010.values.searchsorted(0.5)#索引为116时累加和达到0.5
    116#由于数组是零索引的,所以要+1变成117
    

    按性别和年龄分组,受欢迎程度前50%的姓名个数

    def get_quantile_count(group,q=0.5):
        group = group.sort_values(by='prop',ascending=False).prop.cumsum()
        return group.values.searchsorted(q)+1
    #按性别和年龄分组,受欢迎程度前50%的姓名个数
    top1000.groupby(['year','sex']).apply(get_quantile_count)
    year  sex
    1880  F       38
          M       14
    1881  F       38
          M       14
    1882  F       38
                ... 
    2008  M      109
    2009  F      241
          M      114
    2010  F      246
          M      117
    Length: 262, dtype: int64
    
    diversity = top1000.groupby(['year','sex']).apply(get_quantile_count)
    diversity.unstack('sex')
    
    diversity.plot(title='Number of popular names in top 50%')
    

    最后一个字母

    从name列提取最后一个字母

    last_letters = names.name.map(lambda x:x[-1])
    last_letters.name = 'last_letter'
    lsat_letters
    
    table = names.pivot_table(values='births',index = last_letters,columns=['sex','year'],aggfunc=sum)
    table
    
    #选出三个具有代表性的年份
    suitable=table.reindex(columns=[1910,1960,2010],level='year')
    suitabl
    
    #归一化处理
    letter_prop = suitable/suitable.sum()
    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)
    #关键字参数必须跟随在位置参数后面
    

    以n结尾的男孩名字经历了显著的增长

    #为男孩名字选择一个字母子集,最后转换为使每列成为一个时间序列
    letter_prop = table/table.sum()
    dny_ts = letter_prop.loc[['d','y','n'],'M'].T#所有男性
    dny_ts
    
    dny_ts.plot()
    #姓名以‘y’,'d','n'结尾的男性婴儿的频率标准化后的值
    

    男孩变成女孩名字趋势

    all_names = pd.Series(top1000.name.unique())
    lesley_like = all_names[all_names.str.lower().str.contains('lesl')]
    filterend = top1000[top1000.name.isin(lesley_like)]
    filterend
    
    filterend.groupby('name').births.sum()
    name
    Leslee      1082
    Lesley     35022
    Lesli        929
    Leslie    370429
    Lesly      10067
    Name: births, dtype: int64
    
    table = filterend.pivot_table('births',index='year',columns='sex',aggfunc=sum)
    table
    
    table = table.div(table.sum(1),axis=0)
    table.plot(style={'M':'k-','F':'k--'})
    

    代码细节值得考量,分析思路要多看几遍。

    相关文章

      网友评论

          本文标题:14_3_美国1880_2010年的婴儿名字

          本文链接:https://www.haomeiwen.com/subject/hliynhtx.html