这是一个关于 pandas 从基础到进阶的练习题系列,来源于 github 上的 guipsamora/pandas_exercises 。这个项目从基础到进阶,可以检验你有多么了解 pandas。
我会挑选一些题目,并且提供比原题库更多的解决方法以及更详尽的解析。
计划每天更新一期,希望各位小伙伴先自行思考,再查看答案。如果对你有帮助,记得转发推荐给你的好友!
上期文章:pandas每天一题-题目1、2、3
后台回复"数据",可以下载本题数据集
如下数据:
数据描述:
- 此数据是订单明细表。一个订单会包含很多明细项,表中每个样本(每一行)表示一个明细项
- order_id 列存在重复
- quantity 是明细项数量
请找出数量最多的明细项(并列最多,全部列出),要求列出其所有信息(上表中的列)。
格式如下:
接下来就是答案了!
你可能一开始想到的答案是这样子:
代码语言:javascript复制df.nlargest(1,'quantity',keep='all')
这是不对的。因为 item_name 相当于是一个产品名字,它可能同时存在于多个订单中。
上面的结果只能是"找出数据中,数量最多的行"
因此,我们应该这样做:
代码语言:javascript复制(
df.groupby(['item_name'])
.agg({'quantity': sum,})
.nlargest(1, 'quantity', keep='all')
)
- 行2:按名字分组
- 行3:汇总数量
- 行4:取最多数量的。这里要说明一下,因为分组汇总后的结果仍然是一个 DataFrame(表格),因此可以继续使用他的各种方法
- 为了做到需求中"并列最多,全部列出",这里设置的参数 keep
看看 nlargest 的参数描述:
关键知识点:
- 分组统计。df.groupby agg ,常用操作,必须掌握
- 取前n最大。df.nlargest
解法2
如果最多只有一笔,我们也可以使用:
代码语言:javascript复制(
df.groupby(['item_name'])
.agg({'quantity': sum,})
.sort_values( 'quantity', ascending=False)
.head(1)
)
- 行4:按数量倒序(ascending=False)排序
- 行5:取第一行
那么,这种方式下,可以做到"并列最多,全部列出"的需求吗?
我们尝试一下。
首先,由于数据到了50才出现重复:
于是,我们把结果从50开始截取,当作是汇总后的结果:
代码语言:javascript复制res = (
df.groupby(['item_name'])
.agg({'quantity': sum,})
.sort_values( 'quantity', ascending=False)
.query('quantity<=50')
)
res
其实道理很简单,求出最大值,把数量为最大值的行保留即可:
代码语言:javascript复制res = (
df.groupby(['item_name'])
.agg({'quantity': sum,})
.sort_values( 'quantity', ascending=False)
.query('quantity<=50')
)
maxv = res.iloc[0,0]
res.query('quantity==@maxv')
- 行8:取出汇总数据的第一行第一列。因为是倒序排序,这个值就是最大值
- 行9:把等于最大值的行保留即可
这种方式比较繁琐,如果只是求n大记录,建议使用 nlargest
推荐阅读:
- python 方法太多了,怎么记住?在 JupyterNotebook中这几招很有用