У меня есть фрейм данных pandas, который выглядит так
Index Key 2010-01 2010-02 2010-03 ... 2020-12
A/B/C foo 0.23 0.44 0 2.1
A/B/C bar 0.43 0.12 0.23 1.2
A/B/C baz 0.25 0.23 0.2 2.5
P/Q/R foo 0.31 0.41 0 2.4
P/Q/R foo 0.33 0.54 0.5 4.2
P/Q/R foo 0.93 0.64 0.99 6.5
index
— это индекс из нескольких столбцов. «foo», «bar», «baz» присутствуют для каждого индекса.
Как мне преобразовать эту группу данных в отдельные кадры данных, которые выглядят так
# dataframe for A/B/C
index foo bar baz
2010-01 0.23 0.43 0.25
2010-02 0.44 0.12 0.23
...
2020-12 2.1 1.2 2.5
Я довольно новичок в пандах, поэтому попробовал конвертировать данные в словари и работать с ними. Итак, у меня есть решение, которое включает сбор необходимых значений, а затем на втором проходе преобразование их в отдельные кадры данных. Псевдокод был такой
# loop over the converted dictionary (as per keys)
For each key, create 'foo', 'bar', 'baz' with empty dicts;
when encountering a row for 'foo', collect all values from col 2010-01 to 2020-12 as a list
do the same for 'bar' and 'baz'. Add to the nested dict that is held by the given key
For the second pass, loop through each key
take the nested dict and create a dataframe using the entire dict and the dates 2010-01 to 2020-12 as the index.
Есть ли более панда-способ сделать это? Можно ли преобразовать группу, полученную по индексу A/B/C, и транспонировать ее, не теряя при этом производительности, связанной с транспонированием?
Фактические данные, о которых идет речь, могут иметь более 10 000 таких индексов (> 30 тысяч строк).
похоже, вы ищете стержень
Предполагая, что df
— это начальный DataFrame, я думаю, вы ищете это:
import pandas as pd
for idx in df["Index"].unique():
print(pd.pivot_table(df[df["Index"] == idx],
values=["2010-01", "2010-02", "2010-03", "2020-12"],
columns=["Key"]))
Конечно, список ценностей можно получить из df.columns
.
Этот подход неэффективен, вам придется снова разрезать полный DataFrame для каждого индекса. Лучше используйте groupby
для уникальной операции.
Согласен, в зависимости от нагрузки это тоже вариант.
Предполагая, что индекс является индексом, используйте groupby и транспонирование в словарном понимании, чтобы создать словарь DataFrames:
out = {k: g.set_index('Key').T for k, g in df.groupby(level='Index')}
Выход:
{'A/B/C': Key foo bar baz
2010-01 0.23 0.43 0.25
2010-02 0.44 0.12 0.23
2010-03 0.00 0.23 0.20
2020-12 2.10 1.20 2.50,
'P/Q/R': Key foo foo foo
2010-01 0.31 0.33 0.93
2010-02 0.41 0.54 0.64
2010-03 0.00 0.50 0.99
2020-12 2.40 4.20 6.50}
Затем вы можете получить доступ к каждому DataFrame по ключу:
# out['A/B/C']
Key foo bar baz
2010-01 0.23 0.43 0.25
2010-02 0.44 0.12 0.23
2010-03 0.00 0.23 0.20
2020-12 2.10 1.20 2.50
В качестве альтернативы, если у вас есть одинаковые (уникальные) ключи (foo/bar/baz) для всех групп, вы также можете использовать стек Pivot +:
tmp = df.reset_index().pivot(index='Index', columns='Key').stack(0)
out = dict(list(tmp.reset_index(level=0, drop=True)
.groupby(tmp.index.get_level_values(0))))
Выход:
{'A/B/C': Key bar baz foo
2010-01 0.43 0.25 0.23
2010-02 0.12 0.23 0.44
2010-03 0.23 0.20 0.00
2020-12 1.20 2.50 2.10,
'P/Q/R': Key bar baz foo
2010-01 0.33 0.93 0.31
2010-02 0.54 0.64 0.41
2010-03 0.50 0.99 0.00
2020-12 4.20 6.50 2.40}
@dmayilyan это словарь DataFrames, наиболее логичный способ хранения нескольких DataFrames с ключами.
Ах да, ты прав, моя вина.
Я считаю, что ваш вопрос требует дополнительных разъяснений. Трудно понять, чего вы пытаетесь достичь, учитывая примеры данных и ожидаемый результат. Пожалуйста, обновите свой минимальный воспроизводимый пример набором образцов данных и покажите преобразование, которое приводит к ожидаемому результату. См. Как сделать хорошие воспроизводимые примеры панд, чтобы узнать о лучших практиках, связанных с вопросами о пандах.