У меня есть датафрейм с довольно неинтуитивной структурой:

device1    device2    column_name
      1          1    date
    111        211    param1
    112        212    param2
      2          2    date
    121        221    param1
    122        222    param2
      3          3    date
    131        231    param1
    132        232    param2

Мне трудно преобразовать его в желаемый фрейм данных:

           date    param1    param2
device1       1       111       112
              2       121       122
              3       131       132
device2       1       211       212
              2       221       222
              3       231       232

Игра с pivot, stack / unstack позволила мне приблизиться, но так и не достигла цели.

Как я могу это сделать?

2
user7647857 5 Дек 2020 в 19:45

3 ответа

Лучший ответ

Вы можете stack изменить форму фрейма данных, затем использовать groupby + cumcount для создания последовательного счетчика для идентификации строк с разницей, наконец, использовать set_index для создания многоуровневого индекса и использовать {{X4} } изменить форму:

d = df.set_index('column_name').stack()
i = d.groupby(level=[0, 1]).cumcount()
out = d.to_frame().set_index(i, append=True)[0].unstack(0).droplevel(1)

print(out)

column_name  date  param1  param2
device1         1     111     112
device1         2     121     122
device1         3     131     132
device2         1     211     212
device2         2     221     222
device2         3     231     232
2
Shubham Sharma 5 Дек 2020 в 17:48

Одно из возможных решений:

tmp = df.melt("column_name")
tmp = tmp.set_index(['variable', 'column_name', tmp.column_name.eq('date').cumsum()])["value"].unstack(-2).droplevel(-1)
tmp.columns.name = None
tmp

         date   param1  param2
variable            
device1     1   111     112
device1     2   121     122
device1     3   131     132
device2     1   211     212
device2     2   221     222
device2     3   231     232

Сложность заключалась в том, чтобы распаковать без уникального идентификатора. Цель tmp.column_name.eq('date').cumsum() - дать идентификатор каждой группе (под группой я имею в виду комбинацию date, param1 и param2). Этот вопрос помог мне понять этот.

1
XavierBrt 5 Дек 2020 в 22:36

Вы можете использовать melt с pivot для изменения формы фрейма данных; как и другие ответы, вам нужен уникальный идентификатор:

(
    df.melt("column_name")
    .assign(unique_id=lambda x: x.groupby("column_name").cumcount())
    .pivot(index=["unique_id", "variable"], columns="column_name", values="value")
    .droplevel("unique_id")
    .rename_axis(columns=None, index=None)
)



          date  param1  param2
device1    1     111    112
device1    2     121    122
device1    3     131    132
device2    1     211    212
device2    2     221    222
device2    3     231    232
0
sammywemmy 5 Дек 2020 в 21:51