【发布时间】:2021-05-19 13:37:02
【问题描述】:
背景
我有一个 pandas DataFrame,它用作键值对 c 和 v 的寄存器,对应于计划 p:
In [1]: a = pd.DataFrame({
...: 'p':[1, 1, 2],
...: 'c':['alpha', 'beta', 'alpha'],
...: 'v':['orange', 'football', 'apple']})
In [2]: a
Out[2]:
p c v
0 1 alpha orange
1 1 beta football
2 2 alpha apple
方法一
这个想法是,对于每一行,我都有另一个键值对,稍后将用作与另一个 DataFrame 的合并列。这样,通过在 v 列上堆叠和取消堆叠,我将获得所需形状的表格以进行连接/合并操作:
In [3]: a.set_index(['c', 'p']).stack().unstack(0).reset_index()
Out[3]:
c p level_1 alpha beta
0 1 v orange football
1 2 v apple NaN
方法二
现在,在另一种情况下,对于相同的p 计划和c 键,我可以有不同的v 值,这需要一个额外的步骤来避免ValueError 重复条目:
In [4]: b = pd.DataFrame({
...: 'p':[3, 3, 4, 4],
...: 'c':['alpha', 'alpha', 'beta', 'beta'],
...: 'v':['orange', 'apple', 'football', 'rugby']})
In [5]: b['nid'] = b.groupby('c')['c'].cumcount()
In [6]: b.set_index(['c', 'nid', 'p']).stack().unstack(0).reset_index().sort_values('p')
Out[6]:
c nid p level_2 alpha beta
0 0 3 v orange NaN
2 1 3 v apple NaN
1 0 4 v NaN football
3 1 4 v NaN rugby
新实现
然而,我正在努力在第二个示例中提出一种方法,在该方法中,对于相同的 p 计划,我可以为不同的c 值设置不同的v 值,并且得到一个“点”结果,其中每个键值对的所有组合都显示在最终的 DataFrame 中。
In [7]: pd.DataFrame({
...: 'p':[5, 5, 5, 5, 6, 6],
...: 'c':['alpha', 'alpha', 'beta', 'beta', 'gaga', 'gaga'],
...: 'v':['orange', 'apple', 'football', 'rugby', 'cake', 'pie']})
Out[7]:
p c v
0 5 alpha orange
1 5 alpha apple
2 5 beta football
3 5 beta rugby
4 6 gaga cake
5 6 gaga pie
使用方法 2 将沿着相同的 p 和 nid 列连接 c 键:
c nid p level_2 alpha beta gaga
0 0 5 v orange football NaN
2 1 5 v apple rugby NaN
1 0 6 v NaN NaN cake
3 1 6 v NaN NaN pie
但是,所需的输出应该类似于:
p alpha beta gaga
0 5 orange football NaN
1 5 orange rugby NaN
2 5 apple football NaN
3 5 apple rugby NaN
4 6 NaN NaN cake
5 6 NaN NaN pie
为了更清楚:
- 对于
p == 5,我为alpha注册了2个值,为beta注册了2个值,因此我需要2x2 = 4对; - 对于
p == 6,我只为gaga注册了2个值,所以在这种情况下它只会复制这两行; - 说,对于另一个
p == 7,我为alpha注册了2 个值,为beta和4 注册了3 个值gaga的值,输出 DataFrame 将具有 2x3x4 = 24 个三元组,以考虑所有组合。
关于如何实现这一点的任何想法?它不必在单个命令中,以防万一。
编辑
这可以通过使用itertools.product 而不是创建辅助nid 列来完成,但是在获取组合时,我最终失去了对c 的引用,所以我无法取消堆叠:
from itertools import product
import pandas as pd
x = pd.DataFrame({
'p':[5, 5, 5, 5, 6, 6],
'c':['alpha', 'alpha', 'beta', 'beta', 'gaga', 'gaga'],
'v':['orange', 'apple', 'football', 'rugby', 'cake', 'pie']})
xlist = x.groupby(['p', 'c'])['v'].apply(list)
xprod = xlist.groupby('p').apply(lambda g: list(product(*g)))
这些列表将为每个不同的p 提供正确的组合,包括具有单个c 的组合(在xprod.loc[6] 的情况下),但此时,对c 名称的引用丢失了:
p
5 [(orange, football), (orange, rugby), (apple, ...
6 [(cake,), (pie,)]
Name: v, dtype: object
使用itertools 实际上似乎更有效,但在这最后一步之后我被卡住了。
【问题讨论】:
-
您能否添加更多解释来证明预期输出的合理性。
-
@anky 当然:如前所述,这些 DF 是与另一个包含实际值的 DF 进行连接/合并操作的基础(我们称之为
val)。所以,在最后一种情况下,对于p == 5,我最终将与valon['alpha', 'beta']合并,对于p == 6,我将合并on @987654365 @。因此我需要输出中的“组合”。不过,使用数字表示值并不是最清楚的,我会更新这个问题。 -
已更新,归根结底是一个组合学问题,再加上 Pandas 的数据操作。
标签: python pandas pivot-table data-manipulation