为什么Pandas告诉我我有对象,尽管所选列中的每个项目都是字符串 - 即使在显式转换后也是如此。
这是我的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)
其中五个是dtype object
。我明确地将这些对象转换为字符串:
for c in df.columns:
if df[c].dtype == object:
print "convert ", df[c].name, " to string"
df[c] = df[c].astype(str)
然后,df["attr2"]
仍有dtype object
,但type(df["attr2"].ix[0]
显示str
,这是正确的。
Pandas区分int64
和float64
以及object
。当没有dtype str
时,它背后的逻辑是什么?为什么str
覆盖了object
?
答案 0 :(得分:125)
dtype对象来自NumPy,它描述了ndarray中元素的类型。 ndarray中的每个元素必须具有相同的字节大小。对于int64和float64,它们是8个字节。但对于字符串,字符串的长度不固定。因此,Pandas不是直接在ndarray中保存字符串的字节,而是使用对象ndarray,它保存指向对象的指针,因此这种类型的ddarray是对象。
以下是一个例子:
答案 1 :(得分:10)
@HYRY的答案很好。我只想提供更多背景信息。
阵列将数据存储为连续,固定大小存储块。这些属性的组合使阵列可以快速进行数据访问。例如,考虑您的计算机如何存储32位整数[3,0,1]
。
如果您要求计算机获取数组中的第3个元素,它将从头开始,然后跨64位跳转到第3个元素。 确切知道要跳过多少位才使数组快速运行。
现在考虑字符串['hello', 'i', 'am', 'a', 'banana']
的顺序。字符串是大小不同的对象,因此,如果您尝试将它们存储在连续的内存块中,它将最终看起来像这样。
现在,您的计算机没有快速的方法来访问随机请求的元素。克服这个问题的关键是使用指针。基本上,将每个字符串存储在某个随机的内存位置,然后用每个字符串的内存地址填充数组。 (内存地址只是整数。)所以现在,事情看起来像这样
现在,如果您像以前一样要求计算机获取第三个元素,它可以跨64位跳转(假设内存地址是32位整数),然后再执行一个步骤来获取字符串。 / p>
NumPy面临的挑战是不能保证指针实际上指向字符串。这就是为什么它将dtype报告为“对象”的原因。
要毫不客气地插上我自己讨论的course on NumPy。
答案 2 :(得分:3)
从1.0.0版开始(2020年1月),pandas作为一项实验功能被引入,它通过pandas.StringDtype
为字符串类型提供了一流的支持。
默认情况下您仍然会看到.gitignore
,但可以通过指定object
中的dtype
或简单地使用pd.StringDtype
来使用新类型:
'string'
答案 3 :(得分:2)
可接受的答案是好的。只是想提供一个referenced the documentation的答案。该文档说:
Pandas使用对象dtype来存储字符串。
正如主要评论所说:“不用担心;它应该是这样的。” (尽管公认的答案在解释“为什么”方面做得很好,字符串是可变长度的)
但是对于字符串,字符串的长度不是固定的。