Как написать/прочитать Pandas DataFrame с MultiIndex из/в ASCII файл?
Я хочу иметь возможность создавать Pandas DataFrame
с помощью MultiIndexes для строк и индекса столбцов и читать их из текстового файла ASCII. Мои данные выглядят так:
col_indx = MultiIndex.from_tuples([('A', 'B', 'C'), ('A', 'B', 'C2'), ('A', 'B', 'C3'),
('A', 'B2', 'C'), ('A', 'B2', 'C2'), ('A', 'B2', 'C3'),
('A', 'B3', 'C'), ('A', 'B3', 'C2'), ('A', 'B3', 'C3'),
('A2', 'B', 'C'), ('A2', 'B', 'C2'), ('A2', 'B', 'C3'),
('A2', 'B2', 'C'), ('A2', 'B2', 'C2'), ('A2', 'B2', 'C3'),
('A2', 'B3', 'C'), ('A2', 'B3', 'C2'), ('A2', 'B3', 'C3')],
names=['one','two','three'])
row_indx = MultiIndex.from_tuples([(0, 'North', 'M'),
(1, 'East', 'F'),
(2, 'West', 'M'),
(3, 'South', 'M'),
(4, 'South', 'F'),
(5, 'West', 'F'),
(6, 'North', 'M'),
(7, 'North', 'M'),
(8, 'East', 'F'),
(9, 'South', 'M')],
names=['n', 'location', 'sex'])
size=len(row_indx), len(col_indx)
data = np.random.randint(0,10, size)
df = DataFrame(data, index=row_indx, columns=col_indx)
print df
Я пробовал df.to_csv()
и read_csv()
, но они не сохраняют индекс.
Я думал о создании нового формата с использованием дополнительных разделителей. Например, используя строку ----------------
, чтобы пометить конец индексов столбцов и |
, чтобы отметить конец индекса строки. Таким образом, это будет выглядеть так:
one | A A A A A A A A A A2 A2 A2 A2 A2 A2 A2 A2 A2
two | B B B B2 B2 B2 B3 B3 B3 B B B B2 B2 B2 B3 B3 B3
three | C C2 C3 C C2 C3 C C2 C3 C C2 C3 C C2 C3 C C2 C3
--------------------------------------------------------------------------------------
n location sex :
0 North M | 2 3 9 1 0 6 5 9 5 9 4 4 0 9 6 2 6 1
1 East F | 6 2 9 2 7 0 0 3 7 4 8 1 3 2 1 7 7 5
2 West M | 5 8 9 7 6 0 3 0 2 5 0 3 9 6 7 3 4 9
3 South M | 6 2 3 6 4 0 4 0 1 9 3 6 2 1 0 6 9 3
4 South F | 9 6 0 0 6 1 7 0 8 1 7 6 2 0 8 1 5 3
5 West F | 7 9 7 8 2 0 4 3 8 9 0 3 4 9 2 5 1 7
6 North M | 3 3 5 7 9 4 2 6 3 2 7 5 5 5 6 4 2 9
7 North M | 7 4 8 6 8 4 5 7 9 0 2 9 1 9 7 9 5 6
8 East F | 1 6 5 3 6 4 6 9 6 9 2 4 2 9 8 4 2 4
9 South M | 9 6 6 1 3 1 3 5 7 4 8 6 7 7 8 9 2 3
Есть ли у Pandas способ записи/чтения DataFrames в/из ASCII файлов с помощью MultiIndexes?
Ответы
Ответ 1
Не знаете, какую версию pandas вы используете, но с 0.7.3
вы можете экспортировать DataFrame
в TSV файл и сохранить индексы, выполнив следующие действия:
df.to_csv('mydf.tsv', sep='\t')
Причина, по которой вам нужно экспортировать в TSV по сравнению с CSV, так как заголовки столбцов имеют в них символы ,
. Это должно решить первую часть вашего вопроса.
Вторая часть становится немного сложнее, поскольку, насколько я могу судить, вам нужно заранее иметь представление о том, что вы хотите, чтобы ваш DataFrame содержал. В частности, вам нужно знать:
- Какие столбцы вашего TSV представляют строку
MultiIndex
- и что остальные столбцы также должны быть преобразованы в
MultiIndex
Чтобы проиллюстрировать это, давайте вернем сохраненный выше TSV файл в новый DataFrame
:
In [1]: t_df = read_table('mydf.tsv', index_col=[0,1,2])
In [2]: all(t_df.index == df.index)
Out[2]: True
Таким образом, нам удалось прочитать mydf.tsv
в DataFrame
, который имеет тот же индекс строки, что и исходный df
. Но:
In [3]: all(t_df.columns == df.columns)
Out[3]: False
И причина здесь в том, что pandas (насколько я могу судить) не имеет возможности правильно разбора строки заголовка в MultiIndex
. Как я уже упоминал выше, если вы знаете, что ваш заголовок файла TSV представляет MultiIndex
, вы можете сделать следующее, чтобы исправить это:
In [4]: from ast import literal_eval
In [5]: t_df.columns = MultiIndex.from_tuples(t_df.columns.map(literal_eval).tolist(),
names=['one','two','three'])
In [6]: all(t_df.columns == df.columns)
Out[6]: True
Ответ 2
Вы можете изменить параметры печати, используя set_option
:
display.multi_sparse
:
: boolean
& ЕПРС; & ЕПРС; По умолчанию True
, "спарсинг" MultiIndex
дисплей
& ЕПРС; & emsp; (не отображать повторяющиеся элементы на внешних уровнях внутри групп)
Теперь DataFrame будет напечатан по желанию:
In [11]: pd.set_option('multi_sparse', False)
In [12]: df
Out[12]:
one A A A A A A A A A A2 A2 A2 A2 A2 A2 A2 A2 A2
two B B B B2 B2 B2 B3 B3 B3 B B B B2 B2 B2 B3 B3 B3
three C C2 C3 C C2 C3 C C2 C3 C C2 C3 C C2 C3 C C2 C3
n location sex
0 North M 2 1 6 4 6 4 7 1 1 0 4 3 9 2 0 0 6 4
1 East F 3 5 5 6 4 8 0 3 2 3 9 8 1 6 7 4 7 2
2 West M 7 9 3 5 0 1 2 8 1 6 0 7 9 9 3 2 2 4
3 South M 1 0 0 3 5 7 7 0 9 3 0 3 3 6 8 3 6 1
4 South F 8 0 0 7 3 8 0 8 0 5 5 6 0 0 0 1 8 7
5 West F 6 5 9 4 7 2 5 6 1 2 9 4 7 5 5 4 3 6
6 North M 3 3 0 1 1 3 6 3 8 6 4 1 0 5 5 5 4 9
7 North M 0 4 9 8 5 7 7 0 5 8 4 1 5 7 6 3 6 8
8 East F 5 6 2 7 0 6 2 7 1 2 0 5 6 1 4 8 0 3
9 South M 1 2 0 6 9 7 5 3 3 8 7 6 0 5 4 3 5 9
Примечание: в старых версиях pandas это было pd.set_printoptions(multi_sparse=False)
.