• 实战练习


    实战练习



    分析1880到2017年出生的美国婴儿姓名


    1、获取数据

    链接:https://pan.baidu.com/s/1wIyRZfgR7EjQ_KFP5-cnaA 
    提取码:g0zy 
    

    2、数据规整

    因为获取到的数据是根据出生年份分为了多个文件,其中文件内部的数据也是简单的通过逗号分隔而成的,所以需要规整一下:

    years = range(1880,2018)
    pieces = []
    columns = ['name','sex','births']  # 字段参数
    for year in years:
        path = "D:\data\names\yob%s.txt"%year  # 加入自己相应的文件路径
        frame = pd.read_csv(path,names=columns)
        frame['year'] = year  # 添加出生年份列
        pieces.append(frame)  
    names = pd.concat(pieces,,ignore_index=True)  # 合并数据集,ignore_index=True删除原索引,生成新索引
    

    通过以上操作就可以将所有的数据文件合并为一个数据集,接下来就可以进行具体的数据分析

    3、分析数据

    有了以上数据集就可以利用他们完成很多工作,例如:

    1、以性别和出生年份分析总出生数
    2、分析命名趋势
    3、分析名字中最后一个字母的变化趋势
    

    接下来就主要以以上几种方式进行分析,有其他方案也可以自己添加

    3.1、以性别和出生年份分析总出生数

    首先,通过groupby或pivot_table在year和sex上对其进行聚合:

    total_births = names.pivot_table('births',index='year',columns='sex',aggfunc=sum)
    total_births.tail()  # 展示最后几列数据
    运行结果:
    sex	    F	    M
    year		
    2013	1750321	1886989
    2014	1781072	1915239
    2015	1778883	1909804
    2016	1763916	1889052
    2017	1711811	1834490
    

    现在就可以通过以上得到的total_births将历年出生孩子总数走势图绘制出来

    # 补充(修改走势图标题为中文):
    import matplotlib as mpl
    mpl.rcParams['font.sans-serif']=['SimHei'] #指定默认字体 SimHei为黑体
    mpl.rcParams['axes.unicode_minus']=False #用来正常显示负号
    -----------------------------------------------
    total_births.plot(title='以性别和出生年份分组的出生总数')
    

    项目1

    3.2、分析命名趋势

    以上数据总量相对来说还是比较大的,所以接下来可以通过一系列操作只取每年取名频率前1000的数据进行分析。

    # 插入一个prop列,用于存放指定名字的婴儿数相对于总出生数的比例。先按year和sex分组,然后再将新列加到各个分组上:
    
    def add_prop(group):
        group['prop'] = group.births / group.births.sum()
        return group
    names = names.groupby(['year','sex').apply(add_prop)
    -----------------------------------------------
    运行结果:
        name	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
    ...	...	...	...	...	...
    1924660	Zykai	M	5	2017	0.000003
    1924661	Zykeem	M	5	2017	0.000003
    1924662	Zylin	M	5	2017	0.000003
    1924663	Zylis	M	5	2017	0.000003
    1924664	Zyrie	M	5	2017	0.000003
    

    接下来,就以上数据做一个简单的小检查,验证所有分组的prop的1

    names.groupby(['year','sex']).prop.sum()  # 验证所有分组的总和是否为1
    运行结果:
    year  sex
    1880  F      1.0
          M      1.0
    1881  F      1.0
          M      1.0
    1882  F      1.0
                ... 
    2015  M      1.0
    2016  F      1.0
          M      1.0
    2017  F      1.0
          M      1.0
    Name: prop, Length: 276, dtype: float64
    

    然后就可以取出一个以上数据的子集,每对sex/year组合的前1000个名字。

    def get_top_1000(group):
        return group.sort_values(by='births',ascending=False)[:1000]
    grouped = names.groupby(['year','sex'])
    top_1000 = grouped.apply(get_top_1000)
    top_1000.reset_index(inplace=True,drop=True)
    

    接下来分析的数据集相对来说就比较小了。

    # 将要分析的数据分为男女两个部分
    
    boys = top_1000[top_1000.sex == 'M']
    
    girls = top_1000[top_1000.sex == 'F']
    
    

    创建一个透视表,以年份为索引,名字为聚合列

    total_births = top_1000.pivot_table('births',index='year',columns='name',aggfunc=sum)
    
    

    然后就可以以几个常用名字绘制曲线图:

    subset = total_births[['John','Harry','Mary','Marilyn']]
    subset.plot(subplots=True,title='命名趋势')
    
    

    项目2

    根据以上数据可以发现美国家长对于给孩子起这些常见名字的趋势。

    3.3、分析名字中最后一个字母的变化趋势

    # 从名称中取出最后一个字母
    get_last_letter  = lambda x: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)
    ----------------------------------------------
    # 取出每隔45年的数据
    subtable = table.reindex(columns=[1880,1925,19702015],level='year')  # 只取部分数据查看针对性数据
    subtable.head()  # 查看前几行
    运行结果:
    sex	    F	                    M
    year	1910	1960	2010	1910	1960	2010
    last_letter						
        a	108397.0	691250.0	676646.0	977.0	5212.0	28859.0
        b	NaN	694.0	455.0	411.0	3914.0	39264.0
        c	5.0	49.0	955.0	482.0	15460.0	23341.0
        d	6751.0	3730.0	2640.0	22113.0	262136.0	44817.0
        e	133600.0	435043.0	316665.0	28665.0	178785.0	130228.0
    ----------------------------------------------
    letter_prop = subtable / subtable.sum()  # 各性别各末位字母占总出生人数的比例
    letter_prop
    运行结果:
    sex	    F	                    M
    year	1910	1960	2010	1910	1960	2010
    last_letter						
        a	0.273383	0.341861	0.381261	0.005031	0.002444	0.015063
        b	NaN	0.000343	0.000256	0.002116	0.001836	0.020493
        c	0.000013	0.000024	0.000538	0.002482	0.007250	0.012183
        d	0.017026	0.001845	0.001488	0.113860	0.122932	0.023392
        e	0.336947	0.215153	0.178427	0.147596	0.083844	0.067971
        ...	...	...	...	...	...	...
        v	NaN	0.000060	0.000117	0.000113	0.000036	0.001449
        w	0.000020	0.000031	0.001189	0.006323	0.007709	0.016176
        x	0.000015	0.000037	0.000729	0.003965	0.001851	0.008597
        y	0.110975	0.152552	0.116769	0.077343	0.160976	0.058182
        z	0.002436	0.000658	0.000700	0.000170	0.000184	0.001825
    ----------------------------------------------
    fig,axes = plt.subplots(2,1,figsize=(15,10))  # 生成两个子图,分别绘制男女生趋势
    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')
    

    项目

    接下来就可以以出现几率最高的三个字母对男生进行分析:

    letter_prop_sum = table / table.sum()  # 以之前创建的完整表计算
    dny_ts = letter_prop_sum.loc[['d','n','y'],'M'].T  # 以标签索引取出的d,n,y字母的数据,最后进行转置
    dny_ts.plot(title='各年名字中以d/n/y结尾的男孩人数比例')
    

    项目4

    我把月亮戳到天上 天就是我的 我把脚踩入地里 地就是我的 我亲吻你 你就是我的
  • 相关阅读:
    java 内部类
    webservice restful rpc
    linux 修改文件权限chmod
    java ThreadLocal的理解
    转:Eclipse常用开发插件
    Eclipse安装插件支持jQuery智能提示
    转:VS2008 vs2010中JQUERY智能提醒
    jquery ui和jquery easy ui的区别
    线程池
    java连接数据库URL
  • 原文地址:https://www.cnblogs.com/zhulipeng-1998/p/12863764.html
Copyright © 2020-2023  润新知