2016-07-23 2 views
3

У меня есть панд DataFrame со структурой, как это:стека два столбца в 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 

Я хочу, чтобы сложить столбцы let1 и let2, и добавить метку рассказывая, откуда они пришли. То же самое для num1 и num2. В конце концов, я хотел бы добиться этого:

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 (Д.Ф., { 'letval': [ 'let1', 'let2'], 'numval' : ['num1', 'num2']}) '. Это не хорошо документированная функция, поэтому добавление ее в качестве комментария. – ayhan

+0

@ayhan, это идеальное решение - положите его как ответ – MaxU

+0

@MaxU К сожалению, это просто частичное решение, которое сделал Луис. Он теряет колонки let и num. – ayhan

ответ

4

Вот моя попытка объединить решение @ayhan «s с помощью метода 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

Если я правильно понимаю: сначала вы принимаете только один столбец 'value', отбрасывая все остальные, применяете' melt', а затем снова помещаете все удаленные столбцы ('reshape' +' assign') ... Я предполагаю, что расплав только позвольте вам сделать это один раз, правильно? Я имею в виду, у вас есть только 1 * измерение * ('let') ... – Luis

+0

@ Луис, да, это правильно – 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 
Смежные вопросы