利用Python进行数据分析——第二章 引言(2):利用pandas对babynames数据集进行简单处理
利用Python进行数据分析——第二章 引言(2):利用pandas对babynames数据集进行简单处理
使用数据集为1880年-1929年间美国婴儿名字的频率数据。数据集参见我的资源,附有网址链接。
数据为txt格式,部分数据如下图所示:
根据该数据及,可以进行以下处理:
- 计算指定名字的年度比例;
- 计算某个名字的相对排名;
- 计算各年度最流行的名字,以及增长或减少最快的名字;
- 分析名字的趋势:元音、辅音、长度、总体多样性、拼写变化、首位字母等;
- 分析外源性趋势:圣经中的名字、名人、人口结构变化等。
在次,只进行一些简单的操作。
先对其中一个文件进行操作,查看一下数据的相关内容:
import pandas as pd import matplotlib.pyplot as plt names = ["name","sex","births"]#给定读入数据的标签 names1880 = pd.read_csv("C:/Users/GuanLi/Desktop/babynames/datasetsbabynamesyob1880.txt",sep = ",",names=names) print(names1880[:10])#输出前10条数据进行查看
可以看到前十条数据记录如下,含有姓名name、性别sex、出生数births等字段。
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
按照性别对1880年的出生婴儿总数量进行统计。
sex_births_sum = names1880.groupby("sex").births.sum() print(sex_births_sum)
输出结果如下:
sex F 90993 M 110493 Name: births, dtype: int64
上面是对数据集中1880年的婴儿姓名数据进行处理,所使用的整个数据集含有1880年-1929年共50个数据文件。所以,首先将所有数据整合到一个DataFrame中,并加上一个年份year字段,此处调用pandas.concat。
# coding=gbk import pandas as pd names = ["name","sex","births"] years=range(1880,1930) pieces = [] #通过for循环将50个文件读入 for year in years: path = "C:/Users/GuanLi/Desktop/babynames/datasetsbabynamesyob"+str(year)+".txt" frame = pd.read_csv(path,names = names) frame["year"]=year pieces.append(frame)#将frame添加到列表pieces中 names = pd.concat(pieces,ignore_index=True)##concat默认按行将多个DataFrame组合到一起 print(names)
整合以后的数据部分如下:
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 ... 274820 Yoshimi M 5 1929 274821 Yoshiro M 5 1929 274822 Zeferino M 5 1929 274823 Zell M 5 1929 274824 Zygmund M 5 1929
将50个数据文件整合到一起之后,形成了一个含有274825条记录的数据,含有name、sex、births、year四个字段。
有了这些数据,就可以统计在1880年-1929年间,不同性别下婴儿的数量。
total_births = names.pivot_table("births",index="year",columns="sex",aggfunc=sum) print(total_births)
输出结果如下:
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 1910 396416 194198 1911 418180 225936 1912 557939 429926 1913 624317 512482 1914 761376 654746 1915 983824 848647 1916 1044249 890142 1917 1081194 925512 1918 1157585 1013720 1919 1130149 980215 1920 1198214 1064468 1921 1232845 1101374 1922 1200796 1088380 1923 1206239 1096227 1924 1248821 1132671 1925 1217217 1115798 1926 1185078 1110440 1927 1192207 1126259 1928 1152836 1107113 1929 1116284 1074833
在有了每一年的不同性别下出生婴儿的总数,就可以计算每个名字被使用的比例(频率)。插入prop列用来存放比例。先按year和sex分组,然后将新列(prop列)加到各个分组上。
#定义函数add_prop()来计算比例 def add_prop(group): births = group.births.astype(float)#将出生数births装换成float型数据 group["prop"] = births/births.sum()#计算比例 return group names = names.groupby(["year","sex"]).apply(add_prop) print(names)
输出的结果如下:
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 ... 274820 Yoshimi M 5 1929 0.000005 274821 Yoshiro M 5 1929 0.000005 274822 Zeferino M 5 1929 0.000005 274823 Zell M 5 1929 0.000005 274824 Zygmund M 5 1929 0.000005
如第一行数据prop=0.077643,表示每100个女婴儿中,就有8个(四舍五入)取名为Mary。
另外还可以绘制1880-1929年间美国出生婴儿不同性别随时间的变化图:
year = []#定义一个列表,用来做图的横轴年份 for i in range(1880,1930): year.append(i) fig=plt.figure() ax=fig.add_subplot(1,1,1) ax.set_xlabel=("years") plt.plot(year,total_births["M"]) plt.plot(year,total_births["F"]) plt.legend(loc="best",edgecolor="black")#设置图例边框颜色 plt.legend(loc="best",title="sex") plt.title("Total births by sex and year") plt.show()
绘图结果如下:
在上面一系列操作之后,得到的一个数据集names含有以下字段:name、sex、births、year、prop。在此数据中,我们取出每对sex/year组合的前1000个名字进行进一步的分析工作。
#定义抽取函数get_top1000() def get_top1000(group): return group.sort_index(by="births",ascending=False)[:1000] grouped = names.groupby(["sex","year"]) top1000 = grouped.apply(get_top1000) print(top1000)
接下来的工作在top1000数据集上进行相关的分析。
分析起名字的趋势:
首先将前1000个名字分为男、女两部分。
boys = top1000[top1000.sex == "M"] girls = top1000[top1000.sex == "F"]
在此基础上,可以进行某些名字在美国婴儿中使用的变化情况分析。比如,绘制top1000中,John、Harry、Mary三个名字随时间的变化趋势:
fig1=plt.figure() plt.plot(year,top1000_total_births["John"]) plt.plot(year,top1000_total_births["Harry"]) plt.plot(year,top1000_total_births["Mary"]) plt.title("Number of births per year") plt.legend(loc="best",edgecolor="black",title="name") plt.show()
结果如下图:
可以看出在1880-1929年间,三个名字趋势为先上升后下降。这也说明三个名字在一开始很流行,到后来父母给孩子起比较流行,或者说大众化的名字就很少了。教材上采用了1880-2010年间的数据,可以看到更长时间范围内的变化。
为进一步验证名字的变化趋势,可以计算最流行的1000个名字所占的比例,并绘制变化图。
table=top1000.pivot_table("prop",index="year",columns="sex",aggfunc=sum) fig2=plt.figure() plt.plot(year,table["F"]) plt.plot(year,table["M"]) plt.legend(loc="best") plt.title("sum of top1000.prop by year and sex") plt.show()
结果如下:
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 1910 0.959797 0.969778 1911 0.960108 0.967743 1912 0.955857 0.958370 1913 0.953979 0.955881 1914 0.951697 0.952579 1915 0.948814 0.950604 1916 0.948050 0.950211 1917 0.947547 0.950382 1918 0.946388 0.950806 1919 0.945567 0.949201 1920 0.945281 0.950184 1921 0.945001 0.951235 1922 0.944200 0.950868 1923 0.945099 0.952030 1924 0.944637 0.952422 1925 0.944954 0.953723 1926 0.945526 0.953889 1927 0.945487 0.954031 1928 0.946658 0.954890 1929 0.947905 0.956236
从图中可以看出,名字的多样性出现了增长,从而使某一具体的名字所占比例出现下降。假设我们将名字所占比例从高到低排序,前50%的名字定义为比较流行的名字。那么可以根据前50%名字的数量来观察名字的多样性变化。
def get_quantile_count(group,q=0.5): group = group.sort_index(by="prop",ascending=False) return group.prop.cumsum().searchsorted(q) + 1 diversity = top1000.groupby(["year","sex"]).apply(get_quantile_count) diversity = diversity.unstack("sex") print(diversity) fig3=plt.figure() plt.plot(year,diversity["F"]) plt.plot(year,diversity["M"]) plt.legend(loc="best") plt.title("Number of popular names in top 50%") plt.show()
可以得到1880-1930年间,占比前50%的姓名数量和趋势图:
sex F M year 1880 [38] [14] 1881 [38] [14] 1882 [38] [15] 1883 [39] [15] 1884 [39] [16] ... 1925 [52] [28] 1926 [52] [28] 1927 [52] [28] 1928 [52] [28] 1929 [51] [28]
从图中可以看出女孩姓名的多样性总是比男孩的高。两者的总体变化趋势为升高,即婴儿名字的多样性在升高,名字种类越来越多。
(后面还有名字末字母的分析、名字“变性”分析,_,不做了,哈哈)
- 利用Python进行数据分析(10) pandas基础: 处理缺失数据
- 利用Python进行数据分析(7) pandas基础: Series和DataFrame的简单介绍 一、pandas 是什么 pandas 是基于 NumPy 的一个 Python 数据分析包,主
- 利用python进行数据分析(三):pandas--处理数据的工具
- 利用 Python 进行数据分析(七)pandas 简单介绍(Series 和 DataFrame)
- 利用Python进行数据分析(10) pandas基础: 处理缺失数据
- 利用Python进行数据分析(7) pandas基础: Series和DataFrame的简单介绍
- 利用Python进行数据分析(7) pandas基础: Series和DataFrame的简单介绍
- 利用Python进行数据分析 pandas基础: 处理缺失数据
- 利用Python进行数据分析(11) pandas基础: 层次化索引
- python - 利用Pandas对某app数据进行整理、分析并存入mongodb
- 利用Python进行数据分析(14) pandas基础: 数据转换
- 在Python中利用Pandas库处理大数据的简单介绍
- 利用Pandas进行数据分析(3)——统计、处理缺失值、层次化索引
- 利用Python进行数据分析(六)之pandas基本功能续
- 利用Python进行数据分析_python3实现_pandas入门_相关系数与协方差
- 利用python进行数据分析之pandas库的应用(一)
- 利用Python进行数据分析(13) pandas基础: 数据重塑/轴向旋转
- 利用python进行数据分析——之数据结构pandas(一)
- 利用Python进行数据分析(14) pandas基础: 数据转换
- 利用Python进行数据分析(8) pandas基础: Series和DataFrame的基本操作