python - 将带有小计的 pandas groupby 结果转换为相对值
问题描述
我遇到了一个很好的解决方案,可以将小计插入 pandas groupby 数据框。但是,现在我想修改结果以显示相对于小计的相对值,而不是绝对值。
这是显示 groupby 的代码:
import pandas as pd
import numpy as np
df = pd.DataFrame(
{
"Category": np.random.choice(["Group A", "Group B"], 50),
"Product": np.random.choice(["Product 1", "Product 2"], 50),
"Units_Sold": np.random.randint(1, 100, size=(50)),
"Date": np.random.choice(
pd.date_range("1/1/2011", "03/31/2011", freq="D"), 50, replace=False
),
}
)
iList = ["Category", "Product"]
pvt = pd.concat(
[df.assign(**{x: "" for x in iList[i:]}).groupby(iList).sum() for i in range(1, 3)]
).sort_index()
print(pvt)
这导致
Units_Sold
Category Product
Group A 1170
Product 1 434
Product 2 736
Group B 980
Product 1 437
Product 2 543
我已经尝试过一些类似的东西
pvt.transform(lambda x: (round(x / x['Group A', ''],2)*100).astype(int).astype(str)+"%")
但显然这只计算相对于第一行的值。
我正在寻找的是
Units_Sold
Category Product
Group A 100%
Product 1 37%
Product 2 63%
Group B 100%
Product 1 45%
Product 2 55%
非常感谢!
解决方案
由具有 lambda 函数GroupBy.apply
的第一级使用:MultiIndex
f = lambda x: (x / x.iloc[0]).mul(100).round(2).astype(int).astype(str)+"%"
df = pvt.groupby(level=0).apply(f)
print (df)
Units_Sold
Category Product
Group A 100%
Product 1 49%
Product 2 50%
Group B 100%
Product 1 52%
Product 2 47%
或GroupBy.transform
使用GroupBy.first
:
df = (pvt.div(pvt.groupby(level=0).transform('first'))
.mul(100)
.round(2)
.astype(int)
.astype(str)+"%")
print (df)
Units_Sold
Category Product
Group A 100%
Product 1 43%
Product 2 56%
Group B 100%
Product 1 58%
Product 2 41%
推荐阅读
- javascript - 无法在 window.onhashchange 处读取未定义的属性“parentNode”
- forms - 提交表单后,子表单值在接收端显示为 null
- html - 无法对齐 div 内容
- python - 如何立即退出一组循环并返回第一个循环?
- java - 我是否需要一个带有经常从站点消耗休息 api 的 java 应用程序的数据库?
- applescript - 使用 AppleScript 中的特定 x、y 坐标裁剪图像
- html - 当有水平滚动时,为什么不将块元素扩展到其子项的显式宽度
- windows - TLS 1.1 不会在 Windows Server 2008 R2 上禁用
- r - 收集 Shiny R 中的所有输入标签
- php - 致命错误:未捕获的错误:不能使用 PDOStatement 类型的对象作为数组