【问题标题】:Python 3: Transpose columns of Pandas Data Frame / "melt" data framePython 3:转置 Pandas 数据框/“melt”数据框的列
【发布时间】:2021-05-22 03:09:05
【问题描述】:

我有一个这样的 Pandas 数据框:

    uid   category   count
0    1     comedy     5
1    1     drama      7
2    2     drama      4
3    3     other      10    
4    3     comedy     6

除了有几十个类别、几百万行和几十个其他列。

我想把它变成这样的:

    id   cat_comedy   cat_drama    cat_other
0    1    5            7            0
1    2    0            4            0
2    3    6            0            10

我不知道如何做到这一点,正在寻找提示/提示/完整解决方案。我真的不关心行索引。

谢谢。

【问题讨论】:

  • 不,不是错。
  • @CarlCervone 建议您的数据集可能包含具有相同 idcategory 的行,但计数不同 - 这是正确的,还是 id 和 @987654326 的任意组合@在您的数据中是唯一的吗?

标签: python


【解决方案1】:

我认为这就是您所追求的(该操作称为“枢轴”):

from pandas import DataFrame

df = DataFrame([
    {'id': 1, 'category': 'comedy', 'count': 5},
    {'id': 1, 'category': 'drama', 'count': 7},
    {'id': 2, 'category': 'drama', 'count': 4},
    {'id': 3, 'category': 'other', 'count': 10},
    {'id': 3, 'category': 'comedy', 'count': 6}
]).set_index('id')

result = df.pivot(columns=['category'])

print(result)

结果:

          count
category comedy drama other
id
1           5.0   7.0   NaN
2           NaN   4.0   NaN
3           6.0   NaN  10.0

针对您的评论,如果您不希望 id 作为 df 的索引,您可以告诉操作将其用作枢轴的索引。你需要pivot_table 而不是pivot 来实现这一点,因为它可以处理一个旋转索引/列对的重复值。

NaN 替换为零也是一种选择:


df = DataFrame([
    {'uid': 1, 'category': 'comedy', 'count': 5},
    {'uid': 1, 'category': 'drama', 'count': 7},
    {'uid': 2, 'category': 'drama', 'count': 4},
    {'uid': 3, 'category': 'other', 'count': 10},
    {'uid': 3, 'category': 'comedy', 'count': 6}
])

result = df.pivot_table(columns=['category'], index='uid', fill_value=0)

print(result)

但是,请注意,结果表仍将uid 作为其索引。如果这不是您想要的,您可以将结果列恢复为正常列:

result = df.pivot_table(columns=['category'], index='uid', fill_value=0).reset_index()

最终结果:

         uid  count
category     comedy drama other
0          1      5     7     0
1          2      0     4     0
2          3      6     0    10

【讨论】:

  • 非常接近!除了 id 字段(我在原始问题中将其重命名为 uid 以防更清楚),不应该是索引(我不认为)。并且 NaN 应该是零
  • 要将NaNs 替换为0s,请致电df.fillna(0, inplace=True)
【解决方案2】:

使用pivot_table的完整解决方案:

import pandas as pd

df = pd.DataFrame([
    {'uid': 1, 'category': 'comedy', 'count': 5},
    {'uid': 1, 'category': 'drama', 'count': 7},
    {'uid': 2, 'category': 'drama', 'count': 4},
    {'uid': 3, 'category': 'other', 'count': 10},
    {'uid': 3, 'category': 'comedy', 'count': 6}
])

df.pivot_table(
    columns='category', 
    index='uid', 
    aggfunc=sum, 
    fill_value=0
)

【讨论】:

  • aggfunc 在这种情况下似乎是多余的?
  • 默认的aggfuncmean,因此即使它适用于此处显示的虚拟数据,它也可能不适用于其他真实数据集。例如,如果您像这样添加另一行:{'uid': 3, 'category': 'comedy', 'count': 5}
【解决方案3】:

@Grismar 的原始答案(因为他首先得到它而被赞成)非常接近,但不太有效。不要在枢轴调用之前重置您的索引,然后执行以下操作:

df2 = df.pivot_table(columns='category', index='uid', aggfunc=sum)
df2 = df2.fillna(0).reset_index()

df2 现在是您想要的数据框。 fillna 函数将所有 NaNs 替换为 0s

【讨论】:

  • 请注意,df2 仍将有 uid 作为其索引 - 需要 .reset_index() 才能将其恢复为普通列。我已经更新了我的答案以反映这一点。
  • 好消息@grismar。也更新了。不错的标签团队。
猜你喜欢
  • 1970-01-01
  • 2020-05-15
  • 1970-01-01
  • 2022-12-04
  • 1970-01-01
  • 2020-06-17
  • 1970-01-01
  • 2014-08-19
  • 2022-06-16
相关资源
最近更新 更多