如何从pandas DataFrame中“展开”特定列?

37

我有一个pandas DataFrame,例如:

df = pd.DataFrame({'farm' : ['A','B','A','B'], 
                   'fruit':['apple','apple','pear','pear'], 
                   '2014':[10,12,6,8], 
                   '2015':[11,13,7,9]})

即:

   2014  2015 farm  fruit
0    10    11    A  apple
1    12    13    B  apple
2     6     7    A   pear
3     8     9    B   pear

如何将它转换为以下格式?
  farm  fruit  value  year
0    A  apple     10  2014
1    B  apple     12  2014
2    A   pear      6  2014
3    B   pear      8  2014
4    A  apple     11  2015
5    B  apple     13  2015
6    A   pear      7  2015
7    B   pear      9  2015

我尝试过 stackunstack 但是无法使其工作。


1
Melt是这个函数的绝妙名称。 - kjmerf
2个回答

47

使用pd.melt()可以实现:

# value_name is 'value' by default, but setting it here to make it clear
pd.melt(x, id_vars=['farm', 'fruit'], var_name='year', value_name='value')

结果:

  farm  fruit  year  value
0    A  apple  2014     10
1    B  apple  2014     12
2    A   pear  2014      6
3    B   pear  2014      8
4    A  apple  2015     11
5    B  apple  2015     13
6    A   pear  2015      7
7    B   pear  2015      9

[8 rows x 4 columns]

我不确定"melt"作为这种操作的名称有多常见,但在R的reshape2包中被称为这个名字,这可能启发了这里的名称。


非常简单而棒的名字 - melt!非常感谢! - kjmerf
"melt" 做得非常好。 - nambastha
非常感谢。这正是我想要的。 - Anurag Sharma

2

可以使用stack()来完成;只需要先调用set_index()来为每个年份-值对重复farmfruit

long_df = df.set_index(['farm', 'fruit']).rename_axis(columns='year').stack().reset_index(name='value')

result1

melt也是一个DataFrame方法,因此可以像这样调用:

long_df = df.melt(id_vars=['farm', 'fruit'], var_name='year', value_name='value')

一个有趣的函数是 pd.wide_to_long,它也可以用于“熔解”框架。但是,它需要一个 stubname,因此不适用于 OP 中的情况,但对其他情况有效。例如,在下面的情况中(请注意列标签中的年份中有 value_),该函数可以使用。
long_df = pd.wide_to_long(df, 'value', i=['farm', 'fruit'], j='year', sep='_').reset_index()

result2


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