为什么 max() 有时返回 nan,有时又忽略它?

问题描述 投票:0回答:6

这个问题是由我不久前给出的答案引发的。

假设我有一个像这样的数据框

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
我可以做

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()
在三种情况中的一种失败,但在所有 3 种情况下都失败。为什么
NaN
有时被忽略,有时则不然?

python pandas replace missing-data
6个回答
40
投票

原因是

max
的工作原理是将第一个值作为“迄今为止看到的最大值”,然后检查其他值以查看它是否大于迄今为止看到的最大值。但是
nan
的定义使得与它的比较总是返回 False --- 也就是说,
nan > 1
是 false,但
1 > nan
也是 false。

因此,如果您以

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


8
投票

在第一种情况下,您使用 numpy

max
函数,它知道如何处理
numpy.nan

在第二种情况下,您使用的是 python 的内置

max
函数。这个不知道怎么处理
numpy.nan
。据推测,这种效果是由于 (>, <, == etc.) of
numpy.nan
与浮点数的任何比较都会导致 False。实现
max
的一个明显方法是迭代可迭代对象(本例中的行)并检查每个值是否大于前一个,如果大于,则将其存储为最大值。由于当其中一个比较值是
numpy.nan
时,这种大于比较总是False,所以记录的最大值是你想要的数字还是
numpy.nan
取决于完全取决于第一个值是否为
numpy.nan


2
投票

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

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

结果是

2
,而

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

给出

np.nan
。原因是
max
函数会逐一遍历列表中的值,并进行如下比较:

if a > b

现在,如果我们看看与

nan
进行比较时得到的结果,
np.nan > 2
1 > np.nan
都给出
False
,因此在一种情况下,运行最大值被替换为
nan
,而在另一种情况下则不是.


1
投票

两者不同: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


0
投票

如果可能是inf问题,尝试更换它以及nan。

df[column] = df[column].replace([np.inf, -np.inf], 0.0)
df[column] = df[column].replace([np.nan, -np.nan], 0.0)

0
投票

使用 numpy.nanmax(list) 会导致排除 NaN。

© www.soinside.com 2019 - 2024. All rights reserved.