使用 Pandas 将列转换为行

Convert columns into rows with Pandas

提问人:Wizuriel 提问时间:2/22/2015 最后编辑:buhtzWizuriel 更新时间:11/4/2022 访问量:288207

问:

因此,我的数据集按位置提供了一些 n 个日期的信息。问题是每个日期实际上是一个不同的列标题。例如,CSV 如下所示

location    name    Jan-2010    Feb-2010    March-2010
A           "test"  12          20          30
B           "foo"   18          20          25

我想要的是它看起来像

location    name    Date        Value
A           "test"  Jan-2010    12       
A           "test"  Feb-2010    20
A           "test"  March-2010  30
B           "foo"   Jan-2010    18       
B           "foo"   Feb-2010    20
B           "foo"   March-2010  25

我的问题是我不知道列中有多少个日期(尽管我知道它们总是在名称之后开始)

Python 熊猫

评论

0赞 pyCthon 2/22/2015
stackoverflow.com/questions/19842066/......

答:

410赞 DSM 2/22/2015 #1

更新
从 v0.20 开始,melt 是一阶函数,您现在可以使用

df.melt(id_vars=["location", "name"], 
        var_name="Date", 
        value_name="Value")

  location    name        Date  Value
0        A  "test"    Jan-2010     12
1        B   "foo"    Jan-2010     18
2        A  "test"    Feb-2010     20
3        B   "foo"    Feb-2010     20
4        A  "test"  March-2010     30
5        B   "foo"  March-2010     25

旧版本: <0.20

你可以使用 pd.melt 来获取大部分方法,然后排序:

>>> df
  location  name  Jan-2010  Feb-2010  March-2010
0        A  test        12        20          30
1        B   foo        18        20          25
>>> df2 = pd.melt(df, id_vars=["location", "name"], 
                  var_name="Date", value_name="Value")
>>> df2
  location  name        Date  Value
0        A  test    Jan-2010     12
1        B   foo    Jan-2010     18
2        A  test    Feb-2010     20
3        B   foo    Feb-2010     20
4        A  test  March-2010     30
5        B   foo  March-2010     25
>>> df2 = df2.sort(["location", "name"])
>>> df2
  location  name        Date  Value
0        A  test    Jan-2010     12
2        A  test    Feb-2010     20
4        A  test  March-2010     30
1        B   foo    Jan-2010     18
3        B   foo    Feb-2010     20
5        B   foo  March-2010     25

(可能想要加入一个 ,只是为了保持输出干净。.reset_index(drop=True)

注意已被弃用,取而代之的是 pd。DataFrame.sort_valuespd.DataFrame.sort

评论

0赞 3kstc 3/9/2018
@DSM这个函数的倒数是多少。即如何将 [back] 转换为df2df
3赞 Teepeemm 3/10/2018
@3kstc 试试这里这里。您想要研究枢轴。可能。pandas.pivot_table(df2,values='Value',index=['location','name'],columns='Date').reset_index()
1赞 Adrian 1/24/2019
@DSM有什么办法可以倒退呢?这意味着我有很多同名的行,我希望所有日期都在不同的列上
1赞 Orhan Solak 3/12/2021
@Adrian您可以在 DF 操作中解熔/反熔(又名枢轴)。有关更多详细信息,请查看此 stackoverflow.com/questions/28337117/...
8赞 Prometheus 6/25/2018 #2

我想我找到了一个更简单的解决方案

temp1 = pd.melt(df1, id_vars=["location"], var_name='Date', value_name='Value')
temp2 = pd.melt(df1, id_vars=["name"], var_name='Date', value_name='Value')

用 的 列 Concat 整体temp1temp2name

temp1['new_column'] = temp2['name']

你现在拥有了你所要求的东西。

10赞 jpp 11/14/2018 #3

pd.wide_to_long

您可以将前缀添加到年份列,然后直接馈送到 。我不会假装这是有效的,但在某些情况下它可能比 pd.melt 更方便,例如,当您的列已经有适当的前缀时。pd.wide_to_long

df.columns = np.hstack((df.columns[:2], df.columns[2:].map(lambda x: f'Value{x}')))

res = pd.wide_to_long(df, stubnames=['Value'], i='name', j='Date').reset_index()\
        .sort_values(['location', 'name'])

print(res)

   name        Date location  Value
0  test    Jan-2010        A     12
2  test    Feb-2010        A     20
4  test  March-2010        A     30
1   foo    Jan-2010        B     18
3   foo    Feb-2010        B     20
5   foo  March-2010        B     25

评论

0赞 Rabinzel 4/12/2022
我知道这已经有几年的历史了,但是在学习如何使用的差异时,我遇到了这个答案,自己测试了一下,它只是不想让我得到相同的结果(我只是得到了一个空的 df)。最后,我发现我需要添加才能得到相同的结果。当时是不同,还是从未奏效,但没有人注意到或关心?还是我错过了什么?并不是我想在这里纠正,我只是想确保我了解这些命令是怎么回事。pd.stack()pd.melt()pd.wide_to_long()ressuffix=r".+"
0赞 jpp 4/13/2022
@Rabinzel,我不确定功能有什么变化。但我能说的是,我测试了代码,并且在我写这个答案时它有效。如果这是真的,那么知道为什么需要后缀参数会很有趣。
0赞 Rabinzel 4/13/2022
感谢您的回复。只是想验证问题是否在我这边,或者我误解了什么。在谷歌上搜索了一下后,我读了好几次,需要数字后缀,否则它会失败,但在文档中,它所说的只是默认设置。wide_to_longsuffix="\d+"
30赞 jezrael 2/20/2019 #4

set_indexstack 一起使用 ,然后将 add reset_index 与 :MultiIndex SeriesDataFramerename

df1 = (df.set_index(["location", "name"])
         .stack()
         .reset_index(name='Value')
         .rename(columns={'level_2':'Date'}))
print (df1)
  location  name        Date  Value
0        A  test    Jan-2010     12
1        A  test    Feb-2010     20
2        A  test  March-2010     30
3        B   foo    Jan-2010     18
4        B   foo    Feb-2010     20
5        B   foo  March-2010     25
6赞 jjurm 3/24/2021 #5

添加一个指向可以复制的笔记本的链接,使用 pandas.melt 演示@DMS的答案:

df.melt(id_vars=["location", "name"], 
    var_name="date", 
    value_name="value")

https://deepnote.com/@DataScience/Unpivot-a-DataFrame-from-wide-to-long-format-lN7WlqOdSlqroI_7DGAkoA

4赞 Muhammad Talha 8/10/2022 #6

如果你想用列交换你的行,用行交换列,然后尝试pandas的转置方法:

df.T

查看参考链接:https://note.nkmk.me/en/python-pandas-t-transpose/