Как извлечь период и имя переменной из строк столбца данных для подготовки данных мультииндексной панели - PullRequest
2 голосов
/ 20 февраля 2020

Я новичок в Python и не могу найти ответ, который ищу нигде.

У меня есть DataFrame, который имеет следующую структуру:

df = pd.DataFrame(index=list('abc'), data={'A1': range(3), 'A2': range(3),'B1': range(3), 'B2': range(3), 'C1': range(3), 'C2': range(3)})
df
Out[1]:
   A1 A2 B1 B2 C1 C2
a  0  0  0  0  0  0
b  1  1  1  1  1  1
c  2  2  2  2  2  2

Где числа являются точками, а буквы - переменными. Я хотел бы преобразовать столбцы таким образом, чтобы я разделял периоды и переменные в мультииндекс. Требуемый результат будет выглядеть так:

   A     B     C   
   1  2  1  2  1  2
a  0  0  0  0  0  0
b  1  1  1  1  1  1
c  2  2  2  2  2  2

Я пробовал следующее:

periods = list(range(1, 3))
df.columns = df.columns.str.replace('\d+', '')
df.columns = pd.MultiIndex.from_product([df.columns, periods])

То, что швы для умножения столбцов и повышения ValueError: несоответствие длины

в моем фрейме данных у меня 72 периода и 12 переменных.

Заранее благодарен за вашу помощь!

Редактировать : Я понял, что недостаточно точен , У меня есть несколько имен столбцов, например Impressions1, Impressions2 ... Impressions72 и hhi1, hhi2 ... hhi72. Так что df.columns.str [0], df.columns.str [1] у меня не работает, так как все имена столбцов имеют разную длину. Я думаю, что решение может содержать регулярное выражение, но я не могу понять, как это сделать. Есть идеи?

Ответы [ 3 ]

3 голосов
/ 20 февраля 2020

Использование pd.MultiIndex.from_tuples:

df.columns = pd.MultiIndex.from_tuples(list(zip(df.columns.str[0],df.columns.str[1])))
print(df)
   A     B     C   
   1  2  1  2  1  2
a  0  0  0  0  0  0
b  1  1  1  1  1  1
c  2  2  2  2  2  2

Альтернатива:

pd.MultiIndex.from_tuples([tuple(name) for name in df.columns])

или

pd.MultiIndex.from_tuples(map(tuple, df.columns))
2 голосов
/ 20 февраля 2020

Вы также можете использовать .str.extract и from_frame:

df.columns = pd.MultiIndex.from_frame(df.columns.str.extract('(.)(.)'), names=[None, None])

Выход:

   A     B     C   
   1  2  1  2  1  2
a  0  0  0  0  0  0
b  1  1  1  1  1  1
c  2  2  2  2  2  2
0 голосов
/ 14 марта 2020

Вот что на самом деле решило мою проблему:

df.columns = pd.MultiIndex.from_frame(df.columns.str.extract(r'([a-zA-Z]+)([0-9]+)'), names=[None, None])

Спасибо @Scott Boston за вдохновение в решении!

...