2016-07-23 41 views
3

我有一個熊貓數據幀像這樣的結構:在數據幀堆棧兩列,重複別人

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 

不過,我敢肯定,有一個更簡單的方法實現這一點,而不需複製到虛擬變量和此類變通方法。

任何想法?

+2

你這樣做可以簡化爲'pd.lreshape(DF,{ 'letval' 的一部分: 'let1', 'let2'], 'numval' :['num1','num2']})'。它不是一個記錄良好的功能,因此添加它作爲評論。 – ayhan

+0

@ayhan,這是一個完美的解決方案 - 把它作爲一個答案 – MaxU

+0

@MaxU不幸的是,這只是Luis已經做到的部分解決方案。它失去了let和num指標列。 – ayhan

回答

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 
+0

如果我理解正確:您首先只需要1個「值」列,通過刪除所有其他列,應用'melt',然後再次放置所有刪除的列('reshape' +'assign')...我想融化只讓你做一次吧?我的意思是,你只有1 *測量*('let')... – Luis

+0

@Luis,是的,這是正確的 – MaxU

+0

仍然試圖吸收它。我想我可以喜歡'熔化'(以前從未使用過);) – Luis

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 
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