Você tem três opções principais para converter tipos em pandas:
to_numeric()
- fornece funcionalidade para converter com segurança tipos não numéricos (por exemplo, strings) em um tipo numérico adequado. (Veja também to_datetime()
e to_timedelta()
.)
astype()
- converta (quase) qualquer tipo para (quase) qualquer outro tipo (mesmo que não seja necessariamente sensato fazê-lo). Também permite converter para tipos categoriais (muito útil).
infer_objects()
- um método utilitário para converter colunas de objetos contendo objetos Python em um tipo de panda, se possível.
Continue lendo para obter explicações mais detalhadas e o uso de cada um desses métodos.
1 to_numeric()
A melhor maneira de converter uma ou mais colunas de um DataFrame em valores numéricos é usar pandas.to_numeric()
.
Esta função tentará alterar objetos não numéricos (como seqüências de caracteres) em números inteiros ou números de ponto flutuante, conforme apropriado.
Uso básico
A entrada para to_numeric()
é uma série ou uma única coluna de um DataFrame.
>>> s = pd.Series(["8", 6, "7.5", 3, "0.9"]) # mixed string and numeric values
>>> s
0 8
1 6
2 7.5
3 3
4 0.9
dtype: object
>>> pd.to_numeric(s) # convert everything to float values
0 8.0
1 6.0
2 7.5
3 3.0
4 0.9
dtype: float64
Como você pode ver, uma nova série é retornada. Lembre-se de atribuir esta saída a um nome de variável ou coluna para continuar usando:
# convert Series
my_series = pd.to_numeric(my_series)
# convert column "a" of a DataFrame
df["a"] = pd.to_numeric(df["a"])
Você também pode usá-lo para converter várias colunas de um DataFrame por meio do apply()
método:
# convert all columns of DataFrame
df = df.apply(pd.to_numeric) # convert all columns of DataFrame
# convert just columns "a" and "b"
df[["a", "b"]] = df[["a", "b"]].apply(pd.to_numeric)
Desde que todos os seus valores possam ser convertidos, é provavelmente tudo o que você precisa.
Manipulação de erros
Mas e se alguns valores não puderem ser convertidos em um tipo numérico?
to_numeric()
também usa um errors
argumento de palavra - chave que permite forçar a inclusão de valores não numéricos NaN
ou simplesmente ignorar as colunas que contêm esses valores.
Aqui está um exemplo usando uma série de strings s
que possui o objeto dtype:
>>> s = pd.Series(['1', '2', '4.7', 'pandas', '10'])
>>> s
0 1
1 2
2 4.7
3 pandas
4 10
dtype: object
O comportamento padrão é aumentar se não puder converter um valor. Nesse caso, ele não pode lidar com a string 'pandas':
>>> pd.to_numeric(s) # or pd.to_numeric(s, errors='raise')
ValueError: Unable to parse string
Em vez de falhar, podemos querer que 'pandas' sejam considerados um valor numérico ausente / ruim. Podemos coagir valores inválidos da NaN
seguinte maneira usando o errors
argumento de palavra - chave:
>>> pd.to_numeric(s, errors='coerce')
0 1.0
1 2.0
2 4.7
3 NaN
4 10.0
dtype: float64
A terceira opção para errors
é apenas ignorar a operação se um valor inválido for encontrado:
>>> pd.to_numeric(s, errors='ignore')
# the original Series is returned untouched
Essa última opção é particularmente útil quando você deseja converter todo o seu DataFrame, mas não sabe quais de nossas colunas podem ser convertidas de maneira confiável em um tipo numérico. Nesse caso, basta escrever:
df.apply(pd.to_numeric, errors='ignore')
A função será aplicada a cada coluna do DataFrame. As colunas que podem ser convertidas em um tipo numérico serão convertidas, enquanto as colunas que não puderem (por exemplo, que contêm strings ou datas que não sejam dígitos) serão deixadas em paz.
Downcasting
Por padrão, a conversão com to_numeric()
fornecerá um int64
oufloat64
dtype (ou qualquer largura inteira nativa da sua plataforma).
Isso é geralmente o que você deseja, mas e se você quiser economizar um pouco de memória e usar um tipo mais compacto, como float32
ouint8
?
to_numeric()
oferece a opção de fazer downcast para 'número inteiro', 'assinado', 'não assinado', 'flutuante'. Aqui está um exemplo para uma série simples s
de tipo inteiro:
>>> s = pd.Series([1, 2, -7])
>>> s
0 1
1 2
2 -7
dtype: int64
Downcasting para 'número inteiro' usa o menor número possível possível que pode conter os valores:
>>> pd.to_numeric(s, downcast='integer')
0 1
1 2
2 -7
dtype: int8
O downcasting para 'float' escolhe de maneira semelhante um tipo flutuante menor que o normal:
>>> pd.to_numeric(s, downcast='float')
0 1.0
1 2.0
2 -7.0
dtype: float32
2) astype()
O astype()
método permite que você seja explícito sobre o tipo que você deseja que seu DataFrame ou Series tenha. É muito versátil, pois você pode tentar ir de um tipo para outro.
Uso básico
Basta escolher um tipo: você pode usar um tipo NumPy (por exemplo np.int16
), alguns tipos Python (por exemplo, bool) ou tipos específicos de pandas (como o tipo categórico).
Chame o método no objeto que você deseja converter e astype()
tentará convertê-lo para você:
# convert all DataFrame columns to the int64 dtype
df = df.astype(int)
# convert column "a" to int64 dtype and "b" to complex type
df = df.astype({"a": int, "b": complex})
# convert Series to float16 type
s = s.astype(np.float16)
# convert Series to Python strings
s = s.astype(str)
# convert Series to categorical type - see docs for more details
s = s.astype('category')
Observe que eu disse "tente" - se astype()
não souber converter um valor na série ou no DataFrame, isso gerará um erro. Por exemplo, se você tiver um valor NaN
ou, inf
receberá um erro ao tentar convertê-lo em um número inteiro.
No pandas 0.20.0, esse erro pode ser suprimido passando errors='ignore'
. Seu objeto original será devolvido intocado.
Seja cuidadoso
astype()
é poderoso, mas às vezes converte valores "incorretamente". Por exemplo:
>>> s = pd.Series([1, 2, -7])
>>> s
0 1
1 2
2 -7
dtype: int64
Estes são números inteiros pequenos. Então, que tal converter para um tipo de 8 bits não assinado para economizar memória?
>>> s.astype(np.uint8)
0 1
1 2
2 249
dtype: uint8
A conversão funcionou, mas o -7 foi arredondado para se tornar 249 (ou seja, 2 8 - 7)!
Tentar fazer o downcast usando pd.to_numeric(s, downcast='unsigned')
pode ajudar a evitar esse erro.
3) infer_objects()
A versão 0.21.0 do pandas introduziu o método infer_objects()
para converter colunas de um DataFrame que possuem um tipo de dados de objeto em um tipo mais específico (conversões flexíveis).
Por exemplo, aqui está um DataFrame com duas colunas do tipo de objeto. Um contém inteiros reais e o outro contém cadeias que representam números inteiros:
>>> df = pd.DataFrame({'a': [7, 1, 5], 'b': ['3','2','1']}, dtype='object')
>>> df.dtypes
a object
b object
dtype: object
Usando infer_objects()
, você pode alterar o tipo de coluna 'a' para int64:
>>> df = df.infer_objects()
>>> df.dtypes
a int64
b object
dtype: object
A coluna 'b' foi deixada sozinha, pois seus valores eram cadeias de caracteres, não números inteiros. Se você quiser tentar forçar a conversão de ambas as colunas em um tipo inteiro, use-o df.astype(int)
.