Por que o Pandas me diz que tenho objetos, embora cada item na coluna selecionada seja uma string - mesmo após a conversão explícita?
Este é meu DataFrame:
<class 'pandas.core.frame.DataFrame'>
Int64Index: 56992 entries, 0 to 56991
Data columns (total 7 columns):
id 56992 non-null values
attr1 56992 non-null values
attr2 56992 non-null values
attr3 56992 non-null values
attr4 56992 non-null values
attr5 56992 non-null values
attr6 56992 non-null values
dtypes: int64(2), object(5)
Cinco deles são dtype object
. Eu converto explicitamente esses objetos em strings:
for c in df.columns:
if df[c].dtype == object:
print "convert ", df[c].name, " to string"
df[c] = df[c].astype(str)
Então, df["attr2"]
ainda tem dtype object
, embora type(df["attr2"].ix[0]
revele str
, o que é correto.
O Pandas distingue entre int64
e float64
e object
. Qual é a lógica por trás disso quando não há dtype str
? Por que um está str
coberto por object
?
Respostas:
O objeto dtype vem de NumPy, ele descreve o tipo de elemento em um ndarray. Cada elemento em um ndarray deve ter o mesmo tamanho em bytes. Para int64 e float64, eles têm 8 bytes. Mas para cordas, o comprimento da corda não é fixo. Então, em vez de salvar os bytes de strings no ndarray diretamente, o Pandas usa o objeto ndarray, que salva ponteiros para objetos, por isso o dtipo desse tipo ndarray é objeto.
Aqui está um exemplo:
fonte
A resposta aceita é boa. Queria apenas fornecer uma resposta que referencia a documentação . A documentação diz:
Como diz o comentário principal: "Não se preocupe com isso; é para ser assim." (Embora a resposta aceita tenha explicado muito bem o "porquê"; as strings têm comprimento variável)
fonte
astype(str)
embora eu ainda me pergunte se a conversão de strings é necessáriaA resposta de @HYRY é ótima. Eu só quero fornecer um pouco mais de contexto.
Arrays dados armazenados como contígua , de tamanho fixo blocos de memória. A combinação dessas propriedades é o que torna os arrays extremamente rápidos para o acesso aos dados. Por exemplo, considere como seu computador pode armazenar uma matriz de inteiros de 32 bits
[3,0,1]
,.Se você pedir ao seu computador para buscar o terceiro elemento no array, ele começará no início e então saltará pelos 64 bits para chegar ao terceiro elemento. Saber exatamente quantos bits saltar é o que torna os arrays mais rápidos .
Agora considere a sequência de strings
['hello', 'i', 'am', 'a', 'banana']
. Strings são objetos que variam em tamanho, então se você tentasse armazená-los em blocos de memória contíguos, ficaria assim.Agora seu computador não tem uma maneira rápida de acessar um elemento solicitado aleatoriamente. A chave para superar isso é usar ponteiros. Basicamente, armazene cada string em algum local de memória aleatório e preencha o array com o endereço de memória de cada string. (Os endereços de memória são apenas números inteiros.) Então, agora, as coisas se parecem com isto
Agora, se você pedir ao seu computador para buscar o terceiro elemento, assim como antes, ele pode pular 64 bits (assumindo que os endereços de memória são inteiros de 32 bits) e então dar um passo extra para buscar a string.
O desafio para NumPy é que não há garantia de que os ponteiros estão realmente apontando para strings. É por isso que relata o dtype como 'objeto'.
Sem vergonha, vou inserir meu próprio artigo de blog onde originalmente discuti isso.
fonte
A partir da versão 1.0.0 (janeiro de 2020), o pandas foi introduzido como um recurso experimental que fornece suporte de primeira classe para tipos de strings
pandas.StringDtype
.Embora você ainda esteja vendo
object
por padrão, o novo tipo pode ser usado especificando umdtype
depd.StringDtype
ou simplesmente'string'
:fonte
The implementation may change without warning.
que significa que novas atualizações irão quebrar seus programas antigos.