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.arraydtype="string" 以稳定的方式从any 序列创建StringArray,与使用类构造函数相反,并且“任何数组”暗示转换类型的能力。

以上是关于pandas:将 int Series 转换为新的 StringDtype的主要内容,如果未能解决你的问题,请参考以下文章

pandas.series.rolling.apply 方法似乎将 Series 隐式转换为 numpy 数组

如何将 pandas 列中的 JSON 数据转换为新列

将 pandas.Series 从 dtype 对象转换为浮点数,将错误转换为 nans

无法将 pandas.Series 转换为 dtype=np.float64 的 numpy.array

如何将 Pandas DataFrame 中字典的字符串表示形式转换为新列?

在 pandas.Series 中将时间戳转换为 datetime.datetime