Umgang mit variabler Spaltenanzahl mit Pandas - Python

76

Ich habe einen Datensatz, der so aussieht (höchstens 5 Spalten - kann aber kleiner sein)

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

Ich versuche, pandas read_table zu verwenden, um dies in einen 5-Spalten-Datenrahmen einzulesen. Ich möchte dies ohne zusätzliche Massage einlesen.

Wenn ich es versuche

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

Ich erhalte die Fehlermeldung "Spaltennamen haben 5 Felder, Daten haben 3 Felder".

Gibt es eine Möglichkeit, Pandas dazu zu bringen, beim Lesen der Daten NaN für die fehlenden Spalten auszufüllen?

Jackie Shephard
quelle

Antworten:

80

Ein Weg, der zu funktionieren scheint (zumindest in 0.10.1 und 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

Beachten Sie, dass Sie bei diesem Ansatz den gewünschten Spalten Namen geben müssen. Nicht so allgemein wie einige andere Methoden, funktioniert aber gut genug, wenn es zutrifft.

DSM
quelle
2
Vielen Dank! Das hat funktioniert - die Engine = 'Python' scheint der Schlüssel zu sein. Durch Hinzufügen dieses Attributs funktionieren sowohl read_table als auch read_csv.
Jackie Shephard
2
Das scheint mir ziemlich kratzig zu sein. Hinzufügen eines Github-Problems: github.com/pydata/pandas/issues/2981
Wes McKinney
1
Was es für mich reparierte, war, names=my_colswo my_colsmindestens so lang war wie die Linie mit den meisten Feldern. Wenn die maximale Anzahl von Feldern nicht im Voraus bekannt ist, können Sie dynamisch extrahieren, indem Sie die Datei vorher über 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)) lesen. Der Nachteil ist jedoch, dass die Datei zweimal gelesen wird.
EliadL
mit Pandas Version 0.23.4 pd.read_csv(file, names=my_cols)funktioniert auch dann, wenn len(my_cols)die Anzahl der Felder in einer oder mehreren Zeilen geringer ist. Die zusätzlichen Felder werden einfach verworfen.
Luca Amerio
mit pandas 0.25.3 schlägt es fehl, wenn eine spalte länger als my_cols ist
Gena Kukartsev
15

Es würde mich auch interessieren, ob dies möglich ist. Aus dem Dokument geht hervor, dass dies nicht der Fall ist. Was Sie wahrscheinlich tun könnten, ist, die Datei Zeile für Zeile zu lesen und jeden Lesevorgang zu einem DataFrame zu verketten:

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 )

Es funktioniert aber nicht auf die eleganteste Art, denke ich ...

herrfz
quelle
1

OK. Ich bin mir nicht sicher, wie effizient das ist - aber hier ist, was ich getan habe. Würde gerne hören, ob es einen besseren Weg gibt, dies zu tun. Vielen Dank !

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)
Jackie Shephard
quelle