pandas read_csv dan filter kolom dengan usecols

98

Saya memiliki file csv yang tidak masuk dengan benar pandas.read_csvketika saya memfilter kolom dengan usecolsdan menggunakan beberapa indeks.

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

Saya berharap bahwa df1 dan df2 harus sama kecuali untuk kolom dummy yang hilang, tetapi kolomnya salah label. Juga tanggal diurai sebagai tanggal.

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

Menggunakan nomor kolom daripada nama memberi saya masalah yang sama. Saya dapat mengatasi masalah ini dengan menghapus kolom boneka setelah langkah read_csv, tetapi saya mencoba memahami apa yang salah. Saya menggunakan panda 0.10.1.

edit: memperbaiki penggunaan header yang buruk.

chip
sumber
1
Hal lain, penggunaan kata kunci headerdan Anda namestidak benar (itulah sebabnya baris pertama hilang dalam contoh Anda. headerMengharapkan int (default 0) sebagai baris dengan tajuk. Karena Anda memberikan 'True' yang diartikan sebagai 1, baris kedua (baris data pertama) digunakan sebagai tajuk dan hilang. Namun nama kolom sudah benar karena Anda menimpanya dengan namesargumen. Namun Anda dapat membiarkannya dan baris pertama digunakan untuk nama kolom secara default. Namun, itu tidak menyelesaikan pertanyaan awal Anda.
joris
1
Sepertinya ini usecolsbug. Mungkin terkait dengan bug 2654 ?
abudis
bug masih ada tanpa argumen nama dan header, bagus ditemukan.
Andy Hayden
@andy saya akan menyodoknya sedikit lagi dan mengirimkannya ke bug pandas. Saya menghargai pemeriksaan kewarasan.
chip

Jawaban:

115

Jawaban oleh @chip sama sekali tidak memahami maksud dari dua argumen kata kunci.

  • nama hanya diperlukan jika tidak ada header dan Anda ingin menentukan argumen lain menggunakan nama kolom daripada indeks integer.
  • usecols seharusnya menyediakan filter sebelum membaca seluruh DataFrame ke dalam memori; jika digunakan dengan benar, tidak perlu menghapus kolom setelah membaca.

Solusi ini mengoreksi keanehan tersebut:

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

Yang memberi kita:

                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
sumber
1
Ini adalah solusi buku teks untuk mengurai data CSV, tetapi pada saat itu saya bermaksud menggunakan argumen nama karena data sebenarnya tidak memiliki header.
chip
2
Dalam hal ini, Anda tidak akan menentukan header=0. Anda ingin menggunakan header=Nonedan kemudian menggunakan namessebagai tambahan.
Mack
Tapi masih menggunakan usecolsindeks integer untuk kolom yang ingin dipertahankan @Mack?
Mr_and_Mrs_D
22

Kode ini mencapai apa yang Anda inginkan --- juga aneh dan pasti buggy:

Saya mengamati bahwa itu berhasil ketika:

a) Anda menentukan index_colrel. ke jumlah kolom yang benar-benar Anda gunakan - jadi tiga kolomnya dalam contoh ini, bukan empat (Anda berhenti dummydan mulai menghitung sejak saat itu)

b) sama untuk parse_dates

c) tidak demikian karena usecols;) untuk alasan yang jelas

d) di sini saya menyesuaikan namesuntuk mencerminkan perilaku ini

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

yang mencetak

                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
sumber
1
Terima kasih. Saya tidak pernah menemukan kombinasi yang tepat untuk mengatur ulang namesangka dan berdasarkan usecolssehingga datanya menjadi benar.
chip
8

Jika file csv Anda berisi data tambahan, kolom dapat dihapus dari DataFrame setelah impor.

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

Yang memberi kita:

                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
sumber
mengapa index_col menimbulkan masalah dalam kasus saya, saya mencoba menggunakan nama kolom seperti yang Anda sarankan, tetapi berhasil jika saya melewati nomor kolom.
YouAreAwesome
4
ini adalah pemborosan sumber daya namun
Mr_and_Mrs_D
1

Anda hanya perlu menambahkan index_col=Falseparameter

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
sumber
-4

impor csv terlebih dahulu dan gunakan csv.DictReader mudah untuk diproses ...

Mohan
sumber
2
Ini mungkin lebih mudah, tetapi juga sangat lambat. Saat Anda mengerjakan kumpulan data besar (saat ini saya sendiri sedang mengerjakan satu file CSV 13 GB), tidak perlu menunggu berjam-jam untuk memuat file menjadi jauh lebih penting.
Nama Palsu