Разделить многоуровневый фрейм данных на разные файлы csv

Предположим, у меня есть следующий кадр данных:

    X       Y
   ---+---+---+---
    A | B | A | B
--+---+---+---+---
0 | 1 | 2 | 3 | 4
1 | 5 | 6 | 7 | 8
2 | 9 | 10| 11| 12

Я хочу рекурсивно разделить его на основе многоуровневого индекса и сохранить их в файле csv.

Например, имя файла X_A.csv должно содержать следующий кадр данных:

    X 
   ---
    A 
--+---
0 | 1 
1 | 5 
2 | 9 

Точно так же файл X_B.csv должен хранить кадр данных как:

    X 
   ---
    B 
--+---
0 | 2 
1 | 6 
2 | 10

и так далее для Y_A и Y_B.

Я ищу Pythonic (или эффективный) способ сделать это, а не перебирать значения столбца отдельно, поскольку код довольно большой. Я пытался использовать методы, упомянутые здесь , отбрасывая уровни столбцов и сохраняя отдельные столбцы, но я хочу сделать это таким образом, чтобы мне не нужно было явно указывать имена столбцов, поскольку фрейм данных может расширяться (т.е. на самом верхнем уровне может быть 4 в столбцах указано W, X, Y и Z).


person Gambit1614    schedule 11.09.2017    source источник
comment
Почему бы не объединить два имени столбца уровня в одно   -  person BENY    schedule 11.09.2017
comment
Если подкласс panda.Dataframe numpy.Ndarray, вы не можете использовать индексация numpy на нем, чтобы выбрать интересующие вас столбцы, а затем использовать метод объекта для экспорта в CSV   -  person Nicolas David    schedule 11.09.2017
comment
@Wen Я не хочу менять исходный df, поэтому я не хочу объединять имена столбцов двух уровней.   -  person Gambit1614    schedule 12.09.2017


Ответы (3)


list_of_df = [df[i].to_frame() for i in df.columns]

С предложением @JohnGalt для csv:

_ = [df[i].to_frame().to_csv('{0}_{1}'.format(*i)) for i in df.columns]

Выход:

list_of_df[0]

   X
   A
0  1
1  5
2  9

list_of_df[1]

    X
    B
0   2
1   6
2  10

...

list_of_df[3]

    Y
    B
0   4
1   8
2  12
person Scott Boston    schedule 11.09.2017
comment
Аккуратно и ...to_csv('{0}_{1}.csv'.format(*i)) для csv. - person Zero; 11.09.2017

Вы можете использовать простой apply для этого.

Создайте пример ДФ:

import pandas as pd
import numpy as np

index = pd.MultiIndex(levels=[['X', 'Y'], ['A', 'B']],labels=[[0, 0, 1, 1], [0, 1, 0, 1]])
df = pd.DataFrame(columns=index, data=np.arange(12).reshape((3, 4)))

>>> df
Out[]:
   X      Y
   A  B   A   B
0  0  1   2   3
1  4  5   6   7
2  8  9  10  11

Сохранить как отдельные файлы CSV:

df.apply(lambda x: x.to_csv('_'.join(x.name) + '.csv'), axis=0)

Это даст желаемый результат. Например, X_A.csv содержит:

0,0
1,4
2,8

Если вы хотите включить имя оси в csv, добавьте header=True в качестве аргумента к to_csv, тогда X_A.csv будет содержать:

,X
,A
0,0
1,4
2,8
person FabienP    schedule 11.09.2017

Вариант 1

Переименовать df.columns

df.columns = ['_'.join(x) for x in df.columns]

df

   X_A  X_B  Y_A  Y_B
0                    
0    1    2    3    4
1    5    6    7    8
2    9   10   11   12

for c in df:
     df[c].reset_index().to_csv(c + '.csv')

Вариант 2

groupby уровней

for name, g in df.groupby(level=[0, 1], axis=1):
    g.to_csv('{0}_{1}.csv'.format(*name))
person cs95    schedule 11.09.2017