2016-11-02 70 views
1

具有数据帧,如:联合列在数据帧

import pandas 

df = pandas.DataFrame({'a': [1, 2, 3], 'b': [9, 8, 7], 'c': [4, 5, 6]}) 
df 

enter image description here

我想有一个数据帧:

  • 甲因子/类别列['a', 'b']。这个专栏的名字,我不在乎。
  • 具有ab列的旧值的列,具体取决于['a', 'b']因子。这个专栏的名字,我不在乎。
  • 保留c列值和名称(实际数据框有几列我想保留)。
  • 我不关心结果数据框中列的顺序,也不关心它们中的某些(或任何)列被设置为索引。

这是什么,我想获得一个例子:

df['name_a'] = 'a' 
df['name_b'] = 'b' 

c0 = pandas.concat([df['name_a'], df['name_b']]) 
c1 = pandas.concat([df['a'], df['b']]) 
c2 = pandas.concat([df['c'], df['c']]) 

newdf = pandas.concat([c0, c1, c2], axis=1) 
newdf 

enter image description here

有没有更好的方式来达到同样的效果?我觉得这样很丑陋。也许我错过了一个pandas函数,使得代码更清晰,更易于理解?

回答

1

我想你需要melt

print (pd.melt(df,id_vars='c', var_name='0', value_name='1')) 
    c 0 1 
0 4 a 1 
1 5 a 2 
2 6 a 3 
3 4 b 9 
4 5 b 8 
5 6 b 7 

stack另一种解决方案与sort_values

df1 = df.set_index('c').stack().reset_index().sort_values('level_1') 
df1.columns = ['c', '0','1'] 
print (df1) 
    c 0 1 
0 4 a 1 
2 5 a 2 
4 6 a 3 
1 4 b 9 
3 5 b 8 
5 6 b 7 

更通用的解决方案 - 使用list comprehension的过滤器,不ab可变cols所有列:

cols = [col for col in df.columns if col not in ['a','b']] 
print (cols) 
['c'] 

print (pd.melt(df,id_vars=cols, var_name='0', value_name='1')) 
    c 0 1 
0 4 a 1 
1 5 a 2 
2 6 a 3 
3 4 b 9 
4 5 b 8 
5 6 b 7 

样品添加了另一列g

df = pd.DataFrame({'a': [1, 2, 3], 
        'b': [9, 8, 7], 
        'c': [4, 5, 6], 
        'g': [0, 1, 7]}) 

print (df) 
    a b c g 
0 1 9 4 0 
1 2 8 5 1 
2 3 7 6 7 

cols = [col for col in df.columns if col not in ['a','b']] 
print (cols) 
['c', 'g'] 

更快的解决方案与numpy.setdiff1d

cols = np.setdiff1d(df.columns, ['a','b']).tolist() 
print (cols) 
['c', 'g'] 

print (pd.melt(df,id_vars=cols, var_name='0', value_name='1')) 
    c g 0 1 
0 4 0 a 1 
1 5 1 a 2 
2 6 7 a 3 
3 4 0 b 9 
4 5 1 b 8 
5 6 7 b 7 
+0

谢谢,这看起来很不错!但是,请注意“*实际数据框有几列我想保留*”(即:许多'c'列)。有没有办法使用'a'和'b'作为参数来代替'c'? ('a'和'b'总是2,但是有很多'c'列有不同的名字,我想保留所有这些列)。 – Peque

+0

当然,给我一下。 – jezrael

+0

请检查更新我的答案。 – jezrael