pandas read_csv und filtern spalten mit usecols

96

Ich habe eine CSV-Datei, die nicht richtig eingeht, pandas.read_csvwenn ich die Spalten mit usecolsfiltere und mehrere Indizes verwende.

import pandas as pd
csv = r"""dummy,date,loc,x
   bar,20090101,a,1
   bar,20090102,a,3
   bar,20090103,a,5
   bar,20090101,b,1
   bar,20090102,b,3
   bar,20090103,b,5"""

f = open('foo.csv', 'w')
f.write(csv)
f.close()

df1 = pd.read_csv('foo.csv',
        header=0,
        names=["dummy", "date", "loc", "x"], 
        index_col=["date", "loc"], 
        usecols=["dummy", "date", "loc", "x"],
        parse_dates=["date"])
print df1

# Ignore the dummy columns
df2 = pd.read_csv('foo.csv', 
        index_col=["date", "loc"], 
        usecols=["date", "loc", "x"], # <----------- Changed
        parse_dates=["date"],
        header=0,
        names=["dummy", "date", "loc", "x"])
print df2

Ich gehe davon aus, dass df1 und df2 bis auf die fehlende Dummy-Spalte identisch sein sollten, aber die Spalten sind falsch beschriftet. Auch das Datum wird als Datum analysiert.

In [118]: %run test.py
               dummy  x
date       loc
2009-01-01 a     bar  1
2009-01-02 a     bar  3
2009-01-03 a     bar  5
2009-01-01 b     bar  1
2009-01-02 b     bar  3
2009-01-03 b     bar  5
              date
date loc
a    1    20090101
     3    20090102
     5    20090103
b    1    20090101
     3    20090102
     5    20090103

Die Verwendung von Spaltennummern anstelle von Namen gibt mir das gleiche Problem. Ich kann das Problem umgehen, indem ich die Dummy-Spalte nach dem Schritt read_csv lösche, aber ich versuche zu verstehen, was falsch läuft. Ich benutze Pandas 0.10.1.

Bearbeiten: Fehlerhafte Header-Verwendung behoben.

Chip
quelle
1
Außerdem ist Ihre Verwendung der Schlüsselwörter headerund namesnicht korrekt (aus diesem Grund fehlt in Ihrem Beispiel die erste Zeile. headerErwartet ein int (Standard 0) als Zeile mit der Kopfzeile. Da Sie 'True' angeben, das als 1 interpretiert wird, Die zweite Zeile (erste Datenzeile) wird als Kopfzeile verwendet und fehlt. Die Spaltennamen sind jedoch korrekt, da Sie sie mit dem namesArgument überschreiben . Sie können sie jedoch beide belassen und die erste Zeile wird standardmäßig für die Spaltennamen verwendet. Es löst jedoch nicht Ihre anfängliche Frage.
Joris
1
Das sieht aus wie ein usecolsFehler. Möglicherweise im Zusammenhang mit Fehler 2654 ?
Abudis
Fehler ist immer noch da ohne Namen und Header-Argumente, guter Fund.
Andy Hayden
@andy Ich werde ein bisschen mehr darüber stöbern und es den Pandas Bugs vorlegen. Ich schätze die Überprüfung der geistigen Gesundheit.
Chip

Antworten:

110

Die Antwort von @chip verfehlt den Punkt zweier Schlüsselwortargumente vollständig.

  • Namen sind nur erforderlich, wenn kein Header vorhanden ist und Sie andere Argumente mithilfe von Spaltennamen anstelle von Ganzzahlindizes angeben möchten.
  • usecols soll einen Filter bereitstellen, bevor der gesamte DataFrame in den Speicher eingelesen wird. Bei ordnungsgemäßer Verwendung sollte es niemals erforderlich sein, Spalten nach dem Lesen zu löschen.

Diese Lösung korrigiert diese Kuriositäten:

import pandas as pd
from StringIO import StringIO

csv = r"""dummy,date,loc,x
bar,20090101,a,1
bar,20090102,a,3
bar,20090103,a,5
bar,20090101,b,1
bar,20090102,b,3
bar,20090103,b,5"""

df = pd.read_csv(StringIO(csv),
        header=0,
        index_col=["date", "loc"], 
        usecols=["date", "loc", "x"],
        parse_dates=["date"])

Was uns gibt:

                x
date       loc
2009-01-01 a    1
2009-01-02 a    3
2009-01-03 a    5
2009-01-01 b    1
2009-01-02 b    3
2009-01-03 b    5
Mack
quelle
1
Dies ist die Lehrbuchlösung zum Parsen der CSV-Daten, aber zu der Zeit wollte ich das Argument names verwenden , da die realen Daten keinen Header hatten.
Chip
2
In diesem Fall würden Sie nicht angeben header=0. Sie möchten verwenden header=Noneund dann nameszusätzlich verwenden.
Mack
Aber immer noch usecolsmit ganzzahligen Indizes für die Spalten verwenden, die man @Mack behalten möchte?
Mr_and_Mrs_D
22

Dieser Code erreicht, was Sie wollen - auch sein seltsamer und sicherlich fehlerhafter:

Ich habe festgestellt, dass es funktioniert, wenn:

a) Sie geben die index_colrel. auf die Anzahl der Spalten, die Sie wirklich verwenden - also die drei Spalten in diesem Beispiel, nicht vier (Sie löschen dummyund beginnen von da an zu zählen)

b) Gleiches für parse_dates

c) nicht so für usecols;) aus offensichtlichen Gründen

d) hier habe ich das angepasst, namesum dieses Verhalten widerzuspiegeln

import pandas as pd
from StringIO import StringIO

csv = """dummy,date,loc,x
bar,20090101,a,1
bar,20090102,a,3
bar,20090103,a,5
bar,20090101,b,1
bar,20090102,b,3
bar,20090103,b,5
"""

df = pd.read_csv(StringIO(csv),
        index_col=[0,1],
        usecols=[1,2,3], 
        parse_dates=[0],
        header=0,
        names=["date", "loc", "", "x"])

print df

welche druckt

                x
date       loc   
2009-01-01 a    1
2009-01-02 a    3
2009-01-03 a    5
2009-01-01 b    1
2009-01-02 b    3
2009-01-03 b    5
Theodros Zelleke
quelle
1
Vielen Dank. Ich habe nie die richtige Kombination aus Neuanordnung der namesund Zahlen basierend darauf gefunden, usecolsdamit die Daten korrekt eingehen.
Chip
8

Wenn Ihre CSV-Datei zusätzliche Daten enthält, können Spalten nach dem Import aus dem DataFrame gelöscht werden .

import pandas as pd
from StringIO import StringIO

csv = r"""dummy,date,loc,x
bar,20090101,a,1
bar,20090102,a,3
bar,20090103,a,5
bar,20090101,b,1
bar,20090102,b,3
bar,20090103,b,5"""

df = pd.read_csv(StringIO(csv),
        index_col=["date", "loc"], 
        usecols=["dummy", "date", "loc", "x"],
        parse_dates=["date"],
        header=0,
        names=["dummy", "date", "loc", "x"])
del df['dummy']

Was uns gibt:

                x
date       loc
2009-01-01 a    1
2009-01-02 a    3
2009-01-03 a    5
2009-01-01 b    1
2009-01-02 b    3
2009-01-03 b    5
Chip
quelle
Warum das index_col in meinem Fall ein Problem verursacht, habe ich versucht, den von Ihnen vorgeschlagenen Spaltennamen zu verwenden, aber es hat funktioniert, wenn ich die Spaltennummer übergeben habe.
YouAreAwesome
3
Dies ist jedoch eine Verschwendung von Ressourcen
Mr_and_Mrs_D
0

Sie müssen nur den index_col=FalseParameter hinzufügen

df1 = pd.read_csv('foo.csv',
     header=0,
     index_col=False,
     names=["dummy", "date", "loc", "x"], 
     index_col=["date", "loc"], 
     usecols=["dummy", "date", "loc", "x"],
     parse_dates=["date"])
  print df1
Auday Berro
quelle
-4

Importieren Sie zuerst CSV und verwenden Sie CSV.DictReader. Es ist einfach zu verarbeiten ...

Mohan
quelle
2
Das mag einfacher sein, ist aber auch massiv langsamer. Wenn Sie an großen Datenmengen arbeiten (ich arbeite derzeit selbst mit einer einzelnen 13-GB-CSV-Datei), wird es viel wichtiger, nicht stundenlang auf das Laden der Datei warten zu müssen.
Gefälschter Name