4. 优雅的apply
2020/7/7 17:26:58
本文主要是介绍4. 优雅的apply,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
引言
本文主要讲的是Pandas中第二好用的函数——apply。为什么说第二好用呢?做人嘛,最重要的就是谦虚,做函数也是一样的,而apply就是这样一个优雅而谦虚的函数。
我们单独用一篇来为apply树碑立传,原因有二,
- 一是因为apply函数极其灵活高效,甚至是重新定义了pandas的灵活,一旦熟练运用,在数据清洗和分析界可谓是“屠龙在手,天下我有”
- 二是apply概念相对晦涩,需要结合具体案例去咀嚼和实践。
Apply初体验
apply函数,因为她总是和分组函数
一起出现,所以在江湖得了个·groupby伴侣·的称号。她的主要作用是做聚合运算
,以及在分组基础上根据实际情况来自定义一些规则,常见用法和参数如下:
df.groupby(['列名']).apply(func,args) 复制代码
- 参数func是最重要参数,它接受一个函数,会把分组后的数据根据函数来进行处理。
- args参数是我们可以给函数传入的参数,这个仅了解,用到的比较少。
如果把源数据比作面粉,groupby分组就是把面粉揉成一个个面团的过程,apply起到的作用,是根据数据
需求来调馅
,并且把每一个面团包成我们喜欢的包子
。接下来,我们通过两个场景,更深入的感受下apply函数的优雅迷人。
场景一
背景
:我们拿到了一份4位同学三次模拟考试的成绩,想知道每位同学历次模拟中最好成绩和最差成绩分别是多少。
思路
:最好和最差,分别对应着max与min,我们先按姓名分组,再用apply函数返回对应的最大和最小值,最终将结果合并。
先导入源数据:
max_score = score.groupby('姓名')['综合成绩'].apply(max).reset_index() max_score 复制代码我们指定
综合成绩
列,然后把max函数直接传入apply参数内,返回了对应分组内成绩的最大值。有一些常见函数,如max、min、len等函数可以直接传入apply
。
groupby分组默认会把分组依据列(姓名
)变成索引,这里用reset_index
方法重置或者说取消姓名索引,将它保留在列的位置,维持DataFrame格式,方便后续匹配。
再筛选出最低成绩:
min_score = score.groupby('姓名')['综合成绩'].apply(min).reset_index() min_score 复制代码两张表按姓名合并:
score_combine = pd.merge(max_score,min_score,left_on='姓名',right_on='姓名',how='inner') score_combine.columns=['姓名', '最好成绩', '最差成绩'] score_combine 复制代码得到了我们预期的结果,只是列名略丑,可以用
.columns
方法来赋值更改。场景一比较死板和严肃,场景二我们换个更接地气的风格。
场景二
背景
:Boss丢过来一份省市销售表,里面包含省份、城市、最近1个月销售额3个字段,想看看每个省份销售排名第3的都是哪些城市,以及他们的销售额情况。
思路
:问题的关键是找到每个省份销售排名第3的城市,首先,应该对省份、城市按销售额进行降序排列,然后,找到对应排名第3的城市,Emmm,如果是排名第1的城市,我们可以通过排序后去重实现,
要得到销售排名第3的城市,要先进行排序,这里我们用省份、近1月销售额两个关键字段进行降序排列,得到我们期待的顺序:
接着,在apply函数登场前,我们先详细剖析一下整个过程: apply的精髓,在于揉面
和DIY(调馅)包子
。我们需要把源数据(面粉)给揉成一个个面团,再把一个个面团DIY成我们想要口味的包子。其中,揉面的过程就是groupby分组
,而DIY调馅做包子就是apply自定义函数和应用
的过程。
结合我们的目标,揉面是按省份进行分组,得到每个省各个城市和对应销售额的面团;DIY包子是在每个面团中取其第三名的城市和销售额字段。
第一步分组非常简单,按省份分组即可。而取第3名的城市和销售,表明我们需要城市和销售两个字段,所以在分组后指明这两列:
这一步,我们已经揉好了面,原始的面团也初步成型,虽然返回的结果有点晦涩,但是我们可以在脑海中构建一下这些面团,截图只展示了部分: 要把这些面团包成包子,就是要我们取出每一个面团中,排名第3的城市。有个问题需要注意,有一些直辖市是和省并列的,而作为城市只有单独的一行,这样的城市我们就默认返回其本身的数据;对于非直辖市省份来说,就需要定位筛选。拿x2来举例,要找到这个面团中排名第三的城市和销售额,应该怎么做呢?答案是直接索引,把他看作是一个DataFrame格式的表,要选取第3行的所有值,包括城市和销售额,这里用iloc索引,很简单的一行代码:
x2.icol[2,:] 复制代码
def get_third(x): # 如果分组长度<=1 说明是直辖市 if len(x) <=1: return x.iloc[0,:] # 返回第0行所有值 也就是直辖市本身 else: return x.iloc[2,:] 复制代码至此,每个省份,销售额排名
第三
的城市已经成功筛选出来。回顾整个操作流程,先排序
,后分组
,最后通过定义函数传入apply
,提取出我们的目标值。分组后数据的抽象形态,以及如何判断和取出我们需要的值,是解决问题的关键和难点。
数据
成绩表
姓名 | 科目 | 综合成绩 |
---|---|---|
李华 | 一模 | 651 |
李华 | 二模 | 579 |
李华 | 三模 | 580 |
王雷 | 一模 | 475 |
王雷 | 二模 | 455 |
王雷 | 三模 | 432 |
张建国 | 一模 | 691 |
张建国 | 二模 | 582 |
张建国 | 三模 | 553 |
李子明 | 一模 | 490 |
李子明 | 二模 | 552 |
李子明 | 三模 | 577 |
省市销售数据
省份 | 城市 | 近1月销售额 |
---|---|---|
重庆 | 重庆市 | 255343 |
浙江省 | 金华市 | 302624 |
浙江省 | 台州市 | 147853 |
浙江省 | 舟山市 | 136547 |
浙江省 | 杭州市 | 109073 |
浙江省 | 宁波市 | 67409 |
浙江省 | 嘉兴市 | 63883 |
浙江省 | 衢州市 | 34773 |
浙江省 | 丽水市 | 31285 |
浙江省 | 绍兴市 | 22184 |
浙江省 | 湖州市 | 20867 |
浙江省 | 温州市 | 15099 |
云南省 | 临沧市 | 666949 |
云南省 | 大理白族自治州 | 554325 |
云南省 | 昆明市 | 203210 |
云南省 | 保山市 | 164794 |
云南省 | 昭通市 | 123129 |
云南省 | 德宏傣族景颇族自治州 | 84815 |
云南省 | 红河哈尼族彝族自治州 | 31244 |
云南省 | 玉溪市 | 29546 |
云南省 | 西双版纳傣族自治州 | 16479 |
天津 | 天津市 | 510720 |
四川省 | 南充市 | 532493 |
四川省 | 眉山市 | 460836 |
四川省 | 达州市 | 427285 |
四川省 | 德阳市 | 392361 |
四川省 | 成都市 | 262325 |
四川省 | 自贡市 | 179184 |
四川省 | 巴中市 | 65975 |
四川省 | 雅安市 | 52585 |
四川省 | 内江市 | 30951 |
四川省 | 乐山市 | 24635 |
四川省 | 凉山彝族自治州 | 22985 |
四川省 | 广元市 | 21433 |
四川省 | 绵阳市 | 20530 |
四川省 | 广安市 | 5206 |
上海 | 上海市 | 139261 |
陕西省 | 西安市 | 450490 |
陕西省 | 延安市 | 120161 |
陕西省 | 安康市 | 60456 |
陕西省 | 汉中市 | 59391 |
陕西省 | 咸阳市 | 47411 |
陕西省 | 榆林市 | 36144 |
陕西省 | 宝鸡市 | 29488 |
山西省 | 大同市 | 354828 |
山西省 | 晋中市 | 252932 |
山西省 | 临汾市 | 186931 |
山西省 | 运城市 | 153765 |
山西省 | 朔州市 | 91025 |
山西省 | 晋城市 | 65112 |
山西省 | 太原市 | 49023 |
山西省 | 忻州市 | 36324 |
山西省 | 吕梁市 | 27027 |
山西省 | 阳泉市 | 23328 |
山西省 | 长治市 | 10753 |
山东省 | 济南市 | 355393 |
山东省 | 济宁市 | 329062 |
山东省 | 菏泽市 | 187375 |
山东省 | 潍坊市 | 136845 |
山东省 | 临沂市 | 83493 |
山东省 | 日照市 | 69346 |
山东省 | 泰安市 | 64255 |
山东省 | 滨州市 | 49878 |
山东省 | 淄博市 | 44215 |
山东省 | 威海市 | 41281 |
山东省 | 东营市 | 32000 |
山东省 | 青岛市 | 30497 |
山东省 | 烟台市 | 21219 |
山东省 | 聊城市 | 17802 |
山东省 | 枣庄市 | 1796 |
内蒙古自治区 | 鄂尔多斯市 | 651177 |
内蒙古自治区 | 包头市 | 289065 |
内蒙古自治区 | 兴安盟 | 258106 |
内蒙古自治区 | 巴彦淖尔市 | 141360 |
内蒙古自治区 | 通辽市 | 66463 |
内蒙古自治区 | 呼伦贝尔市 | 62450 |
内蒙古自治区 | 乌海市 | 53515 |
内蒙古自治区 | 赤峰市 | 26836 |
内蒙古自治区 | 呼和浩特市 | 16708 |
辽宁省 | 鞍山市 | 917327 |
辽宁省 | 本溪市 | 575838 |
辽宁省 | 葫芦岛市 | 392363 |
辽宁省 | 盘锦市 | 306124 |
辽宁省 | 沈阳市 | 202724 |
辽宁省 | 抚顺市 | 119776 |
辽宁省 | 大连市 | 115483 |
辽宁省 | 铁岭市 | 75596 |
辽宁省 | 锦州市 | 53737 |
辽宁省 | 朝阳市 | 44664 |
辽宁省 | 营口市 | 38969 |
辽宁省 | 辽阳市 | 20555 |
辽宁省 | 丹东市 | 18011 |
江西省 | 吉安市 | 587941 |
江西省 | 抚州市 | 207687 |
江西省 | 南昌市 | 141011 |
江西省 | 赣州市 | 126004 |
江西省 | 上饶市 | 100209 |
江西省 | 萍乡市 | 92271 |
江西省 | 九江市 | 89530 |
江西省 | 景德镇市 | 30243 |
江西省 | 宜春市 | 8674 |
江苏省 | 宿迁市 | 291918 |
江苏省 | 无锡市 | 274878 |
江苏省 | 镇江市 | 139625 |
江苏省 | 常州市 | 124904 |
江苏省 | 南京市 | 96092 |
江苏省 | 淮安市 | 50116 |
江苏省 | 南通市 | 45943 |
江苏省 | 扬州市 | 40711 |
江苏省 | 徐州市 | 31636 |
江苏省 | 连云港市 | 29047 |
江苏省 | 苏州市 | 21753 |
江苏省 | 盐城市 | 20877 |
江苏省 | 泰州市 | 17473 |
湖南省 | 张家界市 | 203990 |
湖南省 | 永州市 | 177242 |
湖南省 | 长沙市 | 163263 |
湖南省 | 衡阳市 | 143484 |
湖南省 | 怀化市 | 119420 |
湖南省 | 株洲市 | 89771 |
湖南省 | 常德市 | 78640 |
湖南省 | 益阳市 | 35275 |
湖南省 | 娄底市 | 25018 |
湖南省 | 湘潭市 | 19964 |
湖南省 | 岳阳市 | 16941 |
湖南省 | 郴州市 | 16597 |
湖南省 | 邵阳市 | 7408 |
湖北省 | 潜江市 | 839482 |
湖北省 | 黄石市 | 788623 |
湖北省 | 襄阳市 | 194910 |
湖北省 | 孝感市 | 128893 |
湖北省 | 荆门市 | 114273 |
湖北省 | 鄂州市 | 105010 |
湖北省 | 黄冈市 | 100447 |
湖北省 | 随州市 | 70228 |
湖北省 | 宜昌市 | 43783 |
湖北省 | 十堰市 | 29798 |
湖北省 | 武汉市 | 18516 |
湖北省 | 荆州市 | 13307 |
河南省 | 信阳市 | 303765 |
河南省 | 郑州市 | 190843 |
河南省 | 焦作市 | 151812 |
河南省 | 周口市 | 149732 |
河南省 | 济源市 | 119826 |
河南省 | 鹤壁市 | 104734 |
河南省 | 三门峡市 | 86982 |
河南省 | 开封市 | 74053 |
河南省 | 新乡市 | 52236 |
河南省 | 南阳市 | 30565 |
河南省 | 驻马店市 | 29491 |
河南省 | 濮阳市 | 26306 |
河南省 | 漯河市 | 23355 |
河南省 | 许昌市 | 20666 |
河南省 | 平顶山市 | 17923 |
河南省 | 洛阳市 | 11709 |
河南省 | 商丘市 | 6414 |
河北省 | 廊坊市 | 161929 |
河北省 | 沧州市 | 140578 |
河北省 | 邯郸市 | 127017 |
河北省 | 邢台市 | 119624 |
河北省 | 秦皇岛市 | 95955 |
河北省 | 保定市 | 69588 |
河北省 | 承德市 | 54630 |
河北省 | 石家庄市 | 38257 |
河北省 | 张家口市 | 27311 |
河北省 | 唐山市 | 24888 |
河北省 | 衡水市 | 11067 |
广东省 | 广州市 | 745366 |
广东省 | 佛山市 | 405419 |
广东省 | 肇庆市 | 321218 |
广东省 | 梅州市 | 148140 |
广东省 | 惠州市 | 137476 |
广东省 | 阳江市 | 95172 |
广东省 | 清远市 | 68248 |
广东省 | 潮州市 | 34674 |
广东省 | 揭阳市 | 26389 |
广东省 | 韶关市 | 19129 |
广东省 | 深圳市 | 16847 |
广东省 | 汕头市 | 11792 |
广东省 | 中山市 | 11343 |
广东省 | 珠海市 | 4324 |
广东省 | 东莞市 | 1866 |
甘肃省 | 金昌市 | 474105 |
甘肃省 | 陇南市 | 163465 |
甘肃省 | 天水市 | 119378 |
甘肃省 | 庆阳市 | 85120 |
甘肃省 | 平凉市 | 20565 |
甘肃省 | 兰州市 | 18208 |
甘肃省 | 张掖市 | 17878 |
甘肃省 | 酒泉市 | 14233 |
福建省 | 厦门市 | 495921 |
福建省 | 福州市 | 476299 |
福建省 | 莆田市 | 209084 |
福建省 | 南平市 | 141303 |
福建省 | 漳州市 | 138974 |
福建省 | 泉州市 | 74809 |
福建省 | 三明市 | 34839 |
福建省 | 宁德市 | 21116 |
北京 | 北京市 | 154682 |
安徽省 | 宿州市 | 657589 |
安徽省 | 安庆市 | 596127 |
安徽省 | 合肥市 | 179518 |
安徽省 | 淮北市 | 107184 |
安徽省 | 阜阳市 | 71129 |
安徽省 | 淮南市 | 69522 |
安徽省 | 亳州市 | 61254 |
安徽省 | 滁州市 | 30004 |
安徽省 | 宣城市 | 24571 |
安徽省 | 蚌埠市 | 16023 |
安徽省 | 马鞍山市 | 15212 |
这篇关于4. 优雅的apply的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-24Java中定时任务实现方式及源码剖析
- 2024-11-24Java中定时任务实现方式及源码剖析
- 2024-11-24鸿蒙原生开发手记:03-元服务开发全流程(开发元服务,只需要看这一篇文章)
- 2024-11-24细说敏捷:敏捷四会之每日站会
- 2024-11-23Springboot应用的多环境打包入门
- 2024-11-23Springboot应用的生产发布入门教程
- 2024-11-23Python编程入门指南
- 2024-11-23Java创业入门:从零开始的编程之旅
- 2024-11-23Java创业入门:新手必读的Java编程与创业指南
- 2024-11-23Java对接阿里云智能语音服务入门详解