python - 不清楚为什么带有单组的 groupby 会产生行 DataFrame
问题描述
这是对 a 的两个groupby
操作pandas.DataFrame
:
import pandas
d = pandas.DataFrame({"a": [1, 2, 3, 4, 5, 6],
"b": [1, 2, 4, 3, -1, 5]})
grp1 = pandas.Series([1, 1, 1, 1, 1, 1])
ans1 = d.groupby(grp1).apply(lambda x: x.a * x.b.iloc[0])
grp2 = pandas.Series([1, 1, 1, 2, 2, 2])
ans2 = d.groupby(grp2).apply(lambda x: x.a * x.b.iloc[0])
print(ans1.reset_index(drop=True))
# a 0 1 2 3 4 5
# 0 1 2 3 4 5 6
print(ans2.reset_index(drop=True))
# 0 1
# 1 2
# 2 3
# 3 12
# 4 15
# 5 18
# Name: a, dtype: int64
我想要 . 格式的输出ans2
。如果分组 Series 有多个组(如 中grp2
),则输出格式没有问题。但是,当分组 Series 只有一个组时(如 中grp1
),输出是DataFrame
单行的 a。为什么是这样?
ans2
无论分组系列中的组数如何,如何确保输出始终如一?有没有比这更快/更好的方法
- 检查输出是否为 DataFrame 并强制转换为 Series
- 检查分组系列是否只有一个组并避免
groupby
这种情况
解决方案
我认为最简单的方法是避免.apply()
重新组合时确实会做奇怪的事情。这可能是因为这个函数的语义太模糊了。您可以返回任何内容,pandas 会尽力猜测您的意思
如果您希望与适用于整个子数据框的函数的结果一致,您最好自己运行该函数:
>>> pd.concat({n: (lambda x: x.a * x.b.iloc[0])(g) for n, g in d.groupby(grp1)})
1 0 1
1 2
2 3
3 4
4 5
5 6
Name: a, dtype: int64
>>> pd.concat({n: (lambda x: x.a * x.b.iloc[0])(g) for n, g in d.groupby(grp2)})
1 0 1
1 2
2 3
2 3 12
4 15
5 18
Name: a, dtype: int64
现在我建议改为使用具有明确定义的返回形状的函数。这里.transform()
可能有用:
>>> d.groupby(grp1)['b'].transform('first')
0 1
1 1
2 1
3 1
4 1
5 1
Name: b, dtype: int64
>>> d.groupby(grp2)['b'].transform('first')
0 1
1 1
2 1
3 3
4 3
5 3
Name: b, dtype: int64
这是一个如何用于相同计算的示例:
>>> ans1 = d.copy()
>>> ans1['a'] *= d.groupby(grp1)['b'].transform('first')
>>> ans1
a b
0 1 1
1 2 2
2 3 4
3 4 3
4 5 -1
5 6 5
>>> ans2 = d.copy()
>>> ans2['a'] *= d.groupby(grp2)['b'].transform('first')
>>> ans2
a b
0 1 1
1 2 2
2 3 4
3 12 3
4 15 -1
5 18 5
推荐阅读
- node.js - 找不到从封闭的 facebook 组访问提要的正确权限
- angular5 - 如何在angular5中的查询字符串中发送特殊字符
- reactjs - 与 heroku 服务器混合的内容
- javascript - Kafka节点跳过错误偏移
- c# - 有没有办法让 C# 解决方案在 TFS 构建期间使用本地和 nuget 包时使用项目引用?
- php - Admin 中的 WooCommerce 变体排序
- for-loop - 如何使用 Jekyll last_modified_at 按日期列出页面
- javascript - Select2 JS lib 不适用于 Rails 应用程序
- python - 如何在 python 曲面图上更改颜色并添加网格线?
- node.js - 知道框架依赖于哪个 node.js 版本