为什么max()有时会返回nan而有时会忽略它?

时间:2017-12-13 08:16:25

标签: python pandas replace missing-data

这个问题是由我前一段时间提出的an answer推动的。

我们说我有一个像这样的数据框

import numpy as np
import pandas as pd

df = pd.DataFrame({'a': [1, 2, np.nan], 'b': [3, np.nan, 10], 'c':[np.nan, 5, 34]})

     a     b     c
0  1.0   3.0   NaN
1  2.0   NaN   5.0
2  NaN  10.0  34.0

我希望将NaN替换为行的最大值I can do

df.apply(lambda row: row.fillna(row.max()), axis=1)

给了我想要的输出

      a     b     c
0   1.0   3.0   3.0
1   2.0   5.0   5.0
2  34.0  10.0  34.0

然而,当我使用

df.apply(lambda row: row.fillna(max(row)), axis=1)

由于某种原因,只有在三种情况中的两种情况下才能正确替换它:

     a     b     c
0  1.0   3.0   3.0
1  2.0   5.0   5.0
2  NaN  10.0  34.0

的确,如果我手工检查

max(df.iloc[0, :])
max(df.iloc[1, :])
max(df.iloc[2, :])

然后打印

3.0
5.0
nan

做的时候

df.iloc[0, :].max()
df.iloc[1, :].max()
df.iloc[2, :].max()

打印预期的

3.0
5.0
34.0

我的问题是为什么max()在三个案例中的一个案例中失败但在所有案例中都没有。为什么NaN有时会被忽略而有时不会被忽略?

4 个答案:

答案 0 :(得分:9)

原因是max的工作原理是将第一个值作为“到目前为止看到的最大值”,然后检查每个其他值以查看它是否大于目前为止看到的最大值。但nan已定义,因此与它的比较始终返回False - 即nan > 1为false,但1 > nan也为false。

因此,如果您从nan开始作为数组中的第一个值,则每次后续比较都将检查some_other_value > nan。这将永远是错误的,因此nan将保持其“迄今为止看到的最大值”的位置。另一方面,如果nan不是第一个值,那么当达到时,比较nan > max_so_far将再次为假。但在这种情况下,这意味着当前“迄今为止看到的最大值”(不是nan)将保持迄今为止的最大值,因此将永远丢弃nan。

答案 1 :(得分:6)

在第一种情况下,您正在使用numpy max函数,该函数知道如何处理numpy.nan

在第二种情况下,您正在使用python中的内置max函数。这不知道如何处理numpy.nan。据推测,这种效应是由于numpy.nan与浮点数的任何比较(>,<,==等)导致False。实现max的一种显而易见的方法是迭代迭代(在这种情况下为行)并检查每个值是否大于前一个值,并将其存储为最大值(如果是这样)。由于当比较值之一为numpy.nan时,大于比较的值始终为假,因此记录的最大值是否为您想要的数字或numpy.nan完全取决于第一个值是否为numpy.nan或不。

答案 2 :(得分:1)

这是由于列表中元素的排序。首先,如果你输入

max([1, 2, np.nan])

结果为2,而

max([np.nan, 2, 3])

给出np.nan。这样做的原因是max函数逐个遍历列表中的值,并进行比较,如下所示:

if a > b

现在,如果我们看一下与nan比较时得到的结果,np.nan > 21 > np.nan都会给False,所以在一种情况下,运行的最大值会替换为nan而另一方则不是。

答案 3 :(得分:0)

两者不同:max()vs df.max()。

max():python内置函数,它必须是非空的可迭代。点击这里: https://docs.python.org/2/library/functions.html#max

当pandas dataframe - df.max(skipna = ..)时,有一个名为skipna的参数,默认值为True,这意味着排除了NA / null值。点击这里: https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.max.html