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.


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

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

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

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

-4

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


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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.