在DataFrame中堆叠两列,重复其他列

时间:2016-07-23 14:47:49

标签: python pandas dataframe

我有一个像这样的结构的pandas DataFrame:

df = pd.DataFrame( [
            [ 'foo1', 'a', 'z', 'bar1', 1, 4 ],
            [ 'foo2', 'b', 'y', 'bar2', 2, 5 ],
            [ 'foo3', 'c', 'x', 'bar3', 3, 6 ]
        ] )
df.columns = [ 'foo', 'let1', 'let2', 'bar', 'num1', 'num2' ]
print( df )
    foo let1 let2   bar  num1  num2
0  foo1    a    z  bar1     1     4
1  foo2    b    y  bar2     2     5
2  foo3    c    x  bar3     3     6

我想要堆叠列let1let2,并添加一个标签,告诉它们来自哪里。 num1num2也是如此。最后,我想实现这个目标:

    foo   let letval   bar   num  numval
0  foo1  let1      a  bar1  num1       1
1  foo2  let1      b  bar2  num1       2
2  foo3  let1      c  bar3  num1       3
3  foo1  let2      z  bar1  num2       4
4  foo2  let2      y  bar2  num2       5
5  foo3  let2      x  bar3  num2       6

到目前为止,我已经这样做了:

let = pd.concat( [ df.let1, df.let2 ] )
num = pd.concat( [ df.num1, df.num2 ] )
df = df.drop( ['let1', 'let2', 'num1', 'num2' ], axis=1 )
df = pd.concat( [ df, df ] )    
df[ 'letval' ] = let
df[ 'numval' ] = num
print( df )

    foo   bar letval  numval
0  foo1  bar1      a       1
1  foo2  bar2      b       2
2  foo3  bar3      c       3
0  foo1  bar1      z       4
1  foo2  bar2      y       5
2  foo3  bar3      x       6

但是,我很确定有一种更简单的方法可以实现这一点,而无需复制到虚拟变量和此类变通方法。

有什么想法吗?

3 个答案:

答案 0 :(得分:4)

以下是我尝试将@ayhan的解决方案与pd.melt()方法结合使用:

In [191]: (pd.melt(df.drop(['num1','num2'], 1), id_vars=['foo','bar'],
   .....:          var_name='let', value_name='letval')
   .....:    .assign(numval=pd.lreshape(df.filter(like='num'),
   .....:                               {'numval': ['num1', 'num2']})))
Out[191]:
    foo   bar   let letval  numval
0  foo1  bar1  let1      a       1
1  foo2  bar2  let1      b       2
2  foo3  bar3  let1      c       3
3  foo1  bar1  let2      z       4
4  foo2  bar2  let2      y       5
5  foo3  bar3  let2      x       6

答案 1 :(得分:2)

与此同时,我也得到了答案。

@MaxU更加温和,并且基于@ayhan的评论。

let = [ 'let1', 'let2' ]
num = [ 'num1', 'num2' ]

n = df.shape[0]
df = pd.lreshape(df, { 'letval': let, 'numval': num } )

df[ 'let' ] = [ item for item in let for _ in range(n) ]
df[ 'num' ] = [ item for item in num for _ in range(n) ]

print( df )


    bar   foo letval  numval   let   num
0  bar1  foo1      a       1  let1  num1
1  bar2  foo2      b       2  let1  num1
2  bar3  foo3      c       3  let1  num1
3  bar1  foo1      z       4  let2  num2
4  bar2  foo2      y       5  let2  num2
5  bar3  foo3      x       6  let2  num2

答案 2 :(得分:1)

试试这个:

dfm =  pd.melt(df.drop(['num1','num2'], 1), id_vars=['foo','bar'], var_name=('let'), value_name=('letval'))
dfm[['num', 'numvals']] = pd.melt(df.drop(['let1','let2'], 1), id_vars=['foo','bar'], var_name=('num'), value_name=('numvals'))[['num', 'numvals']]

dfm:
   foo   bar   let  letval  num  numvals
0  foo1  bar1  let1      a  num1        1
1  foo2  bar2  let1      b  num1        2
2  foo3  bar3  let1      c  num1        3
3  foo1  bar1  let2      z  num2        4
4  foo2  bar2  let2      y  num2        5
5  foo3  bar3  let2      x  num2        6