Обробка змінної кількості стовпців з Pandas - Python


76

У мене є набір даних, який виглядає так (щонайбільше 5 стовпців - але може бути і менше)

1,2,3
1,2,3,4
1,2,3,4,5
1,2
1,2,3,4
....

Я намагаюся використовувати pandas read_table, щоб прочитати це у 5-стовпчатий фрейм даних. Я хотів би прочитати це без додаткового масажу.

Якщо я спробую

import pandas as pd
my_cols=['A','B','C','D','E']
my_df=pd.read_table(path,sep=',',header=None,names=my_cols)

Я отримую помилку - "імена стовпців мають 5 полів, дані мають 3 поля".

Чи є спосіб змусити панд заповнити NaN для відсутніх стовпців під час зчитування даних?

Відповіді:


80

Один із способів, який, здається, працює (принаймні в 0.10.1 та 0.11.0.dev-fc8de6d):

>>> !cat ragged.csv
1,2,3
1,2,3,4
1,2,3,4,5
1,2
1,2,3,4
>>> my_cols = ["A", "B", "C", "D", "E"]
>>> pd.read_csv("ragged.csv", names=my_cols, engine='python')
   A  B   C   D   E
0  1  2   3 NaN NaN
1  1  2   3   4 NaN
2  1  2   3   4   5
3  1  2 NaN NaN NaN
4  1  2   3   4 NaN

Зауважте, що для цього підходу потрібно вводити імена потрібним стовпцям. Не настільки загальний, як деякі інші способи, але працює досить добре, коли застосовується.


2
Дякую! Це спрацювало - двигун = 'python', схоже, є ключовим. Додавання цього атрибута змушує працювати як read_table, так і read_csv.
Джекі Шепхард,

2
Це здається мені досить бородавчастим. Додавання випуску github: github.com/pydata/pandas/issues/2981
Wes McKinney

1
Для мене це зафіксувало те, names=my_colsде my_colsбуло принаймні стільки, скільки лінія з найбільшою кількістю полів. Якщо максимальна кількість полів не відома заздалегідь, ви можете динамічно витягти, заздалегідь прочитавши файл через, with open('my.csv') as f: num_cols = max(len(line.split(',')) for line in f); f.seek(0); df = pd.read_csv(f, names=range(num_cols)) але зворотний бік полягає в тому, що файл читається двічі.
EliadL

з версією Pandas 0.23.4 pd.read_csv(file, names=my_cols)працює, навіть якщо len(my_cols)менше поля в одному або декількох рядках. Додаткові поля просто відкидаються.
Luca Amerio

з пандами 0.25.3 не вдається, якщо якийсь стовпець довший за my_cols
Гена Кукарцев

16

Мені також було б цікаво дізнатись, чи можливо це, з документа, здається, це не так. Що ви, мабуть, могли б зробити, це прочитати файл, рядок за рядком, і об'єднати кожне читання в DataFrame:

import pandas as pd

df = pd.DataFrame()

with open(filepath, 'r') as f:
    for line in f:
        df = pd.concat( [df, pd.DataFrame([tuple(line.strip().split(','))])], ignore_index=True )

Це працює, але не найелегантнішим чином, я думаю ...


1

Гаразд. Не впевнений, наскільки це ефективно - але ось що я зробив. Хотілося б почути, чи є кращий спосіб це зробити. Дякую !

from pandas import DataFrame

list_of_dicts=[]
labels=['A','B','C','D','E']
for line in file:
    line=line.rstrip('\n')
    list_of_dicts.append(dict(zip(labels,line.split(','))))
frame=DataFrame(list_of_dicts)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.