Opções de read_csv low_memory e dtype do Pandas


320

Ao ligar

df = pd.read_csv('somefile.csv')

Eu recebo:

/Users/josh/anaconda/envs/py27/lib/python2.7/site-packages/pandas/io/parsers.py:1130: DtypeWarning: colunas (4,5,7,16) têm tipos mistos. Especifique a opção dtype na importação ou defina low_memory = False.

Por que a dtypeopção está relacionada low_memorye por que a Falseajudaria com esse problema?


2
Eu tenho uma pergunta sobre este aviso. O índice das colunas mencionadas é baseado em 0? Por exemplo, a coluna 4, que tem um tipo misto, é que df [:, 4] ou df [:, 3]
maziar 21/03/16

@maziar ao ler um csv, por padrão, um novo índice baseado em 0 é criado e usado.
Firelynx

Respostas:


432

A opção low_memory obsoleta

A low_memoryopção não foi descontinuada adequadamente, mas deveria ser, pois na verdade não faz nada de diferente [ fonte ]

A razão pela qual você recebe esse low_memoryaviso é porque adivinhar os tipos de cada coluna exige muita memória. O Pandas tenta determinar que tipo de tipo definir, analisando os dados em cada coluna.

Adivinhação de tipo (muito ruim)

O Pandas pode apenas determinar qual o tipo de coluna que uma coluna deve ter depois que todo o arquivo for lido. Isso significa que nada pode realmente ser analisado antes que o arquivo inteiro seja lido, a menos que você corra o risco de alterar o tipo dessa coluna quando ler o último valor.

Considere o exemplo de um arquivo que possui uma coluna chamada user_id. Ele contém 10 milhões de linhas em que o user_id é sempre números. Como os pandas não podem saber que são apenas números, provavelmente os manterão como as strings originais até ler o arquivo inteiro.

Especificando tipos (sempre deve ser feito)

adicionando

dtype={'user_id': int}

Ao fazer a pd.read_csv()chamada, os pandas saberão quando começar a ler o arquivo, que isso é apenas números inteiros.

Também digno de nota é que, se a última linha do arquivo tivesse sido "foobar"escrita na user_idcoluna, o carregamento seria interrompido se o dtype acima fosse especificado.

Exemplo de dados quebrados que quebram quando os tipos são definidos

import pandas as pd
try:
    from StringIO import StringIO
except ImportError:
    from io import StringIO


csvdata = """user_id,username
1,Alice
3,Bob
foobar,Caesar"""
sio = StringIO(csvdata)
pd.read_csv(sio, dtype={"user_id": int, "username": "string"})

ValueError: invalid literal for long() with base 10: 'foobar'

Normalmente, os dtypes são um problema, leia mais sobre eles aqui: http://docs.scipy.org/doc/numpy/reference/generated/numpy.dtype.html

Quais tipos existem?

Temos acesso a tipos numpy: float, int, bool, timedelta64 [ns] e datetime64 [ns]. Observe que os tipos de data / hora numpy não reconhecem o fuso horário.

O Pandas estende esse conjunto de tipos com seus próprios:

'datetime64 [ns,]' Que é um carimbo de data / hora com reconhecimento de fuso horário.

'categoria', que é essencialmente uma enumeração (cadeias representadas por chaves inteiras para salvar

'período []' Para não ser confundido com um intervalo de tempo, esses objetos são realmente ancorados a períodos específicos

'Esparso', 'Esparso [int]', 'Esparso [flutuante]' é para dados esparsos ou 'Dados com muitos buracos'. Em vez de salvar NaN ou Nenhum no quadro de dados, ele omite os objetos, economizando espaço .

'Intervalo' é um tópico próprio, mas seu principal uso é para indexação. Veja mais aqui

'Int8', 'Int16', 'Int32', 'Int64', 'UInt8', 'UInt16', 'UInt32', 'UInt64' são todos números inteiros específicos de pandas que são anuláveis, diferentemente da variante numpy.

'string' é um dtype específico para trabalhar com dados de string e fornece acesso ao .stratributo na série.

'boolean' é como o numpy 'bool', mas também suporta dados ausentes.

Leia a referência completa aqui:

Referência de tipo de pandas

Pegadinhas, ressalvas, notas

A configuração dtype=objectsilenciará o aviso acima, mas não o tornará mais eficiente em memória, apenas processará se houver alguma coisa.

A configuração dtype=unicodenão fará nada, pois, para numpy, a unicodeé representado como object.

Uso de conversores

@sparrow indica corretamente o uso de conversores para evitar que os pandas explodam ao encontrar 'foobar'em uma coluna especificada como int. Gostaria de acrescentar que os conversores são realmente pesados ​​e ineficientes para uso em pandas e devem ser usados ​​como último recurso. Isso ocorre porque o processo read_csv é um processo único.

Os arquivos CSV podem ser processados ​​linha a linha e, portanto, podem ser processados ​​por vários conversores em paralelo com mais eficiência, simplesmente cortando o arquivo em segmentos e executando vários processos, algo que o pandas não suporta. Mas esta é uma história diferente.


6
Portanto, considerando que definir a dtype=objectnão é mais eficiente em termos de memória, há alguma razão para mexer com isso além de se livrar do erro?
Zthomas.nc 31/08/16

6
@ zthomas.nc sim, o Pandas não precisa se preocupar em testar o que está na coluna. Teoricamente salvar alguma memória durante o carregamento (mas nenhum após o carregamento está completo) e, teoricamente, poupando alguns ciclos de CPU (que você não vai notar desde o disco I / O vai ser o gargalo.
firelynx

5
"Também vale a pena notar que, se a última linha do arquivo tiver" foobar "gravado na coluna user_id, o carregamento será interrompido se o dtype acima for especificado." existe alguma opção "coagir" que poderia ser usada para jogar fora essa linha em vez de falhar?
pardal

5
@ pardal pode haver, mas da última vez que o usei, havia bugs. Pode ser corrigido na versão mais recente do pandas. error_bad_lines=False, warn_bad_lines=Truedeve fazer o truque. A documentação diz que é válida apenas com o analisador C. Ele também diz que o analisador padrão é Nenhum, o que dificulta saber qual é o padrão.
firelynx 02/09

5
@nealmcb Você pode ler o quadro de dados nrows=100como argumento e, em seguida, df.dtypesver os tipos que obtém. No entanto, ao ler todo o quadro de dados com esses tipos, certifique-se de fazer um try/exceptprocedimento para detectar palpites de tipos defeituosos. Os dados estão sujos, você sabe.
firelynx

50

Experimentar:

dashboard_df = pd.read_csv(p_file, sep=',', error_bad_lines=False, index_col=False, dtype='unicode')

De acordo com a documentação dos pandas:

dtype: Digite o nome ou o ditado da coluna -> tipo

Quanto a low_memory, é True por padrão e ainda não está documentado. Eu não acho que seja relevante. A mensagem de erro é genérica, portanto você não precisa mexer com a memória baixa de qualquer maneira. Espero que isso ajude e deixe-me saber se você tiver mais problemas


1
Adicionando dtype=unicodeproduzido: NameError: name 'unicode' is not defined. Mas colocar unicodeaspas (como em 'unicode') parece funcionar!
sedeh

5
@sedeh Você pode especificar dtypes como tipos de python ou como numpy.dtype('unicode'). Quando você atribui à opção dtype uma string, ela tenta convertê-la na numpy.dtype()fábrica por padrão. A especificação 'unicode'não fará nada, os unicodes são apenas otimizados objects. Você receberádtype='object'
firelynx

43
df = pd.read_csv('somefile.csv', low_memory=False)

Isso deve resolver o problema. Recebi exatamente o mesmo erro ao ler 1,8 milhão de linhas de um CSV.


51
Isso silencia o erro, mas na verdade não altera mais nada.
firelynx

2
Tenho mesmo problema durante a execução 1.5GB arquivo de dados
Sitz Blogz

18

Conforme mencionado anteriormente pelo firelynx, se o dtype for especificado explicitamente e houver dados mistos que não sejam compatíveis com esse tipo, o carregamento será interrompido. Usei um conversor como este como solução alternativa para alterar os valores com tipo de dados incompatível, para que os dados ainda pudessem ser carregados.

def conv(val):
    if not val:
        return 0    
    try:
        return np.float64(val)
    except:        
        return np.float64(0)

df = pd.read_csv(csv_file,converters={'COL_A':conv,'COL_B':conv})

2

Eu tive um problema semelhante com um arquivo de ~ 400 MB. Definir low_memory=Falsefez o truque para mim. Faça as coisas simples primeiro, eu verificaria se o seu quadro de dados não é maior que a memória do sistema, reinicie, limpe a RAM antes de continuar. Se você ainda estiver com erros, vale a pena garantir que seu .csvarquivo esteja correto, dê uma olhada rápida no Excel e verifique se não há corrupção óbvia. Dados originais quebrados podem causar estragos ...


1

Eu estava enfrentando um problema semelhante ao processar um enorme arquivo csv (6 milhões de linhas). Eu tive três problemas: 1. o arquivo continha caracteres estranhos (corrigidos usando a codificação) 2. o tipo de dados não foi especificado (corrigido usando a propriedade dtype) definido com base no nome do arquivo (corrigido usando try .. exceto ..)

df = pd.read_csv(csv_file,sep=';', encoding = 'ISO-8859-1',
                 names=['permission','owner_name','group_name','size','ctime','mtime','atime','filename','full_filename'],
                 dtype={'permission':str,'owner_name':str,'group_name':str,'size':str,'ctime':object,'mtime':object,'atime':object,'filename':str,'full_filename':str,'first_date':object,'last_date':object})

try:
    df['file_format'] = [Path(f).suffix[1:] for f in df.filename.tolist()]
except:
    df['file_format'] = ''

-1

Funcionou para mim low_memory = Falsedurante a importação de um DataFrame. Essa é toda a mudança que funcionou para mim:

df = pd.read_csv('export4_16.csv',low_memory=False)
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.