第六课 - Pandas进阶
本课剩余内容:
数据的分组和聚合
pandas groupby 方法
pandas agg 方法
pandas apply 方法
案例讲解
鸢尾花案例婴儿姓名案
先来看作业6-1,第一次做作业不偷看答案啦!🤓
作业6-1:
1,计算每个品种鸢尾花各个属性(花萼、花瓣的长度和宽度)的最小值、平均值又是分别是多少? (提示:使用min、mean 方法。)
2,计算鸢尾花每个品种的花萼长度(sepal_length) 大于6cm的数据个数。
读题1,我去翻了一下上课的例子,有一个是求最大值的,那这个最小值,应该就是一样的套路了:
一想,怎么样把最小值和平均值放在同一个表格中呢?按理来说是可以的,一开始我还在想,是不是可以用前面几节课学的 & 呢?不对,这节课老师没有讲到这个用法,再翻翻课上的例子,看到了重点句:
原来 agg函数是这样用的,应用多个函数,用 agg 函数就可以同时召唤它们啦!(感觉上一篇文章白写了😂。。。)
然鹅。。。悲伤的事情又来了
一看到那么长,小白有点慌。。。然而,不熟练并眼瞎的人,看多两眼发现,少了一个方括号!!!!其实第 15 条写得很清楚,这个用法:
# 我们还可以同时应用多个函数,将函数名字放入一个列表即可,内置函数名需要用引号
里面应该划下划线的词有“多个函数”,“列表”,“引号”。特么的列表啊妈蛋哪里会是圆括号啊!明明要方括号。
列表要方括号!
列表要方括号!
第2题,有点难,我卡住了。先不做。。。我去作弊看别人做的作业,为啥就能用一句搞定!!!!我只能想到里面会有 iris / sepal_length / value_counts ,然后纠结要不要重新定义一个新的函数时,王同学的做法就是:iris.loc[iris['sepal_length']>6]["species"].value_counts()
让我膜拜一下。。。
进入正题,这节课第2个案例:全美婴儿姓名案例
是的,你没看错,下载137个文档。
你们知道我在这里卡了多久吗。。。原以为上一篇文章写完,这篇会在第二天就能完成的。每一次!!只要是导入数据的时候!!!我都会被卡!!!这是第3遍了啊傻蛋!!!
我要解释一下我这次是怎么栽的。。。
为什么我会那么清楚137个?
因为我是手动一个个下的,我算了一下,一个文档下载需要点击5次,137*5=865次。发了个朋友圈纪念一下不懂技术的耻辱。我一直以为我能找到那个一键下载的键,像这样的:
然而,我只看到了我的页面是这样的,菠萝老师以为我能听懂git pull是什么,然而我去搜索也是不懂操作:
我能怎么办我也很绝望啊!!
我已经为了找快速下载137个文档的方法,花了一个晚上加一个早上,我觉得这么浪费时间我的文章到下一节课都写不出来的。最后无望地用40分钟,一个个下载完成,然后在 jupyter 新建一个文件夹,用Upload方法,再次一个个点击上载。
才有了最后和老师一样的页面。。。。老泪纵横啊。。。多么不容易。全程傻瓜式操作,见证了我的智商。。呀。。。惨不忍睹
这里的内容比较丰富啊,来一句一句解释内容代表什么,不知道你们到什么水平来,反正我是要细嚼慢咽慢慢理解的。
这是一份从1880年到2016年的数据,年份跨度就从1880-2016,注意右边圆括号的2017啊不是2016啊!所以是 years=range(1880,2017)。
上课老师说 pieces=[ ] 是初始化一个列表来存储每一年的数据时我听着还挺懵,然而在跟着打码的过程的中,以及老师讲到后面这个表格的最后一步是把列表中所有DataFrame整合在一起的时候,我好像有点明白,这一步是把每一年的数据,都做成一个表格啊!然后有137个表格!!不过要操作之前,首先是要将这份137个文档的数据放在和运行代码同一个文件夹里面,方便数据的读取。
由于这里有众多数据文件,我们需要通过循环,来读取文件。循环先开始,需要初始化一些变量,首先是年份years,整数的数列。设置每一列的名称,用来储存将来每一列的列名。每一列的属性分别是 name , gender , frequency。接着可以用 for 循环来读取每一年的数据了,这个循环用 year 来遍历 years 里面的所有数值,也就是year 遍历了从1880到2016年的所有整数: for year in years
path='names/yob%d.txt' % year,在循环中,首先要定义文件的路径名 path,因为我们将数据存储在 names的文件夹下,每一个文件名都是以yob 开头的,紧跟着是一个年代,并以 .txt 结尾,记录每一年的姓名数据,这样就用一个通配符的形式,构造出每一个年代的文件名。这一段的说明我比较不能理解的是txt前面的小写d,到底是干嘛用的,然后就是后面的% 是干嘛用的。哦~这种文科生什么都想去理解的习惯真是要改改了把。。。
然后我们就可以用 pd.read_csv 的方法来读取数据,第一个参数path就是我们刚才定义的文件路径了,第二个参数names等于上面刚刚定义的 columns,这就定义好了数据中每一列的名称了。columns=[ 'names' , 'gender' , 'frequency' ]
frame[ 'year' ] =year : 要是我们需要在DataFrame中加多一列年份year,记录里面的年份,这样通过单个循环,在frame的变量中记录某一年的所有数据,然后将每一年的数据添加到piece的列表中,这样通过for 循环遍历了每一年的数据,那就在列表pieces中存储了所有数据: pieces.append(frame)
现在这些数据存储的是一个个列表的形式,这里可以使用链接的 concat 方法将这些所有的数据整合在一块,得到一个完整的数列。这里的ignore_index,代表可以忽略原有数据中的索引: baby_names = pd.concat(pieces, ignore_index=True 我的理解是,这一步把前面137个表格全部连在一起了,便于后面的输出。
感觉说的转述太多了。。。接上图的代码,我们来运行一下
下面的这个演示,又让我怀疑人生了
左边的是我运行的,右边是老师运行的,要不是因为听到老师说有差不多190万行的时候我还不会去细看自己的数据,我的只有3万多行啊老天!!剩下的180多万行去哪里了!查看一下上面的代码,也没问题啊。我忍着疑惑,在kernel那里选择restart and run all,重新从前面baby_names的定义开始,终于运行到这步,能够和老师的同步了。。。。老泪纵横呀!!
老师又开始运用groupby 了,根据多个属性来分组数据,比如根据年代和性别分组,计算每组数据的大小。也就是看在不同年代,不同性别的姓名数量有多少,即大家能起的名字有多少数量。
可以看出19世纪,可以选择的姓名数量还是比较少的,只有1000多个左右,到了21世纪明显选择就多起来了,比19世纪增加了十几倍。
在不同的年份不同性别中,计算每个名字所占的百分比
首先这是一个分组运算,在年份和性别进行分组,而要计算的百分比占比是没有内置函数的,所以需要自己自定义函数进行运算
读题理解的是,在年份不一样的表格中,一个名字在这个年代,以及这个性别中,使用的频率是多少。所以我们需要的数据是每一个姓名使用的总量,和在这一年且在这个性别中所有姓名使用的总量。
在这个自定义函数中,我们有一个已经分组好的group可以直接用。我们在group中增加一个列名,定义为 pct ,用 group.frequency 取得每一个组姓名的频率,然后用这个频率除上所有使用频率的总和,就能得到一个比例, *100 表示整个比例的单位。然后再用一个新的数据返回,return group。
函数定义好之后,需要的是运行行了,用第六课刚学的 groupby 函数来分出 year 年份和 gender 性别来分组,然后 apply 语法使用自定义计算占比的函数 add_pct 得出姓名的频率,这个是在原来的数据中增加频率新的一列。
rank可以得到根据频次的占比情况。还是按照年份year 和性别 gender 进行分组,然后用 rank 函数,将函数进行排序,默认的排序是从小到大的,这里用ascending 将排序变成从大到小。排第一位的表示在那个年代最流行的名字,也就是使用频率最高的名字。
每年最流行的男孩女孩名字所占的百分比变化趋势如何?
思路:可以使用matlibplot画出rank1的男孩女孩的名字每年所占总人数的百分比
使用Matplotlib工具绘图
下面的线图(line plot)由matlibplot实现,我们可以逐渐添加比如图标题,x轴和y轴的标签等等使图形更加美观。
首先,赋值定义:
从这个输出可以看出,在19世纪的时候最流行的姓名是John,90年代流行的是Michael,到了21世纪是Jacob,到了2012年之后,流行的姓名是Noah,世界末日语言。。诺亚方舟。。。老师的结论是,姓名还是受文化趋势的影响
haha接下来又是高潮了!!!、
plot函数代表选择的是折线图,横坐标是年份,纵坐标是流行姓名的百分比。
我们来看看老师说的美化之后的图,和上图有什么不同,就是把线调整成蓝色,然后把线的宽度设置得粗一点
仿佛听到了图问:“ 我美吗 ?”。。。
图问:“ 我很美是不是? ”
其实。。。真的有在变好看吗。。。
通过 title 这个函数来定义函数的名称,把需要的名称用字符串的形式引起来,用 size 来定义字体的大小,color 定义字体颜色。
最后这部分有3个内置函数,分别是 title, xlabel 和 ylabel,就是在定义的时候,表格的题目,x 轴和 y 轴的名称都是已经标好位置的了,就差赋值了。
老师说,这个最后的图表明,最流行的名字也是会随着年份的增加随之下降的。
男孩的部分完成了,来来来,在学习的你,打开jupyter 看着下图做一下作业吧!先不要往下翻。
我是往上翻的哈哈
下面第一图我就不把全部po出来了,你们按照同样的代码去试试就可以得出一样的结果了。
名字趋势图:
为什么历史上最流行的男孩女孩名字所占的比重逐年降低?
想要解决一个问题,看思路分析先!
要将上面的格式设置成DataFrame格式的话,进行下面的操作了
这是关于年代和性别的层次索引,下列将这个索引变成DataFrame中的一列数据,可以使用reset_index。得到想要的数据后,将此数据存储在 name_count 的数据变量中,以供后面使用。
下面的作图方法跟上面的套路是一样一样的,用布尔索引的方式取得name_count 中男孩的数据。然后绘制折线图,横坐标是年代,纵坐标是可选年代的名字数量。后面就是美化啦!(有点虚心说美化,真心不知道哪里好看了。。。)
这幅图,老师说,可以看出,随着年代的增加,可选姓名的数量也在增加,鹅。。毕竟大家词汇量也在增加嘛😁
下面的女孩姓名数据得出也是一样的套路,一样的结论~
结论:可选择的名字逐年增加,所以流行名字的占比逐年降低
从数据中快速看到一个现象是我们学习数据分析的一个必要技能,让数据告诉我们发生的现象。
作业6-2:
分别找出2015, 2016年最流行的前10个男孩和女孩名字, 想给自己起一个流行的英文名字的可以行动起来了。
提示:使用groupby().apply()
思路一,使用ranked这一列, 取其值小于等于10的数据
思路二,使用pct这一列,用sort_values方法对其排列大小,取最大的10行数据
选做作业:餐馆小费数据分析
小费,指给予服务生消费额以外的赏钱,在美国餐馆用餐完后通常会给服务生15-20%的小费。
这个数据是由Bryant和Smith于1995年所著的商务统计上的一个数据
分析什么因素会影响小费比例?
一个优秀的数据分析员一定是一个可以提出有意义问题的人
好的数据分析员往往可以根据商业背景提出一些假说,然后通过数据来验证这些假说
周三对我来说简直就是Deadline。。。紧张紧张,终于在新课前完成。这周卡的次数太多了,心里奔溃无数次,看到问题自己找不到去请教,多了之后有点不好意思,然后这次的代码从头开始重新打很多次,因为不知道哪里错了,只能全部全新打,小白没有更好的办法了。
学习日记写到现在,越写越长,也想看看跟我一起学习的小伙伴,看我的文章,有没有觉得哪里需要改进,哪里调整之后这份学习日记对需要的人更有价值?
欢迎各位留言或者私信给我哟!
谢谢你们的关注💕💕