2016-05-24 4 views
3

У меня есть таблица в формате закладки креста, пример ниже:Есть ли способ использовать функцию расплава в Python для нескольких столбцов?

State Item # x1 x2 x3 y1 y2 y3 z1 z2 z3 
CA  1  6 4 3 7 5 3  11  5  1 
CA  2  7 3 1 15 10 5  4  2  1 
FL  3  3 2 1 5 3 2  13  7  2 
FL  4  9 4 2 16 14 12  14  5  4 

Я пытаюсь использовать функцию расплава, чтобы поместить данные в следующем формате:

State Item # x xvalue y yvalue z zvalue 
CA  1  x1 6  y1 7  z1 11 
CA  1  x2 4  y2 5  z2 5 
CA  1  x3 3  y3 3  z3 1 
CA  2  x1 7  y1 15 z1 4 
CA  2  x2 3  y2 10 z2 2 
CA  2  x3 1  y3 5  z3 1  

Я знаю, как использовать функцию расплава, чтобы сделать это только для одного из значений, например x. Но я не знаю, как это сделать с y и z. См. Мой код ниже, чтобы сделать это только для x. Есть ли способ, который я могу настроить, чтобы это сделать для y и z также? Или я должен попробовать отдельные функции расплава для x, y и z, а затем как-то их объединить?

df_m = pd.melt(df, id_vars=['State', 'Item #'], 
      value_vars=['x1','x2','x3'], 
      var_name='x', value_name='xvalue') 
+0

Думаю, вам, возможно, потребуется несколько расплавов. – BrenBarn

ответ

1

Я не думаю, что это так, но вы можете использовать решение две строки:

values = [['x1','x2','x3'], ['y1', 'y2', 'y3'], ['z1', 'z2', 'z3']] 

df_m = pd.concat([pd.melt(df, id_vars=['State', 'Item_#'], value_vars=val, var_name='var', value_name='value') for val in values]) 

pd.concat функция является мощным (т.е. быстрый) способ укладывать DataFrames вертикально.

1

Вот версия, которая не использует melt, но работает для любого количества групп «xyz».

import pandas as pd 
from io import StringIO 

df = pd.read_csv(StringIO(''' 
    State ItemN x1 x2 x3 y1 y2 y3 z1 z2 z3 
CA  1  6 4 3 7 5 3  11  5  1 
CA  2  7 3 1 15 10 5  4  2  1 
FL  3  3 2 1 5 3 2  13  7  2 
FL  4  9 4 2 16 14 12  14  5  4'''), 
sep=r' +') 

# prepare index 
df = df.set_index(list(df.columns[:2])) 
df.columns = pd.MultiIndex.from_tuples([(c[0], c) for c in df.columns]) 

#    x   y   z  
#    x1 x2 x3 y1 y2 y3 z1 z2 z3 
# State ItemN        
# CA 1  6 4 3 7 5 3 11 5 1 
#  2  7 3 1 15 10 5 4 2 1 
# FL 3  3 2 1 5 3 2 13 7 2 
#  4  9 4 2 16 14 12 14 5 4 


# stack and concat each 'group' 
df2 = pd.concat((
    df[c].stack().reset_index(-1) 
    for c in df.columns.levels[0]), 
    axis=1) 

# rename the columns 
new_cols = [None for _ in range(df2.shape[1])] 
new_cols[::2] = [c for c in df.columns.levels[0]] 
new_cols[1::2] = [c + 'value' for c in df.columns.levels[0]] 

df2.columns = new_cols 

#    x xvalue y yvalue z zvalue 
# State ItemN          
# CA 1  x1  6 y1  7 z1  11 
#  1  x2  4 y2  5 z2  5 
#  1  x3  3 y3  3 z3  1 
#  2  x1  7 y1  15 z1  4 
#  2  x2  3 y2  10 z2  2 
#  2  x3  1 y3  5 z3  1 
# FL 3  x1  3 y1  5 z1  13 
#  3  x2  2 y2  3 z2  7 
#  3  x3  1 y3  2 z3  2 
#  4  x1  9 y1  16 z1  14 
#  4  x2  4 y2  14 z2  5 
#  4  x3  2 y3  12 z3  4 
0

Что относительно pd.wide_to_long?

# Make dataframe 
df = pd.DataFrame({'State' : ['CA']*2 + ['FL']*2, 
        'Item' : [1, 2, 3, 4], 
        'x1' : [6, 7, 3, 9], 
        'x2' : [4, 3, 2, 4], 
        'x3' : [3, 1, 1, 2], 
        'y1' : [7, 15, 5, 16], 
        'y2' : [5, 10, 3, 14], 
        'y3' : [3, 5, 2, 12], 
        'z1' : [11, 4, 13, 14], 
        'z2' : [5, 2, 7, 5], 
        'z3' : [1, 1, 2, 4]}) 

# Make final dataframe using pd.wide_to_long 
final = pd.wide_to_long(df, 
         stubnames = ['x', 'y', 'z'], 
         i = ['State', 
          'Item'], 
         j = 'number').reset_index() 

# Show final dataframe 
final 

wide_to_long

Я знаю, что dataframe вернулся не выглядит так же, как тот, который вы запрошенной, но она все еще может работать. Фактически, теперь он объединяет ваши столбцы x, y, z, xvalue, yvalue и zvalue в столбцы x, y, z и 'number' для обращения к первому, второму и третьему значениям.