【问题标题】:Python dataframe: pivot on same columnPython数据框:以同一列为中心
【发布时间】:2018-03-19 22:37:57
【问题描述】:

我有两列“ID”和“division”,如下所示。

df = pd.DataFrame(np.array([['111', 'AAA'],['222','AAA'],['333','BBB'],['444','CCC'],['444','AAA'],['222','BBB'],['111','BBB']]),columns=['ID','division'])

    ID  division
0   111 AAA
1   222 AAA
2   333 BBB
3   444 CCC
4   444 AAA
5   222 BBB
6   111 BBB

预期的输出如下所示,我需要在同一列上进行旋转,但计数取决于“除法”。这应该在热图中显示。

    df = pd.DataFrame(np.array([['0','2','1','1'],['2','0','1','1'],['1','1','0','0'],['1','1','0','0']]),columns=['111','222','333','444'],index=['111','222','333','444'])

    111 222 333 444
111 0   2   1   1
222 2   0   1   1
333 1   1   0   0
444 1   1   0   0

所以,从技术上讲,我在划分 ID 之间进行了重叠。

示例: 突出显示的红色框,其中 111 和 222 ID 之间的重叠为 2(AAA 和 BBB)。其中 111 和 444 之间的重叠为 1(黑色框中突出显示 AAA)。

我可以通过 2 个步骤在 excel 中完成此操作。不确定以下一个是否有帮助。 第一步:=SUM(COUNTIFS($B$2:$B$8,$B2,$A$2:$A$8,$G2),COUNTIFS($B$2:$B$8,$B2,$A$2:$A$8,H$1))-1 第二步:=IF($G12=H$1,0,SUMIFS(H$2:H$8,$G$2:$G$8,$G12))

但是有什么方法可以在 Python 中使用数据帧来实现。 感谢您的帮助

案例 2

if df = pd.DataFrame(np.array([['111', 'AAA','4'],['222','AAA','5'],['333','BBB','6'],
                            ['444','CCC','3'],['444','AAA','2'], ['222','BBB','2'],
                            ['111','BBB','7']]),columns=['ID','division','count'])

   ID   division count
0   111  AAA      4
1   222  AAA      5
2   333  BBB      6
3   444  CCC      3
4   444  AAA      2
5   222  BBB      2
6   111  BBB      7

预期的输出是

df_result = pd.DataFrame(np.array([['0','18','13','6'],['18','0','8','7'],['13','8','0','0'],['6','7','0','0']]),columns=['111','222','333','444'],index=['111','222','333','444'])

   111 222  333 444
111 0   18  13  6
222 18  0   8   7
333 13  8   0   0
444 6   7   0   0

计算:这里 111 和 222 之间的 AAA 和 BBB 部分有重叠,因此总和为 4+5+2+7=18

【问题讨论】:

  • 欢迎来到 SO。请提供 minimal reproducible example。这意味着没有图片,请。您可以使用 df.head().to_dict() 将数据框数据粘贴到您的问题中。祝你好运!
  • 谢谢,更新了代码,但为了便于解释,我保留了一张图片。让我知道这是否有帮助。

标签: python python-3.x pandas dataframe


【解决方案1】:

另一种方法是使用 mergepd.crosstab 的自联接:

df_out = df.merge(df, on='division')

results = pd.crosstab(df_out.ID_x, df_out.ID_y) 
np.fill_diagonal(results.values, 0)

输出:

ID_y  111  222  333  444
ID_x                    
111   0.0  2.0  1.0  1.0
222   2.0  0.0  1.0  1.0
333   1.0  1.0  0.0  0.0
444   1.0  1.0  0.0  0.0

案例 2

df = pd.DataFrame(np.array([['111', 'AAA','4'],['222','AAA','5'],['333','BBB','6'],
                            ['444','CCC','3'],['444','AAA','2'], ['222','BBB','2'],
                            ['111','BBB','7']]),columns=['ID','division','count'])

df['count'] = df['count'].astype(int)
df_out = df.merge(df, on='division')

df_out = df_out.assign(count = df_out.count_x + df_out.count_y)

results = pd.crosstab(df_out.ID_x, df_out.ID_y, df_out['count'], aggfunc='sum').fillna(0) 
np.fill_diagonal(results.values, 0)

输出:

ID_y   111   222   333  444
ID_x                       
111    0.0  18.0  13.0  6.0
222   18.0   0.0   8.0  7.0
333   13.0   8.0   0.0  0.0
444    6.0   7.0   0.0  0.0

【讨论】:

  • 感谢您的帮助
  • @Harish 如果可以的话,这就是你要找的东西吗upvote and accept
  • @jezrael 谢谢。我认为这应该比我在上一次编辑中所做的更容易。
  • 非常感谢,您的解决方案有帮助。只是想知道是否有任何理由使用“交叉表”而不是“数据透视表”。代码table = pivot_table(df_out, values='count', index=['ID_x'], columns=['ID_y'], aggfunc=np.sum).fillna(0)
  • 感谢您的帮助
猜你喜欢
  • 2018-11-12
  • 2018-08-17
  • 2017-03-09
  • 1970-01-01
  • 1970-01-01
  • 2021-01-27
  • 1970-01-01
  • 2020-01-24
相关资源
最近更新 更多