使用Pandas将列转换为行

269

因此,我的数据集包含有关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

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


https://dev59.com/gmIj5IYBdhLWcg3w04Xd - pyCthon
6个回答

410

更新
从版本0.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已被弃用,建议使用pd.DataFrame.sort_values


@DSM,这个函数的反函数是什么?即如何将“df2”[恢复]为“df”? - 3kstc
1
@DSM有没有办法倒退?我的意思是,我有很多行都有相同的名称,我希望所有的日期都在不同的列中。 - Adrian
1
@Adrian 你可以在数据框操作中使用unmelt / reverse melt(即透视)功能。有关详细信息,请查看此网址 https://dev59.com/sF4c5IYBdhLWcg3wFW2N - Orhan Solak

30

使用set_indexstack处理多级索引的序列,对于DataFrame,使用reset_indexrename进行重置:

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

10

pd.wide_to_long

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

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

我知道这已经过去几年了,但在学习如何使用pd.stack() pd.melt()pd.wide_to_long()的区别时,我遇到了这个答案,自己测试了一下,但它并没有给我相同的结果(对于res我只得到了一个空的df)。最后我发现我需要添加suffix=r".+"才能得到相同的结果。那时候是不同的吗?还是从来没有工作过,但没有人注意或关心?还是我错过了什么?我不是想在这里纠正,我只是想确保我理解这些命令的运行方式。 - Rabinzel
@Rabinzel,我不确定功能上发生了什么变化。但是我可以说的是,在我写这个答案的时候,我测试了代码并且它是可行的。如果确实需要后缀参数,了解其原因会很有趣。 - jpp
谢谢回复。我只是想确认问题是在我的一方还是我误解了什么。经过一番搜索,我多次读到 wide_to_long 需要数字后缀,否则它将失败,但在文档中只是说 suffix="\d+" 是默认值。 - Rabinzel

8
我想我找到了一个更简单的解决方案。
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')

temp1temp2的列name连接在一起。

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

现在您拥有了您所要求的内容。


6

4
如果你想将行和列互换,可以尝试使用pandas的转置方法:
df.T

请参考以下链接: https://note.nkmk.me/zh-cn/python-pandas-t-transpose/

该链接介绍了如何使用Python中的Pandas库进行数据透视操作。通过转置函数,可以将行变为列,列变为行,从而更好地展示和分析数据。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接