實戰小練習

分析1880到2017年出生的美國嬰兒姓名

  • 獲取數據
  • 數據規整
  • 分析數據

undefined

一 、獲取數據

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

2、數據規整

由於獲取到的數據是根據出生年份分爲了多個文件,其中文件內部的數據也是簡單的經過逗號分隔而成的,因此須要規整一下:python

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刪除原索引,生成新索引

經過以上操做就能夠將全部的數據文件合併爲一個數據集,接下來就能夠進行具體的數據分析app

三 、分析數據

有了以上數據集就能夠利用他們完成不少工做,例如:字體

一、以性別和出生年份分析總出生數
二、分析命名趨勢
三、分析名字中最後一個字母的變化趨勢

接下來就主要以以上幾種方式進行分析,有其餘方案也能夠本身添加3d

3.1 以性別和出生年份分析總出生數

首先,經過groupby或pivot_table在year和sex上對其進行聚合:code

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將歷年出生孩子總數走勢圖繪製出來blog

# 補充(修改走勢圖標題爲中文):
import matplotlib as mpl
mpl.rcParams['font.sans-serif']=['SimHei'] #指定默認字體 SimHei爲黑體
mpl.rcParams['axes.unicode_minus']=False #用來正常顯示負號
-----------------------------------------------
total_births.plot(title='以性別和出生年份分組的出生總數')

undefined

undefined

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的1unicode

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個名字。get

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='命名趨勢')

undefined

根據以上數據能夠發現美國家長對於給孩子起這些常見名字的趨勢。

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,1970,2015],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')

undefined

接下來就能夠以出現概率最高的三個字母對男生進行分析:

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結尾的男孩人數比例')

undefined

undefined

相關文章
相關標籤/搜索