數(shù)據(jù)分析案例(1880-2010年間全美嬰兒姓名)

用UNIX的head命令查看了其中一個(gè)文件的前10行

!head -n 10 datasets/babynames/yob1880.txt 

不巧的Windows下無法執(zhí)行

!type -10 yob1880.txt 
Windows下貌似只能查看全部
 names1880 = pd.read_csv('yob1880.txt', names=['name', 'sex', 'births'])
加載1880的嬰兒信息

我們可以用births列的sex分組小計(jì)表示該年度的births總計(jì)

names1880.groupby('sex').births.sum() 
用births列的sex分組小計(jì)表示該年度的births總計(jì)

由于該數(shù)據(jù)集按年度被分隔成了多個(gè)文件绿淋,所以第一件事情就是要將所有數(shù)據(jù)都組裝到一個(gè) DataFrame里面,并加上一個(gè)year字段尝盼。使用pandas.concat即可達(dá)到這個(gè)目的:

years = range(1880, 2011)

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

for year in years:
    path = 'babynames/yob%d.txt' % year
    frame = pd.read_csv(path, names=columns)
    frame['year'] = year    
    pieces.append(frame)
多個(gè)文件中的數(shù)據(jù)使用for循環(huán)加載

這里需要注意幾件事情吞滞。第一,concat默認(rèn)是按行將多個(gè)DataFrame組合到一起的;第二裁赠,必須指定ignore_index=True殿漠,因?yàn)槲覀儾幌MA魊ead_csv所返回的原始行號(hào)。

利用groupby或pivot_table在year和sex級(jí)別上對其進(jìn)行聚合了

# Concatenate everything into a single DataFrame 
names = pd.concat(pieces, ignore_index=True)

total_births = names.pivot_table('births', index='year',columns='sex', aggfunc=sum)
簡單聚合

繪制出生嬰兒數(shù)量曲線統(tǒng)計(jì)

total_births.plot(title='Total births by sex and year')
繪制統(tǒng)計(jì)結(jié)果

插入一個(gè)prop列佩捞,用于存放指定名字的嬰兒數(shù)相對于總出生數(shù)的比例:

def add_prop(group):
    group['prop'] = group.births / group.births.sum()
    return group 

names = names.groupby(['year', 'sex']).apply(add_prop)
指定名字的嬰兒數(shù)相對于總出生數(shù)的比例

在執(zhí)行這樣的分組處理時(shí)绞幌,一般都應(yīng)該做一些有效性檢查,比如驗(yàn)證所有分組的prop的總和是否為1

names.groupby(['year', 'sex']).prop.sum() 
有效性驗(yàn)證——比例和為一

工作完成一忱。為了便于實(shí)現(xiàn)更進(jìn)一步的分析莲蜘,我需要取出該數(shù)據(jù)的一個(gè)子集:每對sex/year組合的前1000個(gè)名字。這又是一個(gè)分組操作

def get_top1000(group):
    return group.sort_values(by='births', ascending=False)[:1000] 

grouped = names.groupby(['year', 'sex']) 
top1000 = grouped.apply(get_top1000) 
# Drop the group index, not needed 
top1000.reset_index(inplace=True, drop=True)
創(chuàng)建每年每個(gè)性別的前一千條數(shù)據(jù)

接下來的數(shù)據(jù)分析工作就針對這個(gè)top1000數(shù)據(jù)集

分析命名趨勢

首先將前1000個(gè)名字分為男女兩個(gè)部分

boys = top1000[top1000.sex == 'M']

girls = top1000[top1000.sex == 'F']

生成一張按year和name統(tǒng)計(jì)的總出生數(shù)透視表

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

我們用DataFrame的plot方法繪制幾個(gè)名字的曲線圖

total_births.info()

subset = total_births[['John', 'Harry', 'Mary', 'Marilyn']]

subset.plot(subplots=True, figsize=(12, 10), grid=False, title="Number of births per year")
繪制結(jié)果

評估命名多樣性的增長

計(jì)算流行的1000個(gè)名字所占的比例帘营,按year和sex進(jìn)行聚合并繪圖

table = top1000.pivot_table('prop', index='year',columns='sex', aggfunc=sum)

table.plot(title='Sum of table1000.prop by year and sex',yticks=np.linspace(0, 1.2, 13), xticks=range(1880, 2020,10))
命名多樣性的增長

從圖中可以看出票渠,名字的多樣性確實(shí)出現(xiàn)了增長(前1000項(xiàng)的比例降低)

另一個(gè)辦法是計(jì)算占總出生人數(shù)前50%的不同名字的數(shù)量,這個(gè)數(shù)字不太好計(jì)算芬迄。我們只考慮 2010年男孩的名字:

考慮 2010年男孩

在對prop降序排列之后问顷,我們想知道前面多少個(gè)名字的人數(shù)加起來才夠50%。雖然編寫一個(gè) for循環(huán)確實(shí)也能達(dá)到目的禀梳,但NumPy有一種更聰明的矢量方式杜窄。先計(jì)算prop的累計(jì)和 cumsum,然后再通過searchsorted方法找出0.5應(yīng)該被插入在哪個(gè)位置才能保證不破壞順序

prop_cumsum = df.sort_values(by='prop', ascending=False).prop.cumsum()
前面50%的人名個(gè)數(shù)

由于數(shù)組索引是從0開始的算途,因此我們要給這個(gè)結(jié)果加1羞芍,即終結(jié)果為117

def get_quantile_count(group, q=0.5):
    group = group.sort_values(by='prop', ascending=False)
    return group.prop.cumsum().values.searchsorted(q) + 1

diversity = top1000.groupby(['year', 'sex']).apply(get_quantile_count) 
diversity = diversity.unstack('sex')

diversity.plot()

從圖中可以看出,女孩名字的多樣性總是比男孩的高郊艘,而且還在變得越來越高

男女姓名多樣性變化趨勢

“最后一個(gè)字母”的變革

2007年,一名嬰兒姓名研究人員Laura Wattenberg在她自己的網(wǎng)站上指出(:近百年來唯咬,男孩名字在后一個(gè)字母上的分布發(fā)生了顯著的變化纱注。

首先將全部出生數(shù)據(jù)在年度、性別以及末字母上進(jìn)行了聚合胆胰。

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)

選出具有一定代表性的三年狞贱,并輸出前面幾行

subtable = table.reindex(columns=[1910, 1960, 2010], level='year')
輸出具有一定代表性前面幾行

按總出生數(shù)對該表進(jìn)行規(guī)范化處理,以便計(jì)算出各性別各末字母占總出生人數(shù)的比例

letter_prop = subtable / subtable.sum()
計(jì)算各性別各末字母占總出生人數(shù)的比例

生成一張各年度各性別的條形圖

import matplotlib.pyplot as plt

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)
各年度各性別的條形圖

可以看出蜀涨,從20世紀(jì)60年代開始瞎嬉,以字母”n”結(jié)尾的男孩名字出現(xiàn)了顯著的增長。

回到之前創(chuàng)建的那個(gè)完整表厚柳,按年度和性別對其進(jìn)行規(guī)范化處理氧枣,并在男孩名字中選取幾個(gè)字母,后進(jìn)行轉(zhuǎn)置以便將各個(gè)列做成一個(gè)時(shí)間序列别垮。

letter_prop = table / table.sum()

dny_ts = letter_prop.loc[['d', 'n', 'y'], 'M'].T
轉(zhuǎn)置時(shí)間序列

通過其plot方法繪制出一張趨勢圖


繪制趨勢圖

變成女孩名字的男孩名字

另一個(gè)有趣的趨勢是便监,早年流行于男孩的名字近年來“變性了”,例如Lesley或Leslie∩斩回到 top1000數(shù)據(jù)集毁靶,找出其中以”lesl”開頭的一組名字。

all_names = pd.Series(top1000.name.unique())

lesley_like = all_names[all_names.str.lower().str.contains('lesl')]
以”lesl”開頭的一組名字

利用這個(gè)結(jié)果過濾其他的名字逊移,并按名字分組計(jì)算出生數(shù)以查看相對頻率

filtered = top1000[top1000.name.isin(lesley_like)]

filtered.groupby('name').births.sum() 
按名字分組計(jì)算出生數(shù)以查看相對頻率

按性別和年度進(jìn)行聚合预吆,并按年度進(jìn)行規(guī)范化處理

table = filtered.pivot_table('births', index='year',columns='sex', aggfunc='sum')

table = table.div(table.sum(1), axis=0)
聚合性別和年度,進(jìn)行規(guī)范化處理

繪制一張分性別的年度曲線圖了

性別年度曲線圖
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末胳泉,一起剝皮案震驚了整個(gè)濱河市拐叉,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌胶背,老刑警劉巖巷嚣,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異钳吟,居然都是意外死亡廷粒,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進(jìn)店門红且,熙熙樓的掌柜王于貴愁眉苦臉地迎上來坝茎,“玉大人,你說我怎么就攤上這事暇番∴头牛” “怎么了?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵壁酬,是天一觀的道長次酌。 經(jīng)常有香客問我,道長舆乔,這世上最難降的妖魔是什么岳服? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮希俩,結(jié)果婚禮上吊宋,老公的妹妹穿的比我還像新娘。我一直安慰自己璃搜,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上炸站,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天阀坏,我揣著相機(jī)與錄音,去河邊找鬼。 笑死李命,一個(gè)胖子當(dāng)著我的面吹牛耍鬓,可吹牛的內(nèi)容都是我干的绅这。 我是一名探鬼主播度苔,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼窗市,長吁一口氣:“原來是場噩夢啊……” “哼饮笛!你這毒婦竟也來了咨察?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤福青,失蹤者是張志新(化名)和其女友劉穎摄狱,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體素跺,經(jīng)...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡二蓝,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了指厌。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片刊愚。...
    茶點(diǎn)故事閱讀 38,617評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖踩验,靈堂內(nèi)的尸體忽然破棺而出鸥诽,到底是詐尸還是另有隱情,我是刑警寧澤箕憾,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站钠龙,受9級(jí)特大地震影響碴里,放射性物質(zhì)發(fā)生泄漏咬腋。R本人自食惡果不足惜根竿,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望图贸。 院中可真熱鬧疏日,春花似錦撒汉、人聲如沸挠阁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽寻歧。三九已至码泛,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間卿城,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工多望, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留怀偷,地道東北人椎工。 一個(gè)月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像颅痊,于是被迫代替她去往敵國和親斑响。 傳聞我的和親對象是個(gè)殘疾皇子钳榨,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 目標(biāo) 平常我們做iOS開發(fā),會(huì)經(jīng)常遇到打開其他的APP的功能愤钾。本篇文章講的就是打開別人的APP的一些知識(shí)能颁。我們的目...
    橙娃閱讀 6,547評論 0 5