【问题标题】:pandas: Convert int Series to new StringDtypepandas:将 int Series 转换为新的 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 docint_series.astype('string') 应该可以工作,但它没有。
  • @QuangHoang:是的,string dtype 是 1.0.0 版中的新内容
  • 如果不使用“UInt8”而是常规int,错误更明确:ValueError: StringArray requires a sequence of strings or pandas.NA

标签: python pandas


【解决方案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,与使用类构造函数相反,并且“任何数组”暗示转换类型的能力。
猜你喜欢
  • 2022-08-19
  • 1970-01-01
  • 2012-05-09
  • 2016-12-28
  • 1970-01-01
  • 1970-01-01
  • 2019-12-01
  • 2021-11-02
  • 2017-09-26
相关资源
最近更新 更多