При повороте пустого фрейма данных создается столбец MULTIindex - PullRequest
0 голосов
/ 11 марта 2020

Я сталкиваюсь с проблемой, когда pivot_table создает MultiIndex вместо индекса для столбцов, когда я применяю его к пустому фрейму данных.

Итак, вот что я пытаюсь сделать. У меня есть некоторые данные, которые я читаю в фрейм данных df. Один столбец этого фрейма данных - 'type', и мне нужно разделить фрейм данных df на два фрейма данных df2 и df3 в зависимости от типа в этом столбце df. Хотя большую часть времени данные, которые я передаю для создания df, будут иметь оба типа (типы 'A' и 'B' ниже), иногда я могу пропустить значения одного типа другого.

Тем не менее, мне нужно создать сводную таблицу для каждого с добавленными отсутствующими столбцами и индексами, заполненными нулями, где это необходимо. Это хорошо, когда тип не пропущен в данных: я могу просто использовать .reindex дважды, чтобы заполнить отсутствующие индексы и столбцы. Но если тип полностью отсутствует, то один из производных фреймов данных (df2 или df3 ниже) будет пустым. В этом случае индекс заканчивается мультииндексом.

Вот пример

import pandas as pd
df = pd.DataFrame({'type': ['A', 'A', 'A'], 'val': [1, 2, 3], 'col': ['a', 'b', 'a'], 'ind': [6, 6, 8]})
df2 = df[df['type'] == 'A'][['val', 'col', 'ind']].pivot_table(values='val', index='ind', columns='col', fill_value=0)
df3 = df[df['type'] == 'B'][['val', 'col', 'ind']].pivot_table(values='val', index='ind', columns='col', fill_value=0)

На этом этапе я хотел бы сделать цепочку .reindex(['a', 'b', 'c', 'd'], axis=1, fill_value=0).reindex(list(range(6, 9)), axis=0, fill_value=0) на df2 и df3. Но это приводит к ошибке, потому что индекс столбца df3 равен MultiIndex([], names=[None, 'col']) вместо Index([], name='col'), как я и ожидал. И, кроме того, я не могу просто отбросить None, казалось бы, потому что такие вещи, как .drop(columns=None) просто явно не будут / не работают.

Есть ли эффективный и простой способ справиться с этим?


Чтобы немного разобрать проблему на тот случай, если я действительно должен сделать рефакторинг целиком, у меня есть данные, которые будут выглядеть примерно так

{'type': ['A', 'A', 'A'], 'val': [1, 2, 3], 'col': ['a', 'b', 'a'], 'ind': [6, 6, 8]}

Список type может включать или не включать оба типа 'A' и 'B'.

Исходя из этого, мне нужно создать два отдельных фрейма данных для сбора информации отдельно для типов 'A' и 'B', которые достаточно надежны для обработки в случае отсутствия одного из них. Результирующие кадры данных должны выглядеть следующим образом в приведенном выше примере.

df2 = 
    'a' 'b' 'c' 'd'
6    1   2   0   0
7    0   0   0   0
8    3   0   0   0

and

df3 =
    'a' 'b' 'c' 'd'
6    0   0   0   0
7    0   0   0   0
8    0   0   0   0

1 Ответ

1 голос
/ 11 марта 2020

Надеюсь, это поможет. Может быть более эффективный способ сделать это, но это работает для вашего набора данных. Одна вещь, которую я не могу получить правильно, это сохранить только совпадающие значения столбцов после слияния, но я справился с этим по-другому (надеюсь, что это неправильно)

Все, что я сделал здесь, это создал очистите df с нужными столбцами и индексом и объедините его с вашими df2 и df3 и .fillna(0) после объединения.

    import pandas as pd
    df = pd.DataFrame({'type': ['A', 'A', 'A'], 'val': [1, 2, 3], 'col': ['a', 'b', 'a'], 'ind': [6, 6, 8]})

    df1 = pd.DataFrame(columns=['a', 'b', 'c', 'd'], index=[6, 7, 8])

    df2 = df1.merge(df[df['type'] == 'A'][['val', 'col', 'ind']].pivot_table(values='val', index='ind', columns='col', fill_value=0),
                    left_index=True, right_index=True, how='left', suffixes=('','_y')).fillna(0.0)

    df3 = df1.merge(df[df['type'] == 'B'][['val', 'col', 'ind']].pivot_table(values='val', index='ind', columns='col', fill_value=0),
                    left_index=True, right_index=True, how='left').fillna(0.0)

# this section need rework as I mentioned above
    df2['a'], df2['b'] = df2['a_y'], df2['b_y']
    df2 = df2.drop(['a_y', 'b_y'],1)

    print(df2)
    print(df3)

Вывод:

df2:

     a    b    c    d
6  1.0  2.0  0.0  0.0
7  0.0  0.0  0.0  0.0
8  3.0  0.0  0.0  0.0

df3:

     a    b    c    d
6  0.0  0.0  0.0  0.0
7  0.0  0.0  0.0  0.0
8  0.0  0.0  0.0  0.0
...