【问题标题】:convert entire pandas dataframe to integers in pandas (0.17.0)将整个熊猫数据框转换为熊猫(0.17.0)中的整数
【发布时间】:2016-01-17 22:48:58
【问题描述】:

我的问题与this one 非常相似,但我需要转换我的整个数据框而不仅仅是一个系列。 to_numeric 函数一次仅适用于一个系列,不能很好地替代已弃用的 convert_objects 命令。有没有办法获得与新版 pandas 中的convert_objects(convert_numeric=True) 命令类似的结果?

感谢 Mike Müller 提供的示例。如果值都可以转换为整数,df.apply(pd.to_numeric) 工作得很好。如果在我的数据框中我有无法转换为整数的字符串怎么办? 示例:

df = pd.DataFrame({'ints': ['3', '5'], 'Words': ['Kobe', 'Bryant']})
df.dtypes
Out[59]: 
Words    object
ints     object
dtype: object

然后我可以运行已弃用的函数并获取:

df = df.convert_objects(convert_numeric=True)
df.dtypes
Out[60]: 
Words    object
ints      int64
dtype: object

运行apply 命令会出现错误,即使使用 try 和 except 处理也是如此。

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    所有列可转换

    您可以将函数应用于所有列:

    df.apply(pd.to_numeric)
    

    例子:

    >>> df = pd.DataFrame({'a': ['1', '2'], 
                           'b': ['45.8', '73.9'],
                           'c': [10.5, 3.7]})
    
    >>> df.info()
    <class 'pandas.core.frame.DataFrame'>
    Int64Index: 2 entries, 0 to 1
    Data columns (total 3 columns):
    a    2 non-null object
    b    2 non-null object
    c    2 non-null float64
    dtypes: float64(1), object(2)
    memory usage: 64.0+ bytes
    
    >>> df.apply(pd.to_numeric).info()
    <class 'pandas.core.frame.DataFrame'>
    Int64Index: 2 entries, 0 to 1
    Data columns (total 3 columns):
    a    2 non-null int64
    b    2 non-null float64
    c    2 non-null float64
    dtypes: float64(2), int64(1)
    memory usage: 64.0 bytes
    

    并非所有列都可转换

    pd.to_numeric 有关键字参数errors

      Signature: pd.to_numeric(arg, errors='raise')
      Docstring:
      Convert argument to a numeric type.
    
    Parameters
    ----------
    arg : list, tuple or array of objects, or Series
    errors : {'ignore', 'raise', 'coerce'}, default 'raise'
        - If 'raise', then invalid parsing will raise an exception
        - If 'coerce', then invalid parsing will be set as NaN
        - If 'ignore', then invalid parsing will return the input
    

    将其设置为 ignore 将在无法转换为数字类型时返回未更改的列。

    正如 Anton Protopopov 所指出的,最优雅的方式是将 ignore 作为关键字参数提供给 apply()

    >>> df = pd.DataFrame({'ints': ['3', '5'], 'Words': ['Kobe', 'Bryant']})
    >>> df.apply(pd.to_numeric, errors='ignore').info()
    <class 'pandas.core.frame.DataFrame'>
    Int64Index: 2 entries, 0 to 1
    Data columns (total 2 columns):
    Words    2 non-null object
    ints     2 non-null int64
    dtypes: int64(1), object(1)
    memory usage: 48.0+ bytes
    

    我之前建议的方式,使用模块 functools 中的 partial,更加冗长:

    >>> from functools import partial
    >>> df = pd.DataFrame({'ints': ['3', '5'], 
                           'Words': ['Kobe', 'Bryant']})
    >>> df.apply(partial(pd.to_numeric, errors='ignore')).info()
    <class 'pandas.core.frame.DataFrame'>
    Int64Index: 2 entries, 0 to 1
    Data columns (total 2 columns):
    Words    2 non-null object
    ints     2 non-null int64
    dtypes: int64(1), object(1)
    memory usage: 48.0+ bytes
    

    【讨论】:

    • 我认为,在 apply 中将此参数设置为 keywarg 的最优雅方式:df.apply(pd.to_numeric, errors='ignore') 应该可以正常工作。
    • to_numeric 不使用逗号。
    • 最后只获取整数列,如问题所述,遍历所有列:for i in df.columns: try: df[[i]] = df[[i]].astype(int) except: pass
    【解决方案2】:

    pd.to_numeric() 接受的答案会在需要时立即转换为浮点数。详细阅读这个问题,它是关于将任何数字列转换为 integer。 这就是为什么接受的答案需要对所有列进行循环以最终将数字转换为 int。

    为了完整起见,这甚至可以不使用 pd.to_numeric();当然,不建议这样做:

    df = pd.DataFrame({'a': ['1', '2'], 
                       'b': ['45.8', '73.9'],
                       'c': [10.5, 3.7]})
    
    for i in df.columns:
        try:
            df[[i]] = df[[i]].astype(float).astype(int)
        except:
            pass
    
    print(df.dtypes)
    

    输出:

    a    int32
    b    int32
    c    int32
    dtype: object
    

    已编辑: 请注意,这种不推荐的解决方案过于复杂; pd.to_numeric() 可以简单地使用关键字参数downcast='integer' 强制整数作为输出,谢谢您的评论。不过,在接受的答案中仍然缺少这一点。

    【讨论】:

    • 如果所有的“数字”都被格式化为整数(即​​'5',而不是'5.0'),那么可以在to_numeric函数中使用关键字参数downcast='integer'来强制整数类型:在此示例中,df.apply(pd.to_numeric, downcast='integer') 将列 a 作为整数返回
    【解决方案3】:

    apply() pd.to_numeric with errors='ignore' 将其分配回DataFrame:

    df = pd.DataFrame({'ints': ['3', '5'], 'Words': ['Kobe', 'Bryant']})
    print ("Orig: \n",df.dtypes)
    
    df.apply(pd.to_numeric, errors='ignore')
    print ("\nto_numeric: \n",df.dtypes)
    
    df = df.apply(pd.to_numeric, errors='ignore')
    print ("\nto_numeric with assign: \n",df.dtypes)
    

    输出:

    Orig: 
     ints     object
    Words    object
    dtype: object
    
    to_numeric: 
     ints     object
    Words    object
    dtype: object
    
    to_numeric with assign: 
     ints      int64
    Words    object
    dtype: object
    

    【讨论】:

    • 不言而喻,如果要保存更改,则需要重新分配 df。这应该只是接受的解决方案下的评论。
    【解决方案4】:

    您可以使用 df.astype() 将系列转换为所需的数据类型。

    例如: my_str_df = [['20','30','40']]

    然后: my_int_df = my_str_df['column_name'].astype(int) # 这将是 int 类型

    【讨论】:

    • 投反对票。问题是关于一个数据框,而不是一个系列,并且您没有解释如何更改整个数据框,该数据框也具有字符串类型的浮点列,例如“45.8”。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-05
    • 1970-01-01
    • 1970-01-01
    • 2020-02-07
    • 2019-10-04
    • 2019-10-12
    • 2017-07-31
    相关资源
    最近更新 更多