字符串,但 dtype 是 object

为什么熊猫告诉我我有对象,尽管所选列中的每个项目都是字符串ーー即使经过显式转换。

这是我的数据框架:

<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)

其中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,这是正确的。

熊猫区分 int64float64以及 object。当没有 dtype str时,它背后的逻辑是什么?为什么 strobject覆盖?

97548 次浏览

dtype对象来自 NumPy,它描述了 ndarray中元素的类型。ndarray中的每个元素必须具有相同的字节大小。对于 int64float64,它们是8字节。但是对于字符串,字符串的长度是不固定的。因此,熊猫不直接保存 ndarray中字符串的字节数,而是使用对象 ndarray,它保存指向对象的指针; 因此,这种 ndarraydtype是对象。

这里有一个例子:

  • Int64数组包含4个 int64值。
  • 对象数组包含4个指向3个字符串对象的指针。

enter image description here

接受的答案是好的。我只是想参考 文件。文档说:

熊猫使用对象 dtype 存储字符串。

接受的答案很好地解释了“为什么”; 字符串的长度是可变的:

但是对于字符串,字符串的长度是不固定的。

但正如对公认答案的主要评论曾经说过的那样: “别担心,事情应该是这样的。”

从版本1.0.0(2020年1月)开始,熊猫已经引入了一个实验性的特性,通过 pandas.StringDtype为字符串类型提供一流的支持。

虽然默认情况下仍然可以看到 object,但是可以通过指定 pd.StringDtypedtype或简单地指定 'string'来使用新的类型:

>>> pd.Series(['abc', None, 'def'])
0     abc
1    None
2     def
dtype: object
>>> pd.Series(['abc', None, 'def'], dtype=pd.StringDtype())
0     abc
1    <NA>
2     def
dtype: string
>>> pd.Series(['abc', None, 'def']).astype('string')
0     abc
1    <NA>
2     def
dtype: string

@ HYRY 的回答很棒,我只是想提供更多的背景..。

数组以 相邻的固定大小内存块的形式存储数据。这些属性的组合使得数组能够快速地进行数据访问。例如,考虑计算机如何存储32位整数数组 [3,0,1]

enter image description here

如果要求计算机获取数组中的第3个元素,它将从开始处开始,然后跳过64位到达第3个元素。准确地知道要跳过多少位是使数组快速的原因.

现在考虑字符串的序列 ['hello', 'i', 'am', 'a', 'banana']。字符串是大小不同的对象,所以如果您试图将它们存储在连续的内存块中,结果将是这样的。

enter image description here

现在您的计算机无法快速访问随机请求的元素。解决这个问题的关键是使用指针。基本上,将每个字符串存储在随机的内存位置,并用每个字符串的内存地址填充数组。(内存地址只是整数。)现在,事情是这样的

enter image description here

现在,如果你要求你的计算机获取第三个元素,就像以前一样,它可以跳过64位(假设内存地址是32位整数) ,然后做一个额外的步骤去获取字符串。

NumPy 面临的挑战是不能保证指针实际上指向字符串。这就是它将 dtype 报告为“ object”的原因。

厚颜无耻地插入我自己的 关于笨蛋的课程在我最初讨论这个的地方。