Растопить кучу многоиндексированных столбцов, сохраняя при этом один столбец индекса - PullRequest
2 голосов
/ 14 октября 2019

У меня есть большая таблица со строками, представляющими наблюдения. Подмножество моих столбцов может быть сгруппировано по двум мета-категориям, поэтому я представил их с помощью мультииндекса. Однако мультииндекс не применим ко всем столбцам. Таким образом, все остальные столбцы имеют индексные метки только на первом уровне.

Я хочу применить melt () к некоторым из этих многомерных столбцов, а затем объединить их с моей главной таблицей позже по столбцу индекса.

Вот MRE той части, на которой я застрял. У меня есть фрейм данных, подобный этому:

df = pd.DataFrame({
  ('INDEX',): [1,2,3],
  ('a','x'): ['ww','rt','pb'],
  ('a','y'): [88,97,12],
  ('b','x'): ['ew','tr','cv'],
  ('b','y'): [14,42,67],
  ('c','x'): ['wq','fg','dg'],
  ('c','y'): [65,78,46]})

df
  INDEX   a       b       c
    NaN   x   y   x   y   x   y
0     1  ww  88  ew  14  wq  65
1     2  rt  97  tr  42  fg  78
2     3  pb  12  cv  67  dg  46

Теперь я хотел бы, чтобы:

df.melt(id_vars=('INDEX',))

..., чтобы привести к этому:

INDEX thing_1 thing_2 value
    1       a       x    ww
    2       a       x    rt
    3       a       x    pb
    1       a       y    88
    2       a       y    97
    3       a       y    12
    1       b       x    ew
    2       b       x    tr
    3       b       x    cv
    1       b       y    14
    2       b       y    42
    3       b       y    67
    1       c       x    wq
    2       c       x    fg
    3       c       x    dg
    1       c       y    65
    2       c       y    78
    3       c       y    46

Но я получаю длинную трассировку, заканчивающуюся Exception: Data must be 1-dimensional.

Когда я впервые начал пытаться это сделать, я пытался предоставить value_vars, но безуспешно;Позже я понял, что del df['INDEX']; df.melt() работает без проблем, за исключением, конечно, того, что я хотел сохранить свой столбец INDEX.

Я также пробовал некоторые варианты, такие как помещение 'INDEX' в 1-кортеж, 2-кортеж, оканчивающийся на np.nan и slice(None), список и т. д. Я получаю ту же жалобу на одномерные данные, а в некоторых случаях ValueError: id_vars must be a list of tuples when columns are a MultiIndex.

Как правильно поступить в этом отношении? Я нашел решение после множества проб и ошибок, которые я опубликую ниже, но кажется, что оно должно быть проще или элегантнее. Спасибо.

Ответы [ 2 ]

2 голосов
/ 14 октября 2019

Вы можете использовать пустую строку в качестве 2-го уровня INDEX

df = pd.DataFrame({
  ('INDEX',''): [1,2,3],
  ('a','x'): ['ww','rt','pb'],
  ('a','y'): [88,97,12],
  ('b','x'): ['ew','tr','cv'],
  ('b','y'): [14,42,67],
  ('c','x'): ['wq','fg','dg'],
  ('c','y'): [65,78,46]})

In [198]: df
Out[198]:
  INDEX   a       b       c
          x   y   x   y   x   y
0     1  ww  88  ew  14  wq  65
1     2  rt  97  tr  42  fg  78
2     3  pb  12  cv  67  dg  46

df.melt(id_vars='INDEX')

Out[200]:
    INDEX variable_0 variable_1 value
0       1          a          x    ww
1       2          a          x    rt
2       3          a          x    pb
3       1          a          y    88
4       2          a          y    97
5       3          a          y    12
6       1          b          x    ew
7       2          b          x    tr
8       3          b          x    cv
9       1          b          y    14
10      2          b          y    42
11      3          b          y    67
12      1          c          x    wq
13      2          c          x    fg
14      3          c          x    dg
15      1          c          y    65
16      2          c          y    78
17      3          c          y    46
0 голосов
/ 14 октября 2019

После того, как я начал составлять этот вопрос, я наткнулся на решение.

Если я заменим ('INDEX',) на ('INDEX','foo') в своем назначении DataFrame, тогда я получу решение, которое мне нужно, например:

df.melt(id_vars=[('INDEX','foo')])

    (INDEX, foo) variable_0 variable_1 value
0              1          a          x    ww
1              2          a          x    rt
2              3          a          x    pb
3              1          a          y    88
4              2          a          y    97
[...]
...