将Pandas数据框转换为带逗号和负数的浮点数

15
我已经阅读了几篇关于如何使用pd.to_numeric和applymap(locale.atof)将Pandas列转换为浮点数的文章。
但是我遇到的问题是两者都不起作用。
请注意,原始数据框的数据类型为Object。
df.append(df_income_master[", Net"])
Out[76]: 
Date
2016-09-30       24.73
2016-06-30       18.73
2016-03-31       17.56
2015-12-31       29.14
2015-09-30       22.67
2015-12-31       95.85
2014-12-31       84.58
2013-12-31       58.33
2012-12-31       29.63
2016-09-30      243.91
2016-06-30      230.77
2016-03-31      216.58
2015-12-31      206.23
2015-09-30      192.82
2015-12-31      741.15
2014-12-31      556.28
2013-12-31      414.51
2012-12-31      308.82
2016-10-31    2,144.78
2016-07-31    2,036.62
2016-04-30    1,916.60
2016-01-31    1,809.40
2015-10-31    1,711.97
2016-01-31    6,667.22
2015-01-31    5,373.59
2014-01-31    4,071.00
2013-01-31    3,050.20
2016-09-30       -0.06
2016-06-30       -1.88
2016-03-31            
2015-12-31       -0.13
2015-09-30            
2015-12-31       -0.14
2014-12-31        0.07
2013-12-31           0
2012-12-31           0
2016-09-30        -0.8
2016-06-30       -1.12
2016-03-31        1.32
2015-12-31       -0.05
2015-09-30       -0.34
2015-12-31       -1.37
2014-12-31        -1.9
2013-12-31       -1.48
2012-12-31         0.1
2016-10-31       41.98
2016-07-31          35
2016-04-30      -11.66
2016-01-31       27.09
2015-10-31       -3.44
2016-01-31       14.13
2015-01-31      -18.69
2014-01-31       -4.87
2013-01-31        -5.7
dtype: object

   pd.to_numeric(df, errors='coerce')
    Out[77]: 
    Date
    2016-09-30     24.73
    2016-06-30     18.73
    2016-03-31     17.56
    2015-12-31     29.14
    2015-09-30     22.67
    2015-12-31     95.85
    2014-12-31     84.58
    2013-12-31     58.33
    2012-12-31     29.63
    2016-09-30    243.91
    2016-06-30    230.77
    2016-03-31    216.58
    2015-12-31    206.23
    2015-09-30    192.82
    2015-12-31    741.15
    2014-12-31    556.28
    2013-12-31    414.51
    2012-12-31    308.82
    2016-10-31       NaN
    2016-07-31       NaN
    2016-04-30       NaN
    2016-01-31       NaN
    2015-10-31       NaN
    2016-01-31       NaN
    2015-01-31       NaN
    2014-01-31       NaN
    2013-01-31       NaN
    Name: Revenue, dtype: float64

注意,当我执行to_numeric转换时,它会将具有逗号(千位分隔符)的字符串以及负数转换为NaN。请问您能帮我找到一种方法吗?

编辑:

继续尝试重现此问题,我向单个DataFrame添加了两列,这些列中包含有问题的文本。 我最终想将这些列转换为浮点数,但是我遇到了各种错误:

df
Out[168]: 
             Revenue Other, Net
Date                           
2016-09-30     24.73      -0.06
2016-06-30     18.73      -1.88
2016-03-31     17.56           
2015-12-31     29.14      -0.13
2015-09-30     22.67           
2015-12-31     95.85      -0.14
2014-12-31     84.58       0.07
2013-12-31     58.33          0
2012-12-31     29.63          0
2016-09-30    243.91       -0.8
2016-06-30    230.77      -1.12
2016-03-31    216.58       1.32
2015-12-31    206.23      -0.05
2015-09-30    192.82      -0.34
2015-12-31    741.15      -1.37
2014-12-31    556.28       -1.9
2013-12-31    414.51      -1.48
2012-12-31    308.82        0.1
2016-10-31  2,144.78      41.98
2016-07-31  2,036.62         35
2016-04-30  1,916.60     -11.66
2016-01-31  1,809.40      27.09
2015-10-31  1,711.97      -3.44
2016-01-31  6,667.22      14.13
2015-01-31  5,373.59     -18.69
2014-01-31  4,071.00      -4.87
2013-01-31  3,050.20       -5.7

以下是使用下面解决方案的结果:

print (pd.to_numeric(df.astype(str).str.replace(',',''), errors='coerce'))
Traceback (most recent call last):

  File "<ipython-input-169-d003943c86d2>", line 1, in <module>
    print (pd.to_numeric(df.astype(str).str.replace(',',''), errors='coerce'))

  File "/Users/Lee/anaconda/lib/python3.5/site-packages/pandas/core/generic.py", line 2744, in __getattr__
    return object.__getattribute__(self, name)

AttributeError: 'DataFrame' object has no attribute 'str'

感谢修复,约翰·高尔特。 - leeprevost
1个回答

19

看起来你需要使用replace, 将空字符串替换为空值:

print (df)
2016-10-31    2,144.78
2016-07-31    2,036.62
2016-04-30    1,916.60
2016-01-31    1,809.40
2015-10-31    1,711.97
2016-01-31    6,667.22
2015-01-31    5,373.59
2014-01-31    4,071.00
2013-01-31    3,050.20
2016-09-30       -0.06
2016-06-30       -1.88
2016-03-31            
2015-12-31       -0.13
2015-09-30            
2015-12-31       -0.14
2014-12-31        0.07
2013-12-31           0
2012-12-31           0
Name: val, dtype: object
print (pd.to_numeric(df.str.replace(',',''), errors='coerce'))
2016-10-31    2144.78
2016-07-31    2036.62
2016-04-30    1916.60
2016-01-31    1809.40
2015-10-31    1711.97
2016-01-31    6667.22
2015-01-31    5373.59
2014-01-31    4071.00
2013-01-31    3050.20
2016-09-30      -0.06
2016-06-30      -1.88
2016-03-31        NaN
2015-12-31      -0.13
2015-09-30        NaN
2015-12-31      -0.14
2014-12-31       0.07
2013-12-31       0.00
2012-12-31       0.00
Name: val, dtype: float64

编辑:

如果使用 append,那么第一个 dfdtype 可能是 float,第二个是 object,所以需要先将其转换为 str,因为会得到混合的 DataFrame - 例如,第一行的类型是 float,最后一行的类型是 字符串

print (pd.to_numeric(df.astype(str).str.replace(',',''), errors='coerce'))

还可以通过以下方式检查类型

print (df.apply(type))
2016-09-30    <class 'float'>
2016-06-30    <class 'float'>
2015-12-31    <class 'float'>
2014-12-31    <class 'float'>
2014-01-31      <class 'str'>
2013-01-31      <class 'str'>
2016-09-30      <class 'str'>
2016-06-30      <class 'str'>
2016-03-31      <class 'str'>
2015-12-31      <class 'str'>
2015-09-30      <class 'str'>
2015-12-31      <class 'str'>
2014-12-31      <class 'str'>
2013-12-31      <class 'str'>
2012-12-31      <class 'str'>
Name: val, dtype: object

编辑1:

如果需要对DataFrame的所有列应用解决方案,请使用apply

df1 = df.apply(lambda x: pd.to_numeric(x.astype(str).str.replace(',',''), errors='coerce'))
print (df1)
            Revenue  Other, Net
Date                           
2016-09-30    24.73       -0.06
2016-06-30    18.73       -1.88
2016-03-31    17.56         NaN
2015-12-31    29.14       -0.13
2015-09-30    22.67         NaN
2015-12-31    95.85       -0.14
2014-12-31    84.58        0.07
2013-12-31    58.33        0.00
2012-12-31    29.63        0.00
2016-09-30   243.91       -0.80
2016-06-30   230.77       -1.12
2016-03-31   216.58        1.32
2015-12-31   206.23       -0.05
2015-09-30   192.82       -0.34
2015-12-31   741.15       -1.37
2014-12-31   556.28       -1.90
2013-12-31   414.51       -1.48
2012-12-31   308.82        0.10
2016-10-31  2144.78       41.98
2016-07-31  2036.62       35.00
2016-04-30  1916.60      -11.66
2016-01-31  1809.40       27.09
2015-10-31  1711.97       -3.44
2016-01-31  6667.22       14.13
2015-01-31  5373.59      -18.69
2014-01-31  4071.00       -4.87
2013-01-31  3050.20       -5.70

print(df1.dtypes)
Revenue       float64
Other, Net    float64
dtype: object

但如果需要仅转换DataFrame的某些列,请使用subsetapply

cols = ['Revenue', ...]
df[cols] = df[cols].apply(lambda x: pd.to_numeric(x.astype(str)
                                                   .str.replace(',',''), errors='coerce'))
print (df)
            Revenue Other, Net
Date                          
2016-09-30    24.73      -0.06
2016-06-30    18.73      -1.88
2016-03-31    17.56           
2015-12-31    29.14      -0.13
2015-09-30    22.67           
2015-12-31    95.85      -0.14
2014-12-31    84.58       0.07
2013-12-31    58.33          0
2012-12-31    29.63          0
2016-09-30   243.91       -0.8
2016-06-30   230.77      -1.12
2016-03-31   216.58       1.32
2015-12-31   206.23      -0.05
2015-09-30   192.82      -0.34
2015-12-31   741.15      -1.37
2014-12-31   556.28       -1.9
2013-12-31   414.51      -1.48
2012-12-31   308.82        0.1
2016-10-31  2144.78      41.98
2016-07-31  2036.62         35
2016-04-30  1916.60     -11.66
2016-01-31  1809.40      27.09
2015-10-31  1711.97      -3.44
2016-01-31  6667.22      14.13
2015-01-31  5373.59     -18.69
2014-01-31  4071.00      -4.87
2013-01-31  3050.20       -5.7

print(df.dtypes)
Revenue       float64
Other, Net     object
dtype: object

编辑2:

你的奖励问题的解决方案:

df = pd.DataFrame({'A':['q','e','r'],
                   'B':['4','5','q'],
                   'C':[7,8,9.0],
                   'D':['1,000','3','50,000'],
                   'E':['5','3','6'],
                   'F':['w','e','r']})

print (df)
   A  B    C       D  E  F
0  q  4  7.0   1,000  5  w
1  e  5  8.0       3  3  e
2  r  q  9.0  50,000  6  r
#first apply original solution
df1 = df.apply(lambda x: pd.to_numeric(x.astype(str).str.replace(',',''), errors='coerce'))
print (df1)
   A    B    C      D  E   F
0 NaN  4.0  7.0   1000  5 NaN
1 NaN  5.0  8.0      3  3 NaN
2 NaN  NaN  9.0  50000  6 NaN

#mask where all columns are NaN - string columns
mask = df1.isnull().all()
print (mask)
A     True
B    False
C    False
D    False
E    False
F     True
dtype: bool
#replace NaN to string columns
df1.loc[:, mask] = df1.loc[:, mask].combine_first(df)
print (df1)
   A    B    C      D  E  F
0  q  4.0  7.0   1000  5  w
1  e  5.0  8.0      3  3  e
2  r  NaN  9.0  50000  6  r

谢谢 - 我尝试过了,但不幸的是,它们最初是dtype对象,而不是字符串,因此当我尝试时会出现错误。 - leeprevost
谢谢。我当时出了点问题 - 我在用混合数据框。 - leeprevost
可恶 - 我还在收到错误: print(pd.to_numeric(df.astype(str).str.replace(',',''), errors='coerce')) Traceback (most recent call last): File "<ipython-input-162-d003943c86d2>", line 1, in <module> print(pd.to_numeric(df.astype(str).str.replace(',',''), errors='coerce')) File "/Users/Lee/anaconda/lib/python3.5/site-packages/pandas/core/generic.py", line 2744, in getattr return object.getattribute(self, name)AttributeError: 'DataFrame'对象没有属性'str' - leeprevost
按列操作确实有效。您能想到一种在所有列上执行此操作的方法吗?请参见我上面的编辑,因为我认为我的DF中的内容可能会让您感到困惑。 - leeprevost
当然,你是最棒的!上述的修改1确实有效!谢谢。 - leeprevost
现在来一个奖励问题——如果DataFrame中有一些明显的字符串列,我想将所有的数值字符串列转换为浮点型,而保持其他列不变呢?(这是不是要求太多了?)<g> - leeprevost

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接