US Baby Names 1880-2010

United States Social Security Administration(SSA, 미국사회안전부)에서 1880년부터 지금까지의 출생자의 이름 빈도 데이터를 제공하고 있다.

데이터를 제공하는 URL은 http://www.ssa.gov/oact/babynames/limits.html 이다. names.zip 파일을 내려받아 압축을 풀면 다음과 같은 파일 목록을 볼 수 있다.

$ ls
NationalReadMe.pdf yob1912.txt        yob1945.txt        yob1978.txt
yob1880.txt        yob1913.txt        yob1946.txt        yob1979.txt
yob1881.txt        yob1914.txt        yob1947.txt        yob1980.txt
yob1882.txt        yob1915.txt        yob1948.txt        yob1981.txt
yob1883.txt        yob1916.txt        yob1949.txt        yob1982.txt
yob1884.txt        yob1917.txt        yob1950.txt        yob1983.txt
yob1885.txt        yob1918.txt        yob1951.txt        yob1984.txt
yob1886.txt        yob1919.txt        yob1952.txt        yob1985.txt
yob1887.txt        yob1920.txt        yob1953.txt        yob1986.txt
yob1888.txt        yob1921.txt        yob1954.txt        yob1987.txt
yob1889.txt        yob1922.txt        yob1955.txt        yob1988.txt
yob1890.txt        yob1923.txt        yob1956.txt        yob1989.txt
yob1891.txt        yob1924.txt        yob1957.txt        yob1990.txt
yob1892.txt        yob1925.txt        yob1958.txt        yob1991.txt
yob1893.txt        yob1926.txt        yob1959.txt        yob1992.txt
yob1894.txt        yob1927.txt        yob1960.txt        yob1993.txt
yob1895.txt        yob1928.txt        yob1961.txt        yob1994.txt
yob1896.txt        yob1929.txt        yob1962.txt        yob1995.txt
yob1897.txt        yob1930.txt        yob1963.txt        yob1996.txt
yob1898.txt        yob1931.txt        yob1964.txt        yob1997.txt
yob1899.txt        yob1932.txt        yob1965.txt        yob1998.txt
yob1900.txt        yob1933.txt        yob1966.txt        yob1999.txt
yob1901.txt        yob1934.txt        yob1967.txt        yob2000.txt
yob1902.txt        yob1935.txt        yob1968.txt        yob2001.txt
yob1903.txt        yob1936.txt        yob1969.txt        yob2002.txt
yob1904.txt        yob1937.txt        yob1970.txt        yob2003.txt
yob1905.txt        yob1938.txt        yob1971.txt        yob2004.txt
yob1906.txt        yob1939.txt        yob1972.txt        yob2005.txt
yob1907.txt        yob1940.txt        yob1973.txt        yob2006.txt
yob1908.txt        yob1941.txt        yob1974.txt        yob2007.txt
yob1909.txt        yob1942.txt        yob1975.txt        yob2008.txt
yob1910.txt        yob1943.txt        yob1976.txt        yob2009.txt
yob1911.txt        yob1944.txt        yob1977.txt        yob2010.txt

$ head yob1880.txt
Mary,F,7065
Anna,F,2604
Emma,F,2003
Elizabeth,F,1939
Minnie,F,1746
Margaret,F,1578
Ida,F,1472
Alice,F,1414
Bertha,F,1320
Sarah,F,1288

이 데이터로 어떤 분석들이 가능할까?

  • 특정 이름의 빈도 변화를 그래프로 표시
  • 각 이름의 상대적인 등수 결정
  • 매년 가장 인기있던 이름과 가장 큰 증감률을 보인 이름
  • 이름 유행 분석 등

그럼 지금부터 pandas로 이 데이터분석을 시작해보자.

데이터 로드

In [1]:
%matplotlib inline
import pandas as pd
In [2]:
names1880 = pd.read_csv('/Users/yong27/study/pydata/pydata-book/ch02/names/yob1880.txt', names=['name', 'sex', 'births'])
In [3]:
names1880
Out[3]:
name sex births
0 Mary F 7065
1 Anna F 2604
2 Emma F 2003
3 Elizabeth F 1939
4 Minnie F 1746
5 Margaret F 1578
6 Ida F 1472
7 Alice F 1414
8 Bertha F 1320
9 Sarah F 1288
10 Annie F 1258
11 Clara F 1226
12 Ella F 1156
13 Florence F 1063
14 Cora F 1045
15 Martha F 1040
16 Laura F 1012
17 Nellie F 995
18 Grace F 982
19 Carrie F 949
20 Maude F 858
21 Mabel F 808
22 Bessie F 794
23 Jennie F 793
24 Gertrude F 787
25 Julia F 783
26 Hattie F 769
27 Edith F 768
28 Mattie F 704
29 Rose F 700
... ... ... ...
1970 Philo M 5
1971 Phineas M 5
1972 Presley M 5
1973 Ransom M 5
1974 Reece M 5
1975 Rene M 5
1976 Roswell M 5
1977 Rowland M 5
1978 Sampson M 5
1979 Samual M 5
1980 Santos M 5
1981 Schuyler M 5
1982 Sheppard M 5
1983 Spurgeon M 5
1984 Starling M 5
1985 Sylvanus M 5
1986 Theadore M 5
1987 Theophile M 5
1988 Tilmon M 5
1989 Tommy M 5
1990 Unknown M 5
1991 Vann M 5
1992 Wes M 5
1993 Winston M 5
1994 Wood M 5
1995 Woodie M 5
1996 Worthy M 5
1997 Wright M 5
1998 York M 5
1999 Zachariah M 5

2000 rows × 3 columns

1880년생 이름들이 잘 로드되었다 (상위 2000개 이름들만 제공함). 성별별로 몇명이나 있는지 계산해보자.

In [4]:
names1880.groupby('sex').births.sum()
Out[4]:
sex
F     90993
M    110493
Name: births, dtype: int64

1880년생뿐 아니라 모든 연도 출생자들을 다 로드해보자.

In [5]:
years = range(1880, 2011)
pieces = []
columns = ['name', 'sex', 'births']

for year in years:
    path = '/Users/yong27/study/pydata/pydata-book/ch02/names/yob{}.txt'.format(year)
    frame = pd.read_csv(path, names=columns)
    frame['year'] = year
    pieces.append(frame)
    
names = pd.concat(pieces, ignore_index=True)
In [6]:
names
Out[6]:
name 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
5 Margaret F 1578 1880
6 Ida F 1472 1880
7 Alice F 1414 1880
8 Bertha F 1320 1880
9 Sarah F 1288 1880
10 Annie F 1258 1880
11 Clara F 1226 1880
12 Ella F 1156 1880
13 Florence F 1063 1880
14 Cora F 1045 1880
15 Martha F 1040 1880
16 Laura F 1012 1880
17 Nellie F 995 1880
18 Grace F 982 1880
19 Carrie F 949 1880
20 Maude F 858 1880
21 Mabel F 808 1880
22 Bessie F 794 1880
23 Jennie F 793 1880
24 Gertrude F 787 1880
25 Julia F 783 1880
26 Hattie F 769 1880
27 Edith F 768 1880
28 Mattie F 704 1880
29 Rose F 700 1880
... ... ... ... ...
1690754 Zaviyon M 5 2010
1690755 Zaybrien M 5 2010
1690756 Zayshawn M 5 2010
1690757 Zayyan M 5 2010
1690758 Zeal M 5 2010
1690759 Zealan M 5 2010
1690760 Zecharia M 5 2010
1690761 Zeferino M 5 2010
1690762 Zekariah M 5 2010
1690763 Zeki M 5 2010
1690764 Zeriah M 5 2010
1690765 Zeshan M 5 2010
1690766 Zhyier M 5 2010
1690767 Zildjian M 5 2010
1690768 Zinn M 5 2010
1690769 Zishan M 5 2010
1690770 Ziven M 5 2010
1690771 Zmari M 5 2010
1690772 Zoren M 5 2010
1690773 Zuhaib M 5 2010
1690774 Zyeire M 5 2010
1690775 Zygmunt M 5 2010
1690776 Zykerion M 5 2010
1690777 Zylar M 5 2010
1690778 Zylin M 5 2010
1690779 Zymaire M 5 2010
1690780 Zyonne M 5 2010
1690781 Zyquarius M 5 2010
1690782 Zyran M 5 2010
1690783 Zzyzx M 5 2010

1690784 rows × 4 columns

모든 연도의 데이터가 다 로드되어 names라는 하나의 Dataframe에 저장되었다. 총 1,690,784개의 레코드가 있다.

In [8]:
total_births = names.pivot_table('births', index='year', columns='sex', aggfunc=sum)
In [9]:
total_births
Out[9]:
sex F M
year
1880 90993 110493
1881 91955 100748
1882 107851 113687
1883 112322 104632
1884 129021 114445
1885 133056 107802
1886 144538 110785
1887 145983 101412
1888 178631 120857
1889 178369 110590
1890 190377 111026
1891 185486 101198
1892 212350 122038
1893 212908 112319
1894 222923 115775
1895 233632 117398
1896 237924 119575
1897 234199 112760
1898 258771 122703
1899 233022 106218
1900 299873 150554
1901 239351 106478
1902 264079 122660
1903 261976 119240
1904 275375 128129
1905 291641 132319
1906 295301 133159
1907 318558 146838
1908 334277 154339
1909 347191 163983
... ... ...
1981 1666833 1789568
1982 1692036 1812642
1983 1669486 1790670
1984 1682396 1802735
1985 1719450 1846162
1986 1714053 1839442
1987 1737508 1865113
1988 1779112 1911858
1989 1843057 1999840
1990 1897256 2052070
1991 1874110 2019018
1992 1842818 1995760
1993 1807795 1959712
1994 1784407 1930363
1995 1757240 1902100
1996 1751681 1892700
1997 1739331 1883571
1998 1765390 1909676
1999 1772139 1918267
2000 1813960 1961702
2001 1798284 1940498
2002 1794358 1938941
2003 1824406 1972439
2004 1833005 1981557
2005 1843890 1993285
2006 1896468 2050234
2007 1916888 2069242
2008 1883645 2032310
2009 1827643 1973359
2010 1759010 1898382

131 rows × 2 columns

Dataframe.pivot_table 메쏘드는 테이블내 두 컬럼을 결합한다. 이 데이터를 가지고, 매년 남녀 출생수(births)를 차트로 표시해보자.

In [10]:
total_births.plot(title='Total births by sex and year')
Out[10]:
<matplotlib.axes._subplots.AxesSubplot at 0x108097c18>

매년 남녀 출생수 현황을 한눈에 알 수 있다. 1930년전에는 여자가 많았는데, 그 이후에 남자가 많이지는 점이 이채롭다.

이제, 각 레코드에 "prop" 컬럼을 만들고, 해당 이름의 빈도를 추가해보자.

In [11]:
def add_prop(group):
    #births = group.births.astype(float)
    group['prop'] = group.births / group.births.sum()
    return group

names = names.groupby(['year', 'sex']).apply(add_prop)
In [12]:
names
Out[12]:
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
5 Margaret F 1578 1880 0.017342
6 Ida F 1472 1880 0.016177
7 Alice F 1414 1880 0.015540
8 Bertha F 1320 1880 0.014507
9 Sarah F 1288 1880 0.014155
10 Annie F 1258 1880 0.013825
11 Clara F 1226 1880 0.013474
12 Ella F 1156 1880 0.012704
13 Florence F 1063 1880 0.011682
14 Cora F 1045 1880 0.011484
15 Martha F 1040 1880 0.011429
16 Laura F 1012 1880 0.011122
17 Nellie F 995 1880 0.010935
18 Grace F 982 1880 0.010792
19 Carrie F 949 1880 0.010429
20 Maude F 858 1880 0.009429
21 Mabel F 808 1880 0.008880
22 Bessie F 794 1880 0.008726
23 Jennie F 793 1880 0.008715
24 Gertrude F 787 1880 0.008649
25 Julia F 783 1880 0.008605
26 Hattie F 769 1880 0.008451
27 Edith F 768 1880 0.008440
28 Mattie F 704 1880 0.007737
29 Rose F 700 1880 0.007693
... ... ... ... ... ...
1690754 Zaviyon M 5 2010 0.000003
1690755 Zaybrien M 5 2010 0.000003
1690756 Zayshawn M 5 2010 0.000003
1690757 Zayyan M 5 2010 0.000003
1690758 Zeal M 5 2010 0.000003
1690759 Zealan M 5 2010 0.000003
1690760 Zecharia M 5 2010 0.000003
1690761 Zeferino M 5 2010 0.000003
1690762 Zekariah M 5 2010 0.000003
1690763 Zeki M 5 2010 0.000003
1690764 Zeriah M 5 2010 0.000003
1690765 Zeshan M 5 2010 0.000003
1690766 Zhyier M 5 2010 0.000003
1690767 Zildjian M 5 2010 0.000003
1690768 Zinn M 5 2010 0.000003
1690769 Zishan M 5 2010 0.000003
1690770 Ziven M 5 2010 0.000003
1690771 Zmari M 5 2010 0.000003
1690772 Zoren M 5 2010 0.000003
1690773 Zuhaib M 5 2010 0.000003
1690774 Zyeire M 5 2010 0.000003
1690775 Zygmunt M 5 2010 0.000003
1690776 Zykerion M 5 2010 0.000003
1690777 Zylar M 5 2010 0.000003
1690778 Zylin M 5 2010 0.000003
1690779 Zymaire M 5 2010 0.000003
1690780 Zyonne M 5 2010 0.000003
1690781 Zyquarius M 5 2010 0.000003
1690782 Zyran M 5 2010 0.000003
1690783 Zzyzx M 5 2010 0.000003

1690784 rows × 5 columns

해당 연도, 성별을 그룹으로 하고, 그 그룹에서의 이름 빈도가 추가되었다. 이 빈도가 정확하게 계산되었는지 궁금하다. 한번 확인해보자.

In [13]:
import numpy as np
np.allclose(names.groupby(['year', 'sex']).prop.sum(), 1)
Out[13]:
True

오케이. 이제부터 매년, 각 성별별로 특정 이름의 빈도 변화를 살펴보자. 매년, 각 성별별(그룹별)로 데이터수가 다르니, 그룹별 top1000만 쓰기로 하자.

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

grouped = names.groupby(['year', 'sex'])
top1000 = grouped.apply(get_top1000)
In [15]:
top1000
Out[15]:
name sex births year prop
year sex
1880 F 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
5 Margaret F 1578 1880 0.017342
6 Ida F 1472 1880 0.016177
7 Alice F 1414 1880 0.015540
8 Bertha F 1320 1880 0.014507
9 Sarah F 1288 1880 0.014155
10 Annie F 1258 1880 0.013825
11 Clara F 1226 1880 0.013474
12 Ella F 1156 1880 0.012704
13 Florence F 1063 1880 0.011682
14 Cora F 1045 1880 0.011484
15 Martha F 1040 1880 0.011429
16 Laura F 1012 1880 0.011122
17 Nellie F 995 1880 0.010935
18 Grace F 982 1880 0.010792
19 Carrie F 949 1880 0.010429
20 Maude F 858 1880 0.009429
21 Mabel F 808 1880 0.008880
22 Bessie F 794 1880 0.008726
23 Jennie F 793 1880 0.008715
24 Gertrude F 787 1880 0.008649
25 Julia F 783 1880 0.008605
26 Hattie F 769 1880 0.008451
27 Edith F 768 1880 0.008440
28 Mattie F 704 1880 0.007737
29 Rose F 700 1880 0.007693
... ... ... ... ... ... ... ...
2010 M 1677617 Yair M 201 2010 0.000106
1677616 Talan M 201 2010 0.000106
1677614 Keyon M 201 2010 0.000106
1677613 Kael M 201 2010 0.000106
1677618 Demarion M 200 2010 0.000105
1677619 Gibson M 200 2010 0.000105
1677620 Reagan M 200 2010 0.000105
1677621 Cristofer M 199 2010 0.000105
1677622 Daylen M 199 2010 0.000105
1677623 Jordon M 199 2010 0.000105
1677624 Dashawn M 198 2010 0.000104
1677625 Masen M 198 2010 0.000104
1677629 Rowen M 197 2010 0.000104
1677631 Yousef M 197 2010 0.000104
1677630 Thaddeus M 197 2010 0.000104
1677628 Kadin M 197 2010 0.000104
1677627 Dillan M 197 2010 0.000104
1677626 Clarence M 197 2010 0.000104
1677634 Slade M 196 2010 0.000103
1677632 Clinton M 196 2010 0.000103
1677633 Sheldon M 196 2010 0.000103
1677636 Keshawn M 195 2010 0.000103
1677637 Menachem M 195 2010 0.000103
1677635 Joziah M 195 2010 0.000103
1677638 Bailey M 194 2010 0.000102
1677639 Camilo M 194 2010 0.000102
1677640 Destin M 194 2010 0.000102
1677641 Jaquan M 194 2010 0.000102
1677642 Jaydan M 194 2010 0.000102
1677645 Maxton M 193 2010 0.000102

261877 rows × 5 columns

이로서 top1000 변수에 그룹별 1000개의 이름이 정리됐다.

이름 유행 분석

이름 유행 분석을 해보자. 먼저 top1000을 boys, girls로 분리해보자.

In [17]:
boys = top1000[top1000.sex == 'M']
girls = top1000[top1000.sex == 'F']

그리고, top1000을 피벗테이블로 펼쳐보자.

In [18]:
total_births = top1000.pivot_table('births', index='year', columns='name', aggfunc=sum)
In [19]:
total_births
Out[19]:
name Aaden Aaliyah Aarav Aaron Aarush Ab Abagail Abb Abbey Abbie ... Zoa Zoe Zoey Zoie Zola Zollie Zona Zora Zula Zuri
year
1880 NaN NaN NaN 102.0 NaN NaN NaN NaN NaN 71.0 ... 8.0 23.0 NaN NaN 7.0 NaN 8.0 28.0 27.0 NaN
1881 NaN NaN NaN 94.0 NaN NaN NaN NaN NaN 81.0 ... NaN 22.0 NaN NaN 10.0 NaN 9.0 21.0 27.0 NaN
1882 NaN NaN NaN 85.0 NaN NaN NaN NaN NaN 80.0 ... 8.0 25.0 NaN NaN 9.0 NaN 17.0 32.0 21.0 NaN
1883 NaN NaN NaN 105.0 NaN NaN NaN NaN NaN 79.0 ... NaN 23.0 NaN NaN 10.0 NaN 11.0 35.0 25.0 NaN
1884 NaN NaN NaN 97.0 NaN NaN NaN NaN NaN 98.0 ... 13.0 31.0 NaN NaN 14.0 6.0 8.0 58.0 27.0 NaN
1885 NaN NaN NaN 88.0 NaN 6.0 NaN NaN NaN 88.0 ... 6.0 27.0 NaN NaN 12.0 6.0 14.0 48.0 38.0 NaN
1886 NaN NaN NaN 86.0 NaN NaN NaN NaN NaN 84.0 ... 13.0 25.0 NaN NaN 8.0 NaN 20.0 52.0 43.0 NaN
1887 NaN NaN NaN 78.0 NaN NaN NaN NaN NaN 104.0 ... 9.0 34.0 NaN NaN 23.0 NaN 28.0 46.0 33.0 NaN
1888 NaN NaN NaN 90.0 NaN NaN NaN NaN NaN 137.0 ... 11.0 42.0 NaN NaN 23.0 7.0 30.0 42.0 45.0 NaN
1889 NaN NaN NaN 85.0 NaN NaN NaN NaN NaN 107.0 ... 14.0 29.0 NaN NaN 22.0 NaN 29.0 53.0 55.0 NaN
1890 NaN NaN NaN 96.0 NaN NaN NaN 6.0 NaN 140.0 ... NaN 42.0 NaN NaN 32.0 7.0 27.0 60.0 65.0 NaN
1891 NaN NaN NaN 69.0 NaN NaN NaN NaN NaN 124.0 ... NaN 34.0 NaN NaN 29.0 6.0 14.0 52.0 45.0 NaN
1892 NaN NaN NaN 95.0 NaN NaN NaN NaN NaN 119.0 ... NaN 34.0 NaN NaN 27.0 NaN 25.0 66.0 53.0 NaN
1893 NaN NaN NaN 81.0 NaN NaN NaN NaN NaN 115.0 ... NaN 23.0 NaN NaN 34.0 6.0 15.0 67.0 70.0 NaN
1894 NaN NaN NaN 79.0 NaN NaN NaN NaN NaN 118.0 ... NaN 28.0 NaN NaN 51.0 NaN 23.0 66.0 64.0 NaN
1895 NaN NaN NaN 94.0 NaN NaN NaN NaN NaN 92.0 ... NaN 34.0 NaN NaN 60.0 11.0 38.0 55.0 55.0 NaN
1896 NaN NaN NaN 69.0 NaN NaN NaN NaN NaN 121.0 ... NaN 36.0 NaN NaN 47.0 NaN 38.0 72.0 65.0 NaN
1897 NaN NaN NaN 87.0 NaN NaN NaN NaN NaN 97.0 ... NaN 35.0 NaN NaN 51.0 NaN 28.0 67.0 79.0 NaN
1898 NaN NaN NaN 89.0 NaN NaN NaN NaN NaN 120.0 ... NaN 30.0 NaN NaN 62.0 NaN 28.0 65.0 83.0 NaN
1899 NaN NaN NaN 71.0 NaN NaN NaN NaN NaN 87.0 ... NaN 27.0 NaN NaN 49.0 6.0 31.0 56.0 60.0 NaN
1900 NaN NaN NaN 104.0 NaN NaN NaN NaN NaN 112.0 ... NaN 26.0 NaN NaN 48.0 9.0 44.0 99.0 71.0 NaN
1901 NaN NaN NaN 80.0 NaN NaN NaN NaN NaN 87.0 ... NaN 26.0 NaN NaN 56.0 NaN 31.0 58.0 57.0 NaN
1902 NaN NaN NaN 78.0 NaN NaN NaN NaN NaN 91.0 ... NaN 34.0 NaN NaN 58.0 NaN 23.0 58.0 66.0 NaN
1903 NaN NaN NaN 93.0 NaN NaN NaN NaN NaN 91.0 ... NaN 19.0 NaN NaN 64.0 NaN 41.0 83.0 74.0 NaN
1904 NaN NaN NaN 117.0 NaN NaN NaN NaN NaN 80.0 ... NaN 27.0 NaN NaN 46.0 NaN 35.0 54.0 74.0 NaN
1905 NaN NaN NaN 96.0 NaN NaN NaN NaN NaN 73.0 ... NaN 24.0 NaN NaN 66.0 8.0 24.0 55.0 61.0 NaN
1906 NaN NaN NaN 96.0 NaN NaN NaN NaN NaN 72.0 ... NaN 19.0 NaN NaN 59.0 NaN 37.0 64.0 58.0 NaN
1907 NaN NaN NaN 130.0 NaN NaN NaN NaN NaN 79.0 ... NaN 19.0 NaN NaN 53.0 11.0 39.0 92.0 72.0 NaN
1908 NaN NaN NaN 114.0 NaN NaN NaN NaN NaN 84.0 ... NaN 23.0 NaN NaN 70.0 NaN 31.0 59.0 53.0 NaN
1909 NaN NaN NaN 142.0 NaN NaN NaN NaN NaN 57.0 ... NaN 22.0 NaN NaN 59.0 NaN 39.0 57.0 76.0 NaN
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
1981 NaN NaN NaN 14832.0 NaN NaN NaN NaN 383.0 292.0 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
1982 NaN NaN NaN 14538.0 NaN NaN NaN NaN 372.0 275.0 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
1983 NaN NaN NaN 14627.0 NaN NaN NaN NaN 419.0 223.0 ... NaN 174.0 NaN NaN NaN NaN NaN NaN NaN NaN
1984 NaN NaN NaN 13387.0 NaN NaN NaN NaN 357.0 249.0 ... NaN 200.0 NaN NaN NaN NaN NaN NaN NaN NaN
1985 NaN NaN NaN 13123.0 NaN NaN NaN NaN 314.0 233.0 ... NaN 193.0 NaN NaN NaN NaN NaN NaN NaN NaN
1986 NaN NaN NaN 12685.0 NaN NaN NaN NaN 369.0 228.0 ... NaN 213.0 NaN NaN NaN NaN NaN NaN NaN NaN
1987 NaN NaN NaN 12676.0 NaN NaN NaN NaN 327.0 228.0 ... NaN 248.0 NaN NaN NaN NaN NaN NaN NaN NaN
1988 NaN NaN NaN 14393.0 NaN NaN NaN NaN 404.0 226.0 ... NaN 238.0 NaN NaN NaN NaN NaN NaN NaN NaN
1989 NaN NaN NaN 15312.0 NaN NaN NaN NaN 470.0 265.0 ... NaN 376.0 NaN NaN NaN NaN NaN NaN NaN NaN
1990 NaN NaN NaN 14545.0 NaN NaN NaN NaN 507.0 311.0 ... NaN 478.0 NaN NaN NaN NaN NaN NaN NaN NaN
1991 NaN NaN NaN 14240.0 NaN NaN NaN NaN 451.0 278.0 ... NaN 722.0 NaN NaN NaN NaN NaN NaN NaN NaN
1992 NaN NaN NaN 14494.0 NaN NaN NaN NaN 430.0 260.0 ... NaN 978.0 NaN NaN NaN NaN NaN NaN NaN NaN
1993 NaN NaN NaN 13819.0 NaN NaN NaN NaN 503.0 291.0 ... NaN 1194.0 NaN NaN NaN NaN NaN NaN NaN NaN
1994 NaN 1451.0 NaN 14379.0 NaN NaN NaN NaN 597.0 351.0 ... NaN 1332.0 NaN NaN NaN NaN NaN NaN NaN NaN
1995 NaN 1254.0 NaN 13277.0 NaN NaN NaN NaN 549.0 351.0 ... NaN 1726.0 219.0 NaN NaN NaN NaN NaN NaN NaN
1996 NaN 831.0 NaN 11956.0 NaN NaN NaN NaN 552.0 349.0 ... NaN 2063.0 339.0 NaN NaN NaN NaN NaN NaN NaN
1997 NaN 1737.0 NaN 11156.0 NaN NaN NaN NaN 645.0 386.0 ... NaN 2363.0 407.0 NaN NaN NaN NaN NaN NaN NaN
1998 NaN 1399.0 NaN 10539.0 NaN NaN NaN NaN 661.0 398.0 ... NaN 2690.0 478.0 225.0 NaN NaN NaN NaN NaN NaN
1999 NaN 1088.0 NaN 9846.0 NaN NaN 211.0 NaN 710.0 430.0 ... NaN 3238.0 561.0 257.0 NaN NaN NaN NaN NaN NaN
2000 NaN 1494.0 NaN 9548.0 NaN NaN 222.0 NaN 660.0 432.0 ... NaN 3783.0 691.0 320.0 NaN NaN NaN NaN NaN NaN
2001 NaN 3351.0 NaN 9529.0 NaN NaN 244.0 NaN 687.0 526.0 ... NaN 4642.0 822.0 439.0 NaN NaN NaN NaN NaN NaN
2002 NaN 4775.0 NaN 8993.0 NaN NaN 256.0 NaN 600.0 514.0 ... NaN 4883.0 1182.0 438.0 NaN NaN NaN NaN NaN NaN
2003 NaN 3670.0 NaN 8851.0 NaN NaN 276.0 NaN 625.0 536.0 ... NaN 5080.0 1465.0 448.0 NaN NaN NaN NaN NaN NaN
2004 NaN 3482.0 NaN 8381.0 NaN NaN 258.0 NaN 504.0 500.0 ... NaN 5359.0 1621.0 515.0 NaN NaN NaN NaN NaN NaN
2005 NaN 3452.0 NaN 7796.0 NaN NaN 287.0 NaN 451.0 445.0 ... NaN 4953.0 2266.0 502.0 NaN NaN NaN NaN NaN NaN
2006 NaN 3737.0 NaN 8279.0 NaN NaN 297.0 NaN 404.0 440.0 ... NaN 5145.0 2839.0 530.0 NaN NaN NaN NaN NaN NaN
2007 NaN 3941.0 NaN 8914.0 NaN NaN 313.0 NaN 349.0 468.0 ... NaN 4925.0 3028.0 526.0 NaN NaN NaN NaN NaN NaN
2008 955.0 4028.0 219.0 8511.0 NaN NaN 317.0 NaN 344.0 400.0 ... NaN 4764.0 3438.0 492.0 NaN NaN NaN NaN NaN NaN
2009 1265.0 4352.0 270.0 7936.0 NaN NaN 296.0 NaN 307.0 369.0 ... NaN 5120.0 3981.0 496.0 NaN NaN NaN NaN NaN NaN
2010 448.0 4628.0 438.0 7374.0 226.0 NaN 277.0 NaN 295.0 324.0 ... NaN 6200.0 5164.0 504.0 NaN NaN NaN NaN NaN 258.0

131 rows × 6868 columns

이름이 너무 많으니, 관심있는 이름 John, Harry, Mary, Marilyn만 확인해보자.

In [20]:
subset = total_births[['John', 'Harry', 'Mary', 'Marilyn']]

이 4명을 차트로 표시해보면,

In [21]:
subset.plot(subplots=True, figsize=(12, 10), grid=False, title='Number of births per year')
Out[21]:
array([<matplotlib.axes._subplots.AxesSubplot object at 0x10bce0a20>,
       <matplotlib.axes._subplots.AxesSubplot object at 0x10c1cccf8>,
       <matplotlib.axes._subplots.AxesSubplot object at 0x10beb8f28>,
       <matplotlib.axes._subplots.AxesSubplot object at 0x10bef54e0>], dtype=object)

각 이름별로 매년 어떻게 변화하는지 한눈에 확인이 가능하다.

이름 다양성 증가 확인

위 차트의 설명 가운데 하나는 부모들이 점점 일반적인 이름을 쓰지 않기 때문일 수 있다. 정말 그러한지 확인해보자.

In [22]:
table = top1000.pivot_table('prop', index='year', columns='sex', aggfunc=sum)
In [24]:
table
Out[24]:
sex F M
year
1880 1.000000 0.997375
1881 1.000000 1.000000
1882 0.998702 0.995646
1883 0.997596 0.998566
1884 0.993156 0.994539
1885 0.992251 0.995501
1886 0.989504 0.995035
1887 0.988279 0.996697
1888 0.984241 0.992429
1889 0.984061 0.994981
1890 0.982566 0.992749
1891 0.982177 0.993725
1892 0.979746 0.988815
1893 0.980001 0.991720
1894 0.978571 0.989048
1895 0.975479 0.989071
1896 0.975660 0.988041
1897 0.976558 0.989349
1898 0.972806 0.987197
1899 0.975170 0.990115
1900 0.967760 0.979702
1901 0.972304 0.989603
1902 0.970467 0.985749
1903 0.969490 0.986020
1904 0.968142 0.982502
1905 0.967038 0.981650
1906 0.967535 0.981759
1907 0.964942 0.976975
1908 0.964500 0.976409
1909 0.962744 0.973412
... ... ...
1981 0.867232 0.944762
1982 0.868208 0.944435
1983 0.871602 0.945170
1984 0.870201 0.944705
1985 0.866046 0.942412
1986 0.862619 0.939833
1987 0.858719 0.937574
1988 0.852520 0.934236
1989 0.846535 0.928314
1990 0.840591 0.926585
1991 0.835156 0.923316
1992 0.829654 0.919513
1993 0.826035 0.915127
1994 0.823227 0.911285
1995 0.821738 0.909356
1996 0.817149 0.905296
1997 0.811416 0.901020
1998 0.805665 0.896381
1999 0.799804 0.892714
2000 0.791455 0.887008
2001 0.784125 0.882799
2002 0.780403 0.879775
2003 0.774850 0.876747
2004 0.767291 0.870077
2005 0.762426 0.866514
2006 0.753153 0.860368
2007 0.745959 0.855159
2008 0.740933 0.850003
2009 0.737290 0.845256
2010 0.736780 0.843156

131 rows × 2 columns

In [25]:
table.plot(title='Sum of table1000.prop by year and sex', yticks=np.linspace(0, 1.2, 13), xticks=range(1880, 2020, 10))
Out[25]:
<matplotlib.axes._subplots.AxesSubplot at 0x10c7dc1d0>

그룹별 1000개 레코드의 이름빈도의 합계가 시간이 지날수록 1에서 멀어지는 걸 보아, 다양성이 증가하고 있음을 유추할 수 있다.

또 다른 계산방법으로, 이름빈도로 정렬했을 때, 50%에 도달할 때, 몇명이 있는지 확인할 수 있다. 많을수록 다양하다고 유추할 수 있다. 예를 들어 2010년 출생 남자들은,

In [26]:
df = boys[boys.year == 2010]
In [27]:
df
Out[27]:
name sex births year prop
year sex
2010 M 1676644 Jacob M 21875 2010 0.011523
1676645 Ethan M 17866 2010 0.009411
1676646 Michael M 17133 2010 0.009025
1676647 Jayden M 17030 2010 0.008971
1676648 William M 16870 2010 0.008887
1676649 Alexander M 16634 2010 0.008762
1676650 Noah M 16281 2010 0.008576
1676651 Daniel M 15679 2010 0.008259
1676652 Aiden M 15403 2010 0.008114
1676653 Anthony M 15364 2010 0.008093
1676654 Joshua M 15238 2010 0.008027
1676655 Mason M 14728 2010 0.007758
1676656 Christopher M 14135 2010 0.007446
1676657 Andrew M 14093 2010 0.007424
1676658 David M 14042 2010 0.007397
1676659 Matthew M 13954 2010 0.007350
1676660 Logan M 13943 2010 0.007345
1676661 Elijah M 13735 2010 0.007235
1676662 James M 13714 2010 0.007224
1676663 Joseph M 13657 2010 0.007194
1676664 Gabriel M 12722 2010 0.006701
1676665 Benjamin M 12280 2010 0.006469
1676666 Ryan M 11886 2010 0.006261
1676667 Samuel M 11776 2010 0.006203
1676668 Jackson M 11693 2010 0.006159
1676669 John M 11424 2010 0.006018
1676670 Nathan M 11269 2010 0.005936
1676671 Jonathan M 11028 2010 0.005809
1676672 Christian M 10965 2010 0.005776
1676673 Liam M 10852 2010 0.005716
... ... ... ... ... ...
... Yair M 201 2010 0.000106
1677617 Talan M 201 2010 0.000106
1677616 Keyon M 201 2010 0.000106
1677614 Kael M 201 2010 0.000106
1677613 Demarion M 200 2010 0.000105
1677618 Gibson M 200 2010 0.000105
1677619 Reagan M 200 2010 0.000105
1677620 Cristofer M 199 2010 0.000105
1677621 Daylen M 199 2010 0.000105
1677622 Jordon M 199 2010 0.000105
1677623 Dashawn M 198 2010 0.000104
1677624 Masen M 198 2010 0.000104
1677625 Rowen M 197 2010 0.000104
1677629 Yousef M 197 2010 0.000104
1677631 Thaddeus M 197 2010 0.000104
1677630 Kadin M 197 2010 0.000104
1677628 Dillan M 197 2010 0.000104
1677627 Clarence M 197 2010 0.000104
1677626 Slade M 196 2010 0.000103
1677634 Clinton M 196 2010 0.000103
1677632 Sheldon M 196 2010 0.000103
1677633 Keshawn M 195 2010 0.000103
1677636 Menachem M 195 2010 0.000103
1677637 Joziah M 195 2010 0.000103
1677635 Bailey M 194 2010 0.000102
1677638 Camilo M 194 2010 0.000102
1677639 Destin M 194 2010 0.000102
1677640 Jaquan M 194 2010 0.000102
1677641 Jaydan M 194 2010 0.000102
1677642 Maxton M 193 2010 0.000102

1000 rows × 5 columns

In [28]:
prop_cumsum = df.sort_values(by='prop', ascending=False).prop.cumsum()
In [30]:
prop_cumsum
Out[30]:
year  sex         
2010  M    1676644    0.011523
           1676645    0.020934
           1676646    0.029959
           1676647    0.038930
           1676648    0.047817
           1676649    0.056579
           1676650    0.065155
           1676651    0.073414
           1676652    0.081528
           1676653    0.089621
           1676654    0.097648
           1676655    0.105406
           1676656    0.112852
           1676657    0.120276
           1676658    0.127672
           1676659    0.135023
           1676660    0.142368
           1676661    0.149603
           1676662    0.156827
           1676663    0.164021
           1676664    0.170722
           1676665    0.177191
           1676666    0.183452
           1676667    0.189655
           1676668    0.195815
           1676669    0.201832
           1676670    0.207769
           1676671    0.213578
           1676672    0.219354
           1676673    0.225070
                        ...   
           1677613    0.840147
           1677615    0.840252
           1677616    0.840358
           1677617    0.840464
           1677618    0.840569
           1677619    0.840675
           1677620    0.840780
           1677621    0.840885
           1677622    0.840990
           1677623    0.841095
           1677624    0.841199
           1677625    0.841303
           1677628    0.841407
           1677626    0.841511
           1677627    0.841615
           1677630    0.841718
           1677631    0.841822
           1677629    0.841926
           1677634    0.842029
           1677632    0.842132
           1677633    0.842236
           1677636    0.842338
           1677637    0.842441
           1677635    0.842544
           1677638    0.842646
           1677639    0.842748
           1677640    0.842850
           1677641    0.842953
           1677642    0.843055
           1677645    0.843156
Name: prop, dtype: float64

cumsum 메쏘드는 누적합을 의미한다. 위 데이터에서 0.5에 도달할 때의 index는 searchsorted 메쏘드로 확인한다.

In [31]:
prop_cumsum.searchsorted(0.5)
Out[31]:
array([116])

파이썬이 0부터 카운팅하므로, 117개의 이름이 50%를 차지함을 알 수 있다. 반면에,

In [32]:
df = boys[boys.year == 1900]
in1900 = df.sort_values(by='prop', ascending=False).prop.cumsum()
in1900.searchsorted(0.5) + 1
Out[32]:
array([25])

1900년생은 25명이다. 확실히 다양성이 증가했다.

이를 종합하여 매년 어떻게 변화하는지 살펴보자.

In [33]:
def get_quantile_count(group, q=0.5):
    group = group.sort_values(by='prop', ascending=False)
    return (group.prop.cumsum().searchsorted(q) + 1)[0]

diversity = top1000.groupby(['year', 'sex']).apply(get_quantile_count)
diversity = diversity.unstack('sex')
In [34]:
diversity
Out[34]:
sex F M
year
1880 38 14
1881 38 14
1882 38 15
1883 39 15
1884 39 16
1885 40 16
1886 41 16
1887 41 17
1888 42 17
1889 43 18
1890 44 19
1891 44 20
1892 44 20
1893 44 21
1894 45 22
1895 46 22
1896 46 23
1897 46 23
1898 47 24
1899 47 25
1900 49 25
1901 49 25
1902 49 26
1903 49 27
1904 50 28
1905 50 28
1906 49 28
1907 50 30
1908 49 30
1909 49 30
... ... ...
1981 78 35
1982 75 35
1983 71 34
1984 71 35
1985 72 36
1986 74 37
1987 75 39
1988 78 40
1989 83 43
1990 90 45
1991 95 48
1992 102 51
1993 107 54
1994 111 57
1995 115 60
1996 122 64
1997 129 67
1998 138 70
1999 146 73
2000 155 77
2001 164 81
2002 170 83
2003 178 87
2004 191 92
2005 199 96
2006 209 99
2007 223 103
2008 234 109
2009 241 114
2010 246 117

131 rows × 2 columns

In [35]:
diversity.plot(title="Number of popular names in top 50%")
Out[35]:
<matplotlib.axes._subplots.AxesSubplot at 0x10ce56940>

남자이름 보단 여자이름이 더 다양한 것으로 나옴. 1980년대 이후 특히 증가함을 알 수 있다.

The "Last letter" Revolution

2007년에 출생아 이름 연구가 Laura Wattenberg는 남자이름의 마지막 글자 분포가 지난 100년에 걸처 유의하게 변해왔다고 한다. 확인해보자.

In [36]:
get_last_letter = lambda x: x[-1]
last_letters = names.name.map(get_last_letter)
last_letters.name = 'last_letter'
last_letters
Out[36]:
0          y
1          a
2          a
3          h
4          e
5          t
6          a
7          e
8          a
9          h
10         e
11         a
12         a
13         e
14         a
15         a
16         a
17         e
18         e
19         e
20         e
21         l
22         e
23         e
24         e
25         a
26         e
27         h
28         e
29         e
          ..
1690754    n
1690755    n
1690756    n
1690757    n
1690758    l
1690759    n
1690760    a
1690761    o
1690762    h
1690763    i
1690764    h
1690765    n
1690766    r
1690767    n
1690768    n
1690769    n
1690770    n
1690771    i
1690772    n
1690773    b
1690774    e
1690775    t
1690776    n
1690777    r
1690778    n
1690779    e
1690780    e
1690781    s
1690782    n
1690783    x
Name: last_letter, dtype: object
In [37]:
table = names.pivot_table('births', index=last_letters, columns=['sex', 'year'], aggfunc=sum)
table
Out[37]:
sex F ... M
year 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 ... 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010
last_letter
a 31446.0 31581.0 36536.0 38330.0 43680.0 45408.0 49100.0 48942.0 59442.0 58631.0 ... 39124.0 38815.0 37825.0 38650.0 36838.0 36156.0 34654.0 32901.0 31430.0 28438.0
b NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... 50950.0 49284.0 48065.0 45914.0 43144.0 42600.0 42123.0 39945.0 38862.0 38859.0
c NaN NaN 5.0 5.0 NaN NaN NaN NaN NaN NaN ... 27113.0 27238.0 27697.0 26778.0 26078.0 26635.0 26864.0 25318.0 24048.0 23125.0
d 609.0 607.0 734.0 810.0 916.0 862.0 1007.0 1027.0 1298.0 1374.0 ... 60838.0 55829.0 53391.0 51754.0 50670.0 51410.0 50595.0 47910.0 46172.0 44398.0
e 33378.0 34080.0 40399.0 41914.0 48089.0 49616.0 53884.0 54353.0 66750.0 66663.0 ... 145395.0 144651.0 144769.0 142098.0 141123.0 142999.0 143698.0 140966.0 135496.0 129012.0
f NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... 1758.0 1817.0 1819.0 1904.0 1985.0 1968.0 2090.0 2195.0 2212.0 2255.0
g 7.0 5.0 12.0 8.0 24.0 11.0 18.0 25.0 44.0 28.0 ... 2151.0 2084.0 2009.0 1837.0 1882.0 1929.0 2040.0 2059.0 2396.0 2666.0
h 4863.0 4784.0 5567.0 5701.0 6602.0 6624.0 7146.0 7141.0 8630.0 8826.0 ... 85959.0 88085.0 88226.0 89620.0 92497.0 98477.0 99414.0 100250.0 99979.0 98090.0
i 61.0 78.0 81.0 76.0 84.0 92.0 85.0 105.0 141.0 134.0 ... 20980.0 23610.0 26011.0 28500.0 31317.0 33558.0 35231.0 38151.0 40912.0 42956.0
j NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... 1069.0 1088.0 1203.0 1094.0 1291.0 1241.0 1254.0 1381.0 1416.0 1459.0
k 13.0 15.0 11.0 17.0 21.0 18.0 27.0 19.0 21.0 22.0 ... 42477.0 42043.0 42296.0 41400.0 42151.0 42537.0 42136.0 39563.0 37507.0 35198.0
l 2541.0 2911.0 3527.0 3848.0 4808.0 5144.0 5721.0 6175.0 7900.0 8395.0 ... 153648.0 153493.0 153862.0 152800.0 155312.0 156234.0 155203.0 150791.0 143751.0 133583.0
m 58.0 57.0 81.0 86.0 79.0 75.0 103.0 90.0 123.0 137.0 ... 41967.0 42663.0 42790.0 43054.0 41600.0 42503.0 43860.0 44316.0 46278.0 46808.0
n 3008.0 2959.0 3576.0 3837.0 4507.0 4735.0 5242.0 5512.0 6833.0 7103.0 ... 616099.0 630322.0 663419.0 676011.0 686326.0 720998.0 741355.0 733869.0 715388.0 688677.0
o 30.0 49.0 35.0 47.0 74.0 84.0 93.0 97.0 134.0 142.0 ... 82146.0 83180.0 85423.0 88822.0 92001.0 96350.0 96895.0 91485.0 86423.0 81025.0
p NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... 3419.0 3157.0 2982.0 2841.0 2768.0 2721.0 2739.0 2637.0 2595.0 2409.0
q NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... 602.0 618.0 585.0 523.0 446.0 430.0 431.0 339.0 377.0 342.0
r 481.0 417.0 590.0 640.0 718.0 799.0 917.0 910.0 1207.0 1214.0 ... 165377.0 164821.0 169878.0 169452.0 172069.0 176490.0 177207.0 174632.0 173200.0 166064.0
s 1391.0 1316.0 1637.0 1794.0 2039.0 2127.0 2524.0 2803.0 3582.0 3569.0 ... 143791.0 139595.0 138632.0 139642.0 139913.0 143232.0 142155.0 137056.0 129861.0 123670.0
t 2152.0 2165.0 2399.0 2554.0 2825.0 2889.0 3017.0 3140.0 3816.0 3784.0 ... 47688.0 44991.0 43765.0 43870.0 43369.0 43553.0 43437.0 43846.0 43674.0 43398.0
u 380.0 427.0 410.0 444.0 490.0 495.0 511.0 476.0 541.0 469.0 ... 1833.0 1819.0 2052.0 2138.0 2129.0 2201.0 2311.0 2405.0 2417.0 2318.0
v NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... 1209.0 1332.0 1652.0 1823.0 1794.0 2010.0 2295.0 2418.0 2589.0 2723.0
w NaN 5.0 NaN NaN NaN NaN 5.0 NaN NaN NaN ... 52265.0 50103.0 49079.0 47556.0 45464.0 43217.0 40251.0 36937.0 33181.0 30656.0
x NaN NaN NaN 7.0 NaN NaN NaN NaN NaN NaN ... 10691.0 11009.0 11718.0 12399.0 13025.0 13992.0 14306.0 14834.0 16640.0 16352.0
y 10469.0 10404.0 12145.0 12063.0 13917.0 13927.0 14936.0 14980.0 17931.0 17601.0 ... 139109.0 134557.0 130569.0 128367.0 125190.0 123707.0 123397.0 122633.0 112922.0 110425.0
z 106.0 95.0 106.0 141.0 148.0 150.0 202.0 188.0 238.0 277.0 ... 2840.0 2737.0 2722.0 2710.0 2903.0 3086.0 3301.0 3473.0 3633.0 3476.0

26 rows × 262 columns

연도가 너무 많으니 대표적은 3개의 연도만 확인해보기로 하자.

In [38]:
subtable = table.reindex(columns=[1910, 1960, 2010], level='year')
In [39]:
subtable.sum()
Out[39]:
sex  year
F    1910     396416.0
     1960    2022062.0
     2010    1759010.0
M    1910     194198.0
     1960    2132588.0
     2010    1898382.0
dtype: float64
In [40]:
letter_prop = subtable / subtable.sum()
In [41]:
letter_prop
Out[41]:
sex F M
year 1910 1960 2010 1910 1960 2010
last_letter
a 0.273390 0.341853 0.381240 0.005031 0.002440 0.014980
b NaN 0.000343 0.000256 0.002116 0.001834 0.020470
c 0.000013 0.000024 0.000538 0.002482 0.007257 0.012181
d 0.017028 0.001844 0.001482 0.113858 0.122908 0.023387
e 0.336941 0.215133 0.178415 0.147556 0.083853 0.067959
f NaN 0.000010 0.000055 0.000783 0.004325 0.001188
g 0.000144 0.000157 0.000374 0.002250 0.009488 0.001404
h 0.051529 0.036224 0.075852 0.045562 0.037907 0.051670
i 0.001526 0.039965 0.031734 0.000844 0.000603 0.022628
j NaN NaN 0.000090 NaN NaN 0.000769
k 0.000121 0.000156 0.000356 0.036581 0.049384 0.018541
l 0.043189 0.033867 0.026356 0.065016 0.104904 0.070367
m 0.001201 0.008613 0.002588 0.058044 0.033827 0.024657
n 0.079240 0.130687 0.140210 0.143415 0.152522 0.362771
o 0.001660 0.002439 0.001243 0.017065 0.012829 0.042681
p 0.000018 0.000023 0.000020 0.003172 0.005675 0.001269
q NaN NaN 0.000030 NaN NaN 0.000180
r 0.013390 0.006764 0.018025 0.064481 0.031034 0.087477
s 0.039042 0.012764 0.013332 0.130815 0.102730 0.065145
t 0.027438 0.015201 0.007830 0.072879 0.065655 0.022861
u 0.000684 0.000574 0.000417 0.000124 0.000057 0.001221
v NaN 0.000060 0.000117 0.000113 0.000037 0.001434
w 0.000020 0.000031 0.001182 0.006329 0.007711 0.016148
x 0.000015 0.000037 0.000727 0.003965 0.001851 0.008614
y 0.110972 0.152569 0.116828 0.077349 0.160987 0.058168
z 0.002439 0.000659 0.000704 0.000170 0.000184 0.001831

이를 차트로 표시해보면,

In [42]:
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)
Out[42]:
<matplotlib.axes._subplots.AxesSubplot at 0x10d7b0d68>

남자의 경우, 1960년대 이후, "n"으로 끝나는 이름이 현저히 늘었다. 이를 전체 그룹에 대해 확장해보자.

In [43]:
letter_prop = table / table.sum()
dny_ts = letter_prop.ix[['d', 'n', 'y'], 'M'].T
dny_ts
Out[43]:
last_letter d n y
year
1880 0.083055 0.153213 0.075760
1881 0.083247 0.153214 0.077451
1882 0.085340 0.149560 0.077537
1883 0.084066 0.151646 0.079144
1884 0.086120 0.149915 0.080405
1885 0.085472 0.146361 0.081882
1886 0.087647 0.149659 0.081681
1887 0.089072 0.148838 0.082870
1888 0.087707 0.151286 0.084919
1889 0.091934 0.151976 0.086328
1890 0.093834 0.146470 0.086277
1891 0.094478 0.148353 0.084933
1892 0.096388 0.144857 0.084883
1893 0.098318 0.142558 0.084643
1894 0.100462 0.142112 0.085554
1895 0.100019 0.143350 0.083332
1896 0.102881 0.140631 0.083922
1897 0.101987 0.140112 0.083283
1898 0.104887 0.139614 0.090633
1899 0.105020 0.140607 0.084807
1900 0.102946 0.137645 0.084661
1901 0.106792 0.141428 0.081754
1902 0.108022 0.140641 0.081901
1903 0.109577 0.141337 0.080309
1904 0.109335 0.143145 0.080739
1905 0.110226 0.142429 0.079331
1906 0.111836 0.141447 0.078786
1907 0.112689 0.143328 0.079046
1908 0.113899 0.143146 0.078593
1909 0.115500 0.144204 0.077386
... ... ... ...
1981 0.069564 0.247668 0.109612
1982 0.067343 0.247982 0.107810
1983 0.064590 0.250570 0.103872
1984 0.062247 0.249121 0.104434
1985 0.060067 0.249074 0.106783
1986 0.058999 0.248461 0.108102
1987 0.057410 0.248466 0.108872
1988 0.054987 0.250193 0.108163
1989 0.052868 0.251095 0.106309
1990 0.049690 0.254481 0.104817
1991 0.046487 0.260756 0.103390
1992 0.043886 0.269240 0.101575
1993 0.042119 0.271248 0.100591
1994 0.039973 0.278569 0.096975
1995 0.038017 0.284643 0.091720
1996 0.037067 0.289856 0.087609
1997 0.036652 0.293351 0.083793
1998 0.035442 0.298259 0.079016
1999 0.034149 0.304703 0.076184
2000 0.032753 0.313060 0.073000
2001 0.031352 0.317495 0.071687
2002 0.028794 0.325086 0.069397
2003 0.027069 0.336344 0.066197
2004 0.026118 0.341151 0.064781
2005 0.025420 0.344319 0.062806
2006 0.025075 0.351666 0.060338
2007 0.024451 0.358274 0.059634
2008 0.023574 0.361101 0.060342
2009 0.023398 0.362523 0.057223
2010 0.023387 0.362771 0.058168

131 rows × 3 columns

이를 차트로 표시하면,

In [44]:
dny_ts.plot()
Out[44]:
<matplotlib.axes._subplots.AxesSubplot at 0x10fa79278>

전체 연도로 패턴을 보니, 확실히 "n"으로 끝나는 빈도가 증가하고 있다.

성별이 바뀌는 이름

성별이 바뀌는 이름들이 있다. Lesley, Leslie 이름이 대표적인 예. 이를 구체적으로 확인해보자.

In [45]:
all_names = top1000.name.unique()
mask = np.array(['lesl' in x.lower() for x in all_names])
lesley_like = all_names[mask]
lesley_like
Out[45]:
array(['Leslie', 'Lesley', 'Leslee', 'Lesli', 'Lesly'], dtype=object)
In [46]:
filtered = top1000[top1000.name.isin(lesley_like)]
filtered.groupby('name').births.sum()
Out[46]:
name
Leslee      1082
Lesley     35022
Lesli        929
Leslie    370429
Lesly      10067
Name: births, dtype: int64
In [47]:
table = filtered.pivot_table('births', index='year', columns='sex', aggfunc=sum)
table
Out[47]:
sex F M
year
1880 8.0 79.0
1881 11.0 92.0
1882 9.0 128.0
1883 7.0 125.0
1884 15.0 125.0
1885 10.0 122.0
1886 8.0 136.0
1887 12.0 166.0
1888 23.0 175.0
1889 23.0 155.0
1890 20.0 181.0
1891 28.0 164.0
1892 22.0 207.0
1893 26.0 185.0
1894 36.0 223.0
1895 22.0 235.0
1896 27.0 237.0
1897 34.0 222.0
1898 24.0 236.0
1899 18.0 181.0
1900 30.0 285.0
1901 29.0 204.0
1902 37.0 251.0
1903 24.0 244.0
1904 30.0 243.0
1905 35.0 247.0
1906 29.0 263.0
1907 34.0 273.0
1908 41.0 290.0
1909 35.0 292.0
... ... ...
1981 5796.0 500.0
1982 5814.0 430.0
1983 4975.0 414.0
1984 4419.0 367.0
1985 4168.0 331.0
1986 3741.0 379.0
1987 3666.0 290.0
1988 3555.0 318.0
1989 3259.0 327.0
1990 3268.0 295.0
1991 2920.0 277.0
1992 2836.0 216.0
1993 2607.0 201.0
1994 2685.0 207.0
1995 2782.0 186.0
1996 3584.0 176.0
1997 3847.0 158.0
1998 4289.0 NaN
1999 4693.0 NaN
2000 5019.0 NaN
2001 4920.0 NaN
2002 4708.0 NaN
2003 4924.0 NaN
2004 4694.0 NaN
2005 4284.0 NaN
2006 4166.0 NaN
2007 3805.0 NaN
2008 3022.0 NaN
2009 2573.0 NaN
2010 2060.0 NaN

131 rows × 2 columns

In [48]:
table = table.div(table.sum(1), axis=0)
table
Out[48]:
sex F M
year
1880 0.091954 0.908046
1881 0.106796 0.893204
1882 0.065693 0.934307
1883 0.053030 0.946970
1884 0.107143 0.892857
1885 0.075758 0.924242
1886 0.055556 0.944444
1887 0.067416 0.932584
1888 0.116162 0.883838
1889 0.129213 0.870787
1890 0.099502 0.900498
1891 0.145833 0.854167
1892 0.096070 0.903930
1893 0.123223 0.876777
1894 0.138996 0.861004
1895 0.085603 0.914397
1896 0.102273 0.897727
1897 0.132812 0.867188
1898 0.092308 0.907692
1899 0.090452 0.909548
1900 0.095238 0.904762
1901 0.124464 0.875536
1902 0.128472 0.871528
1903 0.089552 0.910448
1904 0.109890 0.890110
1905 0.124113 0.875887
1906 0.099315 0.900685
1907 0.110749 0.889251
1908 0.123867 0.876133
1909 0.107034 0.892966
... ... ...
1981 0.920584 0.079416
1982 0.931134 0.068866
1983 0.923177 0.076823
1984 0.923318 0.076682
1985 0.926428 0.073572
1986 0.908010 0.091990
1987 0.926694 0.073306
1988 0.917893 0.082107
1989 0.908812 0.091188
1990 0.917205 0.082795
1991 0.913356 0.086644
1992 0.929227 0.070773
1993 0.928419 0.071581
1994 0.928423 0.071577
1995 0.937332 0.062668
1996 0.953191 0.046809
1997 0.960549 0.039451
1998 1.000000 NaN
1999 1.000000 NaN
2000 1.000000 NaN
2001 1.000000 NaN
2002 1.000000 NaN
2003 1.000000 NaN
2004 1.000000 NaN
2005 1.000000 NaN
2006 1.000000 NaN
2007 1.000000 NaN
2008 1.000000 NaN
2009 1.000000 NaN
2010 1.000000 NaN

131 rows × 2 columns

In [49]:
table.plot(style={'M': 'k-', 'F': 'k--'})
Out[49]:
<matplotlib.axes._subplots.AxesSubplot at 0x1102b5630>

"Lesl~"로 시작하는 이름은 1940년대에는 남자이름이었다가 그후 빠르게 여자이름으로 바뀜.

In [ ]: