2013-02-22 8 views
45

Mam plik CSV, który nie jest poprawnie wyświetlany z pandas.read_csv, gdy filtruję kolumny przy użyciu usecols i używam wielu indeksów.
pandy read_csv i kolumny filtrów z plikami użytkowymi

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', 
     index_col=["date", "loc"], 
     usecols=["dummy", "date", "loc", "x"], 
     parse_dates=["date"], 
     header=0, 
     names=["dummy", "date", "loc", "x"]) 
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 

Spodziewam się, że DF1 i df2 powinna być taka sama, z wyjątkiem brakującej manekina kolumny, ale kolumny przyjść błędnie. Również data jest przetwarzana jako data.

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 

Używanie numerów kolumn zamiast nazw daje mi ten sam problem. Mogę obejść ten problem, upuszczając kolumnę manekinową po kroku read_csv, ale próbuję zrozumieć, co jest nie tak. Używam pand 0.10.1.

edit: poprawiono złe użycie nagłówka.

+1

coś innego, swój korzystanie z 'header' i' names' słowo nie jest prawidłowe (dlatego w twoim przykładzie brakuje pierwszego wiersza. 'header' oczekuje wartości int (domyślnie 0) jako wiersza z nagłówkiem, ponieważ podajesz" True ", który jest interpretowany jako 1, drugi wiersz (pierwszy wiersz danych) jest używany jako nagłówek i brakuje. Jednak nazwy kolumn są poprawne, ponieważ nadpisujesz go argumentem "names". Ale możesz je zostawić, a pierwszy wiersz jest domyślnie używany dla nazw kolumn. Jednak to nie rozwiązuje początkowego pytania. – joris

+1

Wygląda to na błąd 'usecols'. Prawdopodobnie związane z [bug 2654] (https://github.com/pydata/pandas/issues/2654)? – abudis

+0

Błąd nadal istnieje bez nazw i argumentów nagłówka, dobre znalezisko. –

Odpowiedz

7

Jeśli plik CSV zawiera dodatkowe informacje, kolumny mogą być deleted z DataFrame po imporcie.

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'] 

co daje nam:

   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 
10

Kod ten osiąga co chcesz --- również jego dziwne i na pewno buggy:

I zauważył, że to działa, gdy:

a) określenie index_col rel. do liczby kolumn naprawdę wykorzystać - tak swoje trzy kolumny w tym przykładzie, nie cztery (upuszczenia dummy i rozpocząć liczenie od tego momentu)

b) takie same dla parse_dates

c) nie tak dla usecols ;) z oczywistych względów

d) Oto ja dostosował names lustro to zachowanie

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 

która drukuje

   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

Dzięki. Nigdy nie wymyśliłem właściwej kombinacji ponownego zestawiania "nazw" i liczb na podstawie "usecols", więc dane były poprawne. – chip

-3

import CSV pierwszy i używać csv.DictReader jej łatwo przetwarzać ...

+0

To może być łatwiejsze, ale jest również znacznie wolniejsze. Kiedy pracujesz nad dużymi zestawami danych (sam pracuję teraz z pojedynczym plikiem CSV o pojemności 13 GB), nie trzeba czekać godzinami na załadowanie pliku. –

41

Odpowiedź przez @chip całkowicie mija się z celem z dwoma argumentami słów kluczowych.

  • nazwy jest konieczne tylko gdy nie ma nagłówka i chcesz określić inne argumenty używając nazwy kolumn zamiast indeksów całkowitych.
  • usecols ma dostarczać filtr przed odczytaniem całej DataFrame do pamięci; jeśli jest używany prawidłowo, nigdy nie powinno być potrzeby usuwania kolumn po przeczytaniu.

Takie rozwiązanie poprawia te osobliwości:

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"]) 

co daje nam:

   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 
+0

To jest podręcznikowe rozwiązanie do analizowania danych CSV, ale w tym czasie miałem zamiar użyć argumentu * names *, ponieważ prawdziwe dane nie miały nagłówka. – chip

+0

W takim przypadku nie podano wartości 'header = 0'. Chciałbyś użyć 'header = None', a następnie dodatkowo użyć' names'. – Mack

Powiązane problemy