在数据框中替换NaN会使数字位数

时间:2018-08-10 14:45:21

标签: python pandas dataframe

我试图理解为什么用空格替换NaN会减少显示位数。

我有DataFrame:

0    -3.030889       -3.510211       -3.502291       -3.502357       -3.502817
1    -3.460590             NaN       -3.584687             NaN             NaN
2    -2.151932       -2.504276       -2.494087       -2.493053       -2.493741
3    -2.462477             NaN       -2.556205             NaN             NaN
4    -1.712807       -1.906281       -1.902953       -1.902297       -1.902253
5    -1.883432             NaN       -1.932924             NaN             NaN

使用`df = df.replace(np.nan,'',regex = True)后,某些数字显示为5个十进制数字。

0    -3.030889       -3.51021       -3.502291       -3.50236       -3.50282
1    -3.460590                      -3.584687                                                        
2    -2.151932       -2.50428       -2.494087       -2.49305       -2.49374
3    -2.462477                      -2.556205                                                        
4    -1.712807       -1.90628       -1.902953        -1.9023       -1.90225
5    -1.883432                      -1.932924                               

如何控制它并保持像第一个DataFrame中那样显示数字的精度?

1 个答案:

答案 0 :(得分:1)

正如评论所建议的那样,您失去精度的原因是因为当您将字符串弹出到浮点数列中时,pandas被迫将该列的dtype转换为object。我将在此答案中尝试详细说明。这是一个示例:

import pandas as pd
import numpy as np
NaN = np.NaN

rows = [[-3.030889, -3.510211, -3.502291, -3.502357, -3.502817],
        [-3.460590, NaN, -3.584687, NaN, NaN],
        [-2.151932, -2.504276, -2.494087, -2.493053, -2.493741],
        [-2.462477, NaN, -2.556205, NaN, NaN],
        [-1.712807, -1.906281, -1.902953, -1.902297, -1.902253],
        [-1.883432, NaN, -1.932924, NaN, NaN]]

df = pd.DataFrame(rows)
print(df)
print(df.dtypes)
print()

new_df = df.replace(np.nan, '', regex=True)
print(new_df)
print(new_df.dtypes)

这将输出:

          0         1         2         3         4
0 -3.030889 -3.510211 -3.502291 -3.502357 -3.502817
1 -3.460590       NaN -3.584687       NaN       NaN
2 -2.151932 -2.504276 -2.494087 -2.493053 -2.493741
3 -2.462477       NaN -2.556205       NaN       NaN
4 -1.712807 -1.906281 -1.902953 -1.902297 -1.902253
5 -1.883432       NaN -1.932924       NaN       NaN
0    float64
1    float64
2    float64
3    float64
4    float64
dtype: object

          0        1         2        3        4
0 -3.030889 -3.51021 -3.502291 -3.50236 -3.50282
1 -3.460590          -3.584687
2 -2.151932 -2.50428 -2.494087 -2.49305 -2.49374
3 -2.462477          -2.556205
4 -1.712807 -1.90628 -1.902953  -1.9023 -1.90225
5 -1.883432          -1.932924
0    float64
1     object
2    float64
3     object
4     object
dtype: object

请注意,无论是将NaN替换为''的列,现在都是object类型(在上面的示例中,第1、3和4列)。转换为对象时,不仅会失去精度,而且还会失去语义。您的数据不再是float64类型的所有数据。因此,如果您尝试对列进行一些操作,则会很困难,因为列项目的类型不尽相同。

如果我们在上面的代码段末尾进入pdb(通过调用import pdb; pdb.set_trace()),我们可以很容易地看到这一点:

(Pdb) df[1].apply(lambda x: x**2)
0    12.321581
1          NaN
2     6.271398
3          NaN
4     3.633907
5          NaN
Name: 1, dtype: float64
(Pdb) new_df[1].apply(lambda x: x**2)
*** TypeError: unsupported operand type(s) for ** or pow(): 'str' and 'int'

您可能希望将所有内容都保留为float64问题是,您将NaN替换为什么?答案是:取决于。只有您知道您的数据及其代表什么。这里有几个选择(还有更多选择):

您可以选择将其保留为NaN,具体取决于您的工作。

>>> np.NaN ** 2
nan
>>> np.NaN - 100
nan
>>> np.sqrt(np.NaN)
nan

浮点运算将什么都不做:数据将保持为NaN。某些python库也可以处理NaN,它们非常好用。

另一个选择是将NaN替换为其他一些浮点值。 WLOG,假设您正在尝试计算列之间的欧几里得距离,该距离代表了模型的某些含义或代表了问题的某些价值。

您可以将NaN替换为一些“远”值。如果您的数据的大小为[-1,1](如正弦数据一样),那么一个很好的替代值可能是-999。可以肯定地认为-999将NaN的列与其他列相距足够远。欧氏距离。因此,如果您希望使用NaN“惩罚”列,那么您可以这样做。

OTOH,也许您希望包含NaN的列仅对w.r.t进行“平均”。欧氏距离(因此本质上只需在NaN中使用您范围内的有效值即可)。 0在[-1,1]的中间,所以它可能是一个不错的选择。这意味着NaN不会真正“惩罚”或“帮助”他人。欧氏距离。您也可以取平均值(或其他某种形式的插值)来计算缺失值。例如,如果您的列向量是[0, 1, NaN, .5, NaN, .7],则可能要用[0, 1, .75, .5, .6, .7](线性插值)代替。

只有您可以决定什么是合适的替代品。

如有疑问,只需尝试。很难预测给定的替换将如何影响大型管道中的结果。如果您没有在下游获得预期的结果,请适当调整替代策略,然后再进行尝试。

每种替换策略都有其优缺点,并且会给您的下游模型/管道带来偏差:只知道您做了什么,并有充分的理由解释奇怪的结果并解释您可能会引入的偏差。

您可以像这样float64进行替换(扩展上面的代码):

fill_value = 0.0 # Make sure it's a float. Only you can decide what it should be.
float_df = df.fillna(fill_value)
print(float_df)
print(float_df.dtypes)

并输出(保持精度):

          0         1         2         3         4
0 -3.030889 -3.510211 -3.502291 -3.502357 -3.502817
1 -3.460590  0.000000 -3.584687  0.000000  0.000000
2 -2.151932 -2.504276 -2.494087 -2.493053 -2.493741
3 -2.462477  0.000000 -2.556205  0.000000  0.000000
4 -1.712807 -1.906281 -1.902953 -1.902297 -1.902253
5 -1.883432  0.000000 -1.932924  0.000000  0.000000
0    float64
1    float64
2    float64
3    float64
4    float64
dtype: object