【问题标题】:Reshaping to all value combinations when unstacking a DataFrame取消堆叠 DataFrame 时重塑为所有值组合
【发布时间】:2021-05-19 13:37:02
【问题描述】:

背景

我有一个 pandas DataFrame,它用作键值对 cv 的寄存器,对应于计划 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 将沿着相同的 pnid 列连接 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 个值,为beta4 注册了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,我最终将与val on ['alpha', 'beta'] 合并,对于p == 6,我将合并on @987654365 @。因此我需要输出中的“组合”。不过,使用数字表示值并不是最清楚的,我会更新这个问题。
  • 已更新,归根结底是一个组合学问题,再加上 Pandas 的数据操作。

标签: python pandas pivot-table data-manipulation


【解决方案1】:

你可以试试groupbyexplode

df['nid'] = df.groupby('c')['c'].cumcount()
df.set_index(['c', 'nid', 'p']).stack().unstack(0).sort_values('p').groupby(level='p').agg(lambda x: list(set(x)))
for col in k.columns:
    k = k.explode(col)

输出:

c   alpha      beta  gaga
p                        
5  orange     rugby   NaN
5  orange  football   NaN
5   apple     rugby   NaN
5   apple  football   NaN
6     NaN       NaN   pie
6     NaN       NaN  cake

NOTE:这里,我使用set 进行聚合,如果需要,您可以使用list

【讨论】:

  • 所以没有通知我这个答案,抱歉回复晚了。不过,我在这里有点困惑。最后一条语句之后的k 将成形为 (2, 3),c 正确显示在列上,但行仍将显示 set 对象,而不是分解 DataFrame。我正在尝试使用itertools.product 到达那里,但不幸的是,我失去了对c 的引用。
  • 我猜将每一列 1 1 分解会产生相同的答案。无论如何,我已经更新了我的答案,使其不那么复杂。 @manoelpqueiroz
  • 我不知道这是否可能是熊猫版本控制问题,但即使更新了答案,set 对象也无法爆炸,使用list 将生成 (256, 3) DataFrame O_O
  • 如果您能够分解列表,那么您只需将集合转换回列表并分解即可。我已经更新了答案
猜你喜欢
  • 2018-04-12
  • 2019-02-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多