pandas read_csv e colunas de filtro com usecols


97

Tenho um arquivo csv que não está chegando corretamente pandas.read_csvquando filtro as colunas usecolse uso 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 iguais, exceto pela coluna fictícia ausente, mas as colunas vêm com rótulos incorretos. 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. Posso contornar o problema eliminando a coluna fictícia após a etapa read_csv, mas estou tentando entender o que está errado. Estou usando o pandas 0.10.1.

editar: corrigido o uso incorreto do cabeçalho.


1
Outra coisa, o uso das palavras-chave headere namesnão está correto (é por isso que a primeira linha está faltando em seu exemplo. headerEspera um int (padrão 0) como a linha com o cabeçalho. Porque você fornece "Verdadeiro", que é interpretado como 1, a segunda linha (primeira linha de dados) é usada como cabeçalho e está ausente. No entanto, os nomes das colunas estão corretos porque você os sobrescreveu com o namesargumento. Mas você pode deixá-los e a primeira linha é usada para os nomes das colunas por padrão. No entanto, isso não resolve sua pergunta inicial.
joris

1
Isso parece um usecolsbug. Possivelmente relacionado ao bug 2654 ?
abudis

bug ainda está lá sem nomes e argumentos de cabeçalho, bom achado.
Andy Hayden

@andy vou cutucar um pouco mais e enviar para os bugs dos pandas. Agradeço a verificação de sanidade.
chip de

Respostas:


113

A resposta de @chip ignora completamente o objetivo de dois argumentos de palavra-chave.

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

Esta solução corrige essas estranhezas:

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

1
Esta é a solução de livro para analisar os dados CSV, mas na época eu pretendia usar o argumento names porque os dados reais não tinham cabeçalho.
chip de

2
Nesse caso, você não especificaria header=0. Você gostaria de usar header=Nonee usar namesalém disso.
Mack

Mas ainda usar usecolscom índices inteiros para as colunas que se deseja manter @Mack?
Mr_and_Mrs_D

22

Este código atinge o que você deseja --- também é estranho e certamente cheio de erros:

Observei que funciona quando:

a) você especifica o index_colrel. para o número de colunas que você realmente usa - então são três colunas neste exemplo, não quatro (você descarta dummye começa a contar a partir de então)

b) mesmo para parse_dates

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

d) aqui adaptei o namespara espelhar este 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

quais impressões

                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
Obrigado. Eu nunca descobri a combinação certa de reorganizar os namesnúmeros e com base em usecolspara que os dados viessem corretos.
chip de

8

Se o seu arquivo csv contiver dados extras, as colunas podem 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

porque o index_col está criando problema no meu caso, tentei usar o nome da coluna como você sugeriu, mas funcionou se eu passasse o número da coluna.
YouAreAwesome,

4
no entanto, isso é um desperdício de recursos
Mr_and_Mrs_D

0

Você tem que apenas adicionar o index_col=Falseparâmetro

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

importe o csv primeiro e use o csv.DictReader, é fácil de processar ...


2
Isso pode ser mais fácil, mas também é muito mais lento. Quando você está trabalhando em grandes conjuntos de dados (atualmente estou trabalhando com um único arquivo CSV de 13 GB), não ter que esperar horas para o arquivo carregar torna-se muito mais importante.
Nome falso de
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.