【问题标题】:pandas: to_numeric for multiple columnspandas:多列的 to_numeric
【发布时间】:2016-08-17 06:45:18
【问题描述】:

我正在使用以下df

c.sort_values('2005', ascending=False).head(3)
      GeoName ComponentName     IndustryId IndustryClassification Description                                2004 2005  2006  2007  2008  2009 2010 2011 2012 2013 2014
37926 Alabama Real GDP by state 9          213                    Support activities for mining              99   98    117   117   115   87   96   95   103  102  (NA)
37951 Alabama Real GDP by state 34         42                     Wholesale trade                            9898 10613 10952 11034 11075 9722 9765 9703 9600 9884 10199
37932 Alabama Real GDP by state 15         327                    Nonmetallic mineral products manufacturing 980  968   940   1084  861   724  714  701  589  641  (NA)

我想对所有年份强制使用数字:

c['2014'] = pd.to_numeric(c['2014'], errors='coerce')

有没有简单的方法可以做到这一点,还是我必须全部输入?

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    更新:之后您不需要转换您的值,您可以在读取 CSV 时即时进行:

    In [165]: df=pd.read_csv(url, index_col=0, na_values=['(NA)']).fillna(0)
    
    In [166]: df.dtypes
    Out[166]:
    GeoName                    object
    ComponentName              object
    IndustryId                  int64
    IndustryClassification     object
    Description                object
    2004                        int64
    2005                        int64
    2006                        int64
    2007                        int64
    2008                        int64
    2009                        int64
    2010                        int64
    2011                        int64
    2012                        int64
    2013                        int64
    2014                      float64
    dtype: object
    

    如果您需要将多列转换为数字 dtype - 使用以下技术:

    示例源 DF:

    In [271]: df
    Out[271]:
         id    a  b  c  d  e    f
    0  id_3  AAA  6  3  5  8    1
    1  id_9    3  7  5  7  3  BBB
    2  id_7    4  2  3  5  4    2
    3  id_0    7  3  5  7  9    4
    4  id_0    2  4  6  4  0    2
    
    In [272]: df.dtypes
    Out[272]:
    id    object
    a     object
    b      int64
    c      int64
    d      int64
    e      int64
    f     object
    dtype: object
    

    将选定的列转换为数字类型:

    In [273]: cols = df.columns.drop('id')
    
    In [274]: df[cols] = df[cols].apply(pd.to_numeric, errors='coerce')
    
    In [275]: df
    Out[275]:
         id    a  b  c  d  e    f
    0  id_3  NaN  6  3  5  8  1.0
    1  id_9  3.0  7  5  7  3  NaN
    2  id_7  4.0  2  3  5  4  2.0
    3  id_0  7.0  3  5  7  9  4.0
    4  id_0  2.0  4  6  4  0  2.0
    
    In [276]: df.dtypes
    Out[276]:
    id     object
    a     float64
    b       int64
    c       int64
    d       int64
    e       int64
    f     float64
    dtype: object
    

    PS 如果您想选择所有 string (object) 列,请使用以下简单技巧:

    cols = df.columns[df.dtypes.eq('object')]
    

    【讨论】:

    • 感谢 MaxU,您的两个回答 :)
    • @MichaelPerdue,很高兴为您提供帮助 :)
    • 为了完整性:您还可以在初始化数据帧时即时进行转换,例如:pd.DataFrame(datalist, dtype=float),它将在可能的情况下将所有字段转换为浮点数(并且其他保持不变)
    • 当我这样做时,为什么有些行变成了 NaN?
    • @h_musk,请查看提供的解决方案中的示例。所有不能转换为数值的值都会变成 NaN。
    【解决方案2】:

    另一种方法是使用apply,一个班轮:

    cols = ['col1', 'col2', 'col3']
    data[cols] = data[cols].apply(pd.to_numeric, errors='coerce', axis=1)
    

    【讨论】:

    • 如果我们想要转换为分类而不是数字,该怎么办?
    【解决方案3】:

    你可以使用:

    print df.columns[5:]
    Index([u'2004', u'2005', u'2006', u'2007', u'2008', u'2009', u'2010', u'2011',
           u'2012', u'2013', u'2014'],
          dtype='object')
    
    for col in  df.columns[5:]:
        df[col] = pd.to_numeric(df[col], errors='coerce')
    
    print df
           GeoName      ComponentName  IndustryId  IndustryClassification  \
    37926  Alabama  Real GDP by state           9                     213   
    37951  Alabama  Real GDP by state          34                      42   
    37932  Alabama  Real GDP by state          15                     327   
    
                                          Description  2004   2005   2006   2007  \
    37926               Support activities for mining    99     98    117    117   
    37951                            Wholesale  trade  9898  10613  10952  11034   
    37932  Nonmetallic mineral products manufacturing   980    968    940   1084   
    
            2008  2009  2010  2011  2012  2013     2014  
    37926    115    87    96    95   103   102      NaN  
    37951  11075  9722  9765  9703  9600  9884  10199.0  
    37932    861   724   714   701   589   641      NaN  
    

    filter 的另一个解决方案:

    print df.filter(like='20')
           2004   2005   2006   2007   2008  2009  2010  2011  2012  2013   2014
    37926    99     98    117    117    115    87    96    95   103   102   (NA)
    37951  9898  10613  10952  11034  11075  9722  9765  9703  9600  9884  10199
    37932   980    968    940   1084    861   724   714   701   589   641   (NA)
    
    for col in  df.filter(like='20').columns:
        df[col] = pd.to_numeric(df[col], errors='coerce')
    print df
           GeoName      ComponentName  IndustryId  IndustryClassification  \
    37926  Alabama  Real GDP by state           9                     213   
    37951  Alabama  Real GDP by state          34                      42   
    37932  Alabama  Real GDP by state          15                     327   
    
                                          Description  2004   2005   2006   2007  \
    37926               Support activities for mining    99     98    117    117   
    37951                            Wholesale  trade  9898  10613  10952  11034   
    37932  Nonmetallic mineral products manufacturing   980    968    940   1084   
    
            2008  2009  2010  2011  2012  2013     2014  
    37926    115    87    96    95   103   102      NaN  
    37951  11075  9722  9765  9703  9600  9884  10199.0  
    37932    861   724   714   701   589   641      NaN  
    

    【讨论】:

    • 很高兴能帮到您!祝你好运!
    【解决方案4】:
    df[cols] = pd.to_numeric(df[cols].stack(), errors='coerce').unstack()
    

    【讨论】:

    • 为我工作。一种将多列转换为数字的更简洁的方法。
    • 正如@Blessy 所说。更清洁和简单,这适用于 nan 值。
    【解决方案5】:

    如果您正在寻找一系列列,您可以试试这个:

    df.iloc[7:] = df.iloc[7:].astype(float)
    

    上面的示例将类型转换为浮点数,因为所有列都从第 7 列开始到末尾。你当然可以使用不同的类型或不同的范围。

    我认为当您需要转换大量列和大量行时,这很有用。它不会让您自己遍历每一行 - 我相信 numpy 会更有效地完成。

    这仅在您知道所有必需的列仅包含数字时才有用 - 它不会将“坏值”(如字符串)更改为 NaN。

    【讨论】:

    • 对我来说,它不是从第 7 列开始,而是从第一列开始。
    • 我也是。它从第一列开始
    • astype(float) 不能单独替换 pd.to_numericerrors='coerce' 这是问题的一部分。将触发异常。
    【解决方案6】:
    df.loc[:,'col':] = df.loc[:,'col':].apply(pd.to_numeric, errors = 'coerce')
    

    【讨论】:

    • 虽然此代码可能会为问题提供解决方案,但最好添加有关其工作原理/方式的上下文。这可以帮助未来的用户学习并最终将这些知识应用到他们自己的代码中。解释代码时,您也可能会得到用户的积极反馈/赞成。
    • 我实际上是在这里结束的,因为我正是这样做的,它不适用于 df.loc
    猜你喜欢
    • 1970-01-01
    • 2018-07-10
    • 2018-10-31
    • 2017-10-03
    • 2018-07-09
    • 2016-10-16
    • 2023-02-13
    • 2020-07-29
    • 2018-01-23
    相关资源
    最近更新 更多