【问题标题】:Why does pandas Series.str convert numbers to NaN?为什么 pandas Series.str 将数字转换为 NaN?
【发布时间】:2018-02-26 05:50:40
【问题描述】:

这可能是我的一个基本误解,但我希望pandas.Series.strpandas.Series 值转换为字符串。

但是,当我执行以下操作时,系列中的数值将转换为np.nan

df = pd.DataFrame({'a': ['foo    ', 'bar', 42]})
df = df.apply(lambda x: x.str.strip() if x.dtype == 'object' else x)
print(df)

Out:
     a
0  foo
1  bar
2  NaN

如果我首先将str 函数应用于每一列,数值将转换为字符串而不是np.nan

df = pd.DataFrame({'a': ['foo    ', 'bar', 42]})
df = df.apply(lambda x: x.apply(str) if x.dtype == 'object' else x)
df = df.apply(lambda x: x.str.strip() if x.dtype == 'object' else x)
print(df)

Out:
     a
0  foo
1  bar
2   42

关于这个主题的文档相当少。我错过了什么?

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    在这一行:

    df.apply(lambda x: x.str.strip() if x.dtype == 'object' else x)
    

    x.dtype 正在查看整个系列(列)。该列不是数字。因此,整个列都在类似的字符串上进行操作。

    在你的第二个例子中,数字没有被保留,它是一个字符串'42'

    输出的差异将是由于panda的str和python的str不同。

    对于 pandas .str,这不是转换,它是一个访问器,允许您对每个元素执行 .strip()。这意味着您尝试将.strip() 应用于整数。这会引发异常,pandas 通过返回 Nan 来响应异常。

    .apply(str) 的情况下,您实际上是将值转换为字符串。稍后当您应用.strip() 时会成功,因为该值已经是一个字符串,因此可以被剥离。

    【讨论】:

      【解决方案2】:

      您使用.apply 的方式是按,因此请注意:

      >>> df.apply(lambda x: x.str.strip() if x.dtype == 'object' else x)
           a
      0  foo
      1  bar
      2  NaN
      

      它作用于列,x.dtype总是object

      >>> df.apply(lambda x:x.dtype)
      a    object
      dtype: object
      

      如果您确实逐行使用axis=1,您仍然会看到相同的行为:

      >>> df.apply(lambda x:x.dtype, axis=1)
      0    object
      1    object
      2    object
      dtype: object
      

      你瞧:

      >>> df.apply(lambda x: x.str.strip() if x.dtype == 'object' else x, axis=1)
           a
      0  foo
      1  bar
      2  NaN
      >>>
      

      所以,当它说object dtype 时,它​​的意思是Python object。所以考虑一个非对象数字列:

      >>> S = pd.Series([1,2,3])
      >>> S.dtype
      dtype('int64')
      >>> S[0]
      1
      >>> S[0].dtype
      dtype('int64')
      >>> isinstance(S[0], int)
      False
      

      而使用此对象 dtype 列:

      >>> df
               a
      0  foo
      1      bar
      2       42
      >>> df['a'][2]
      42
      >>> isinstance(df['a'][2], int)
      True
      >>>
      

      你正在有效地这样做:

      >>> s = df.a.astype(str).str.strip()
      >>> s
      0    foo
      1    bar
      2     42
      Name: a, dtype: object
      >>> s[2]
      '42'
      

      注意:

      >>> df.apply(lambda x: x.apply(str) if x.dtype == 'object' else x).a[2]
      '42'
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-10-24
        • 2018-05-19
        • 2013-08-28
        • 1970-01-01
        • 2020-01-23
        • 1970-01-01
        • 2017-03-20
        • 2018-06-26
        相关资源
        最近更新 更多