pandas:将 int Series 转换为新的 StringDtype
Posted
技术标签:
【中文标题】pandas:将 int Series 转换为新的 StringDtype【英文标题】:pandas: Convert int Series to new StringDtype 【发布时间】:2020-07-24 05:42:06 【问题描述】:我正在尝试将UInt8
pandas 系列转换为新的StringDtype
。
我可以执行以下操作,在 this question 中介绍,它早于新的 string
dtype:
import pandas as pd
int_series = pd.Series(range(20), dtype="UInt8")
obj_series = int_series.apply(str)
这给了我一系列包含字符串的 Object dtype。
但如果我尝试将系列转换为新的 string
dtype,我会收到错误:
>>> string_series = int_series.astype("string")
...
TypeError: data type not understood
请注意,首先将系列转换为Object
,然后再转换为string
dtype:
int_series.apply(str).astype("string")
如何将 int 系列直接转换为字符串?
我在 Python 3.7.6 上使用 pandas 1.0.3 版
更新:我在 pandas Github 页面中找到了this open issue,它描述了完全相同的问题。
上述问题中的一条评论指向another open issue,它涵盖了在不同 ExtensionArray 类型之间进行转换的所需但当前不可用的功能。
所以答案是现在无法进行直接转换,但将来可能会。
【问题讨论】:
我一直认为pandas
只有object
作为字符串值的dtype。很有趣。
根据this doc,int_series.astype('string')
应该可以工作,但它没有。
@QuangHoang:是的,string
dtype 是 1.0.0 版中的新内容
如果不使用“UInt8”而是常规int,错误更明确:ValueError: StringArray requires a sequence of strings or pandas.NA
【参考方案1】:
使用 numpy.string_
string_series = int_series.astype(np.string_)
【讨论】:
这给了我ValueError: When changing to a smaller dtype, its size must be a divisor of the size of original dtype
添加截图
不幸的是,这在我的系统中不起作用,尽管如此,它正在生成 bytes16
系列,而不是 string
【参考方案2】:
这在docs 的示例部分中进行了解释:
与对象 dtype 数组不同,StringArray 不允许非字符串值
下面的例子显示在哪里:
pd.array(['1', 1], dtype="string")
Traceback(最近一次调用最后一次): ... ValueError: StringArray 需要一个 object-dtype ndarray 字符串。
唯一的解决方案似乎是像你正在做的那样转换为Object
dtype,然后然后转换为字符串。
source code of StringArray
中也明确说明了这一点,您会在顶部看到警告:
.. warning:: Currently, this expects an object-dtype ndarray where the elements are Python strings or :attr:`pandas.NA`. This may change without warning in the future. Use :meth:`pandas.array` with ``dtype="string"`` for a stable way of creating a `StringArray` from any sequence.
如果您检查_validate
中的验证步骤,您将看到非字符串数组将如何失败:
def _validate(self):
"""Validate that we only store NA or strings."""
if len(self._ndarray) and not lib.is_string_array(self._ndarray, skipna=True):
raise ValueError("StringArray requires a sequence of strings or pandas.NA")
if self._ndarray.dtype != "object":
raise ValueError(
"StringArray requires a sequence of strings or pandas.NA. Got "
f"'self._ndarray.dtype' dtype instead."
)
对于问题中的示例:
from pandas._libs import lib
lib.is_string_array(np.array(range(20)), skipna=True)
# False
【讨论】:
我理解这一点是为了创建数组,而不是转换。这pd.array([1, "2"], dtype="UInt8")
失败,但成功pd.array([1, "2"], dtype="object").astype("UInt8")
。所以虽然UInt8
不接受字符串,但它仍然可以使用astype
转换字符串
是的,因为之前您已经投射到对象。并且 afaik 使用 astype
转换为另一个 dtype 与重新创建数据框或系列相同,请注意它会创建一个副本 @foglerit
好像有bug。您引用的警告是针对 StringArray
__init__
方法的 values
参数。它声明这应该可以工作pd.array(int_series, dtype="string")
,但它没有。
无论如何,你的回答很有见地。我将在 Github 中打开一个问题,并在他们确认您的观点后接受您的回答。
你可能是对的。我解释了以下语句:使用:meth:pandas.array
和dtype="string"
以稳定的方式从any 序列创建StringArray
,与使用类构造函数相反,并且“任何数组”暗示转换类型的能力。以上是关于pandas:将 int Series 转换为新的 StringDtype的主要内容,如果未能解决你的问题,请参考以下文章
pandas.series.rolling.apply 方法似乎将 Series 隐式转换为 numpy 数组
将 pandas.Series 从 dtype 对象转换为浮点数,将错误转换为 nans
无法将 pandas.Series 转换为 dtype=np.float64 的 numpy.array