ti-enxame.com

pandas read_csv e filtrar colunas com usecols

Eu tenho um arquivo csv que não está vindo corretamente com pandas.read_csv quando eu filtrar as colunas com usecols e usar vários índices.

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

Espero que df1 e df2 sejam os mesmos, exceto pela coluna dummy faltante, mas as colunas vêm erradas. Além disso, a data está sendo analisada como uma 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

Usar números de coluna em vez de nomes me dá o mesmo problema. Eu posso resolver o problema, soltando a coluna fictícia após a etapa read_csv, mas estou tentando entender o que está errado. Eu estou usando pandas 0.10.1.

edit: fixou o uso incorreto do cabeçalho.

71
chip

A resposta de @chip perde completamente o ponto de dois argumentos de palavras-chave.

  • nomes é necessário apenas quando não há cabeçalho e você deseja especificar outros argumentos usando nomes de colunas em vez de índices inteiros.
  • secols deve fornecer um filtro antes de ler o DataFrame inteiro na memória; Se usado corretamente, nunca deve ser necessário excluir colunas após a leitura.

Esta solução corrige essas esquisitices:

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

O que nos dá:

                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
81
Mack

Este código atinge o que você quer - também é estranho e certamente bugs:

Eu observei que funciona quando:

a) você especifica o index_col rel. para o número de colunas que você realmente usa - então suas três colunas neste exemplo, não quatro (você solta dummy e começa a contar a partir de então)

b) mesmo para parse_dates

c) não é assim para usecols;) por razões óbvias

d) aqui eu adaptei o names para espelhar esse comportamento

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

que imprime

                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
20
Theodros Zelleke

Se o seu arquivo csv contiver dados extras, as colunas poderão ser excluídas do DataFrame após a importação.

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

O que nos dá:

                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
8
chip