Pandas: 将值从一列移动到合适的列

2 投票
2 回答
36 浏览
提问于 2025-04-14 16:14

我在网上查找信息时遇到了一些困难。我有一个简单的数据表,长得像这样:

样本 主题 地点 物品
1-1 珍妮特
1-1 波士顿
1-1 帽子
1-2 克里斯
1-2 奥斯丁
1-2 围巾

我想把主题这一列的值移动到它们应该在的位置,这样我最终得到的结果应该像这样:

样本 主题 地点 物品
1-1 珍妮特 珍妮特 波士顿 帽子
1-2 克里斯 克里斯 奥斯丁 围巾

我看过一些数据处理的方法,比如透视表和转置,但这些似乎不太合适。

如果有任何建议,我会非常感激! :)

2 个回答

2

试试这个:

out = (
    df.groupby("Sample")["Subject"]
    .apply(lambda x: pd.Series([*x], index=["Person", "Place", "Thing"]))
    .unstack(level=1)
).reset_index()

# If `Subject` column is required, then:
# out["Subject"] = out["Person"]
print(out)

输出结果是:

  Sample Person   Place  Thing
0    1-1  Janet  Boston    Hat
1    1-2  Chris  Austin  Scarf
1

如果这些组是排好序的,并且模式总是一样的(没有缺失值),那么可以用numpy来重新整理数据:

cols = ['Person', 'Place', 'Thing']

out = df.loc[::len(cols), ['Sample']].reset_index(drop=True)

out[cols] = df['Subject'].to_numpy().reshape(-1, len(cols))

如果想要更通用的方法,只要假设每组中的类别顺序总是相同,可以用groupby.cumcount来找出每组的位置,然后用map来映射名称,最后再用pivot

order = ['Person', 'Place', 'Thing']

out = (df.assign(col=df.groupby('Sample').cumcount()
                       .map(dict(enumerate(order))))
         .pivot(index='Sample', columns='col', values='Subject')
         .reset_index().rename_axis(columns=None)
      )

还有一种用rename的方法:

order = ['Person', 'Place', 'Thing']

out = (df.assign(col=df.groupby('Sample').cumcount())
         .pivot(index='Sample', columns='col', values='Subject')
         .rename(columns=dict(enumerate(order)))
         .reset_index().rename_axis(columns=None)
      )

输出结果:

  Sample Person   Place  Thing
0    1-1  Janet  Boston    Hat
1    1-2  Chris  Austin  Scarf

最后,如果你真的想要“Subject”这一列,可以用insert把它加进去:

out.insert(1, 'Subject', out['Person'])

print(out)

  Sample Subject Person   Place  Thing
0    1-1   Janet  Janet  Boston    Hat
1    1-2   Chris  Chris  Austin  Scarf

时间比较

如果你能使用numpy的方法,它对输入的要求更严格,但速度会快很多:

这里输入图片描述

撰写回答