Converter carros alegóricos em polegadas em Pandas?


230

Eu tenho trabalhado com dados importados de um CSV. O Pandas mudou algumas colunas para flutuar, agora os números nessas colunas são exibidos como pontos flutuantes! No entanto, preciso que eles sejam exibidos como números inteiros ou sem vírgula. Existe uma maneira de convertê-los em números inteiros ou não exibir a vírgula?


22
Você pode mudar o tipo (desde que não existem valores em falta)df.col = df.col.astype(int)
EdChum

Esta questão é duas perguntas ao mesmo tempo, e o título dessa pergunta reflete apenas uma delas.
Monica Heddneck 15/07

Para pessoas que atingiram o que precede e que consideram útil no conceito, mas não estão funcionando para você, esta é a versão que funcionou para mim no python 3.7.5 com pandas X:df = df.astype(int)
Oliver.R

Respostas:


217

Para modificar a saída flutuante, faça o seguinte:

df= pd.DataFrame(range(5), columns=['a'])
df.a = df.a.astype(float)
df

Out[33]:

          a
0 0.0000000
1 1.0000000
2 2.0000000
3 3.0000000
4 4.0000000

pd.options.display.float_format = '{:,.0f}'.format
df

Out[35]:

   a
0  0
1  1
2  2
3  3
4  4

16
Obrigado! Ajustei isso no meu to_csv: fin.to_csv ('minha_tabela.csv', float_format = '%. F'). Funcionou!
MJP 22/01

4
Na última versão de pandas que você precisa para acrescentar cópia = False aos argumentos de astype para evitar um aviso
g.stevo

Isso é necessário df.a = df.a.astype(float)? Isso faz uma cópia (não sabe como o copyparâmetro astype()é usado)? Enfim, para atualizar o tipo "in place"?
Mr_and_Mrs_D

1
@ EdChum, existe uma maneira de impedir o Pandas de converter tipos para começar? Por exemplo, tente DF.({'200': {'#': 354, '%': 0.9971830985915493}, '302': {'#': 1, '%': 0.0028169014084507044}}) Observe que o # é convertido em flutuante e são linhas, não colunas. porque cada um é um Seriesque pode armazenar apenas um único tipo uniforme?
Alancalvitti 06/06/19

@alancalvitti qual é a sua intenção aqui de preservar os valores ou o dtype? Se for dtype, então você precisa para criar as colunas de dtype objectmodo que permite mista, caso contrário, o meu conselho seria para uso apenas flutuar e quando as comparações que fazem usonp.isclose
EdChum

180

Use a pandas.DataFrame.astype(<type>)função para manipular tipos de coluna.

>>> df = pd.DataFrame(np.random.rand(3,4), columns=list("ABCD"))
>>> df
          A         B         C         D
0  0.542447  0.949988  0.669239  0.879887
1  0.068542  0.757775  0.891903  0.384542
2  0.021274  0.587504  0.180426  0.574300
>>> df[list("ABCD")] = df[list("ABCD")].astype(int)
>>> df
   A  B  C  D
0  0  0  0  0
1  0  0  0  0
2  0  0  0  0

EDITAR:

Para lidar com valores ausentes:

>>> df
          A         B     C         D
0  0.475103  0.355453  0.66  0.869336
1  0.260395  0.200287   NaN  0.617024
2  0.517692  0.735613  0.18  0.657106
>>> df[list("ABCD")] = df[list("ABCD")].fillna(0.0).astype(int)
>>> df
   A  B  C  D
0  0  0  0  0
1  0  0  0  0
2  0  0  0  0

3
Eu tentei a sua abordagem e ele me dá um ValueError: Não é possível converter NA para inteiro
MJP

6
@MJP Você não pode converter série de float para inteiro, se houver valores ausentes ver pandas.pydata.org/pandas-docs/stable/... , você tem que usar carros alegóricos
EdChum

2
Os valores não estão ausentes, mas a coluna não especifica um valor para cada linha de propósito. Existe alguma maneira de obter uma solução alternativa? Como esses valores são IDs de chave estrangeira, preciso de ints.
MJP 22/01

4
Fiz uma edição na qual todos os NaN são substituídos por 0,0.
Ryan G

3
Ou melhor ainda, se você estiver apenas modificando um CSV, então: df.to_csv ("path.csv", na_rep = "", float_format = "%. 0f", index = False) Mas isso editará todos os carros alegóricos, então pode ser melhor converter sua coluna FK em uma sequência, fazer a manipulação e salvar.
Ryan G

44

Considerando o seguinte quadro de dados:

>>> df = pd.DataFrame(10*np.random.rand(3, 4), columns=list("ABCD"))
>>> print(df)
...           A         B         C         D
... 0  8.362940  0.354027  1.916283  6.226750
... 1  1.988232  9.003545  9.277504  8.522808
... 2  1.141432  4.935593  2.700118  7.739108

Usando uma lista de nomes de colunas, altere o tipo para várias colunas com applymap():

>>> cols = ['A', 'B']
>>> df[cols] = df[cols].applymap(np.int64)
>>> print(df)
...    A  B         C         D
... 0  8  0  1.916283  6.226750
... 1  1  9  9.277504  8.522808
... 2  1  4  2.700118  7.739108

Ou para uma única coluna com apply():

>>> df['C'] = df['C'].apply(np.int64)
>>> print(df)
...    A  B  C         D
... 0  8  0  1  6.226750
... 1  1  9  9  8.522808
... 2  1  4  2  7.739108

5
E se houver um NaN no valor?
Zhang18

3
@ Zhang18 Tentei esta solução e, no caso de NaN, você tem este erro:ValueError: ('cannot convert float NaN to integer', u'occurred at index <column_name>')
enri

2
@enri: Pode tentar o seguinte código -df['C'] = df['C'].dropna().apply(np.int64)
vsdaking

12

Esta é uma solução rápida, caso você deseje converter mais colunas do seu pandas.DataFramefloat para inteiro, considerando também o caso em que você pode ter valores de NaN.

cols = ['col_1', 'col_2', 'col_3', 'col_4']
for col in cols:
   df[col] = df[col].apply(lambda x: int(x) if x == x else "")

Eu tentei com else x)e else None), mas o resultado ainda está tendo o número flutuante, então usei else "".


ele aplicará o ""a todos os valores emcol
Raheel

Ele aplicará a cadeia vazia ("") a todos os valores ausentes, se for o que for necessário, mas o restante dos valores será inteiro.
Krzysztof Słowiński 15/03/19

Obrigado por isso. Isso funcionou quando .astype () e .apply (np.int64) não.
Alison S

Isso parece hacky, e não vejo razão para usá-lo entre as muitas alternativas disponíveis.
AMC

8

Ao expandir o uso mencionado do pandas.DataFrame.astype(<type>)método por @Ryan G , pode-se usar o errors=ignoreargumento para converter apenas as colunas que não produzem um erro, o que simplifica notavelmente a sintaxe. Obviamente, deve-se ter cuidado ao ignorar erros, mas para esta tarefa é muito útil.

>>> df = pd.DataFrame(np.random.rand(3, 4), columns=list('ABCD'))
>>> df *= 10
>>> print(df)
...           A       B       C       D
... 0   2.16861 8.34139 1.83434 6.91706
... 1   5.85938 9.71712 5.53371 4.26542
... 2   0.50112 4.06725 1.99795 4.75698

>>> df['E'] = list('XYZ')
>>> df.astype(int, errors='ignore')
>>> print(df)
...     A   B   C   D   E
... 0   2   8   1   6   X
... 1   5   9   5   4   Y
... 2   0   4   1   4   Z

Dos documentos do pandas.DataFrame.astype :

erros: {'aumentar', 'ignorar'}, padrão 'aumentar'

Controle a criação de exceções em dados inválidos para o tipo de dado fornecido.

  • raise: permite que exceções sejam levantadas
  • ignorar: suprimir exceções. Em caso de erro, retorne o objeto original

Novo na versão 0.20.0.


7
>>> import pandas as pd
>>> right = pd.DataFrame({'C': [1.002, 2.003], 'D': [1.009, 4.55], 'key': ['K0', 'K1']})
>>> print(right)
           C      D key
    0  1.002  1.009  K0
    1  2.003  4.550  K1
>>> right['C'] = right.C.astype(int)
>>> print(right)
       C      D key
    0  1  1.009  K0
    1  2  4.550  K1

5

Para converter todas as colunas flutuantes em int

>>> df = pd.DataFrame(np.random.rand(5, 4) * 10, columns=list('PQRS'))
>>> print(df)
...     P           Q           R           S
... 0   4.395994    0.844292    8.543430    1.933934
... 1   0.311974    9.519054    6.171577    3.859993
... 2   2.056797    0.836150    5.270513    3.224497
... 3   3.919300    8.562298    6.852941    1.415992
... 4   9.958550    9.013425    8.703142    3.588733

>>> float_col = df.select_dtypes(include=['float64']) # This will select float columns only
>>> # list(float_col.columns.values)
>>> for col in float_col.columns.values:
...     df[col] = df[col].astype('int64')
>>> print(df)
...     P   Q   R   S
... 0   4   0   8   1
... 1   0   9   6   3
... 2   2   0   5   3
... 3   3   8   6   1
... 4   9   9   8   3

0

Aqui está uma função simples que fará o downcast flutuar no menor número inteiro possível que não perca nenhuma informação. Por exemplo,

  • 100.0 pode ser convertido de float para inteiro, mas 99.9 não (sem perder informações para arredondamento ou truncamento)

  • Além disso, a 1.0 pode ser baixada até o fim int8sem perder informações, mas o menor número inteiro para 100_000.0 éint32

Exemplos de código:

import numpy as np
import pandas as pd

def float_to_int( s ):
    if ( s.astype(np.int64) == s ).all():
        return pd.to_numeric( s, downcast='integer' )
    else:
        return s

# small integers are downcast into 8-bit integers
float_to_int( np.array([1.0,2.0]) )
Out[1]:array([1, 2], dtype=int8)

# larger integers are downcast into larger integer types
float_to_int( np.array([100_000.,200_000.]) )
Out[2]: array([100000, 200000], dtype=int32)

# if there are values to the right of the decimal
# point, no conversion is made
float_to_int( np.array([1.1,2.2]) )
Out[3]: array([ 1.1,  2.2])

0

As colunas que precisam ser convertidas para int podem ser mencionadas em um dicionário também como abaixo

df = df.astype({'col1': 'int', 'col2': 'int', 'col3': 'int'})

-5
>>> df_18['cyl'].value_counts()
... 4.0     365
... 6.0     246
... 8.0     153

>>> df_18['cyl'] = df_18['cyl'].astype(int)
>>> df_18['cyl'].value_counts()
... 4     365
... 6     246
... 8     153

1
astype(int)já foi mencionado várias vezes. Esta resposta não adiciona nada de novo.
Georgy
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.