为什么 max() 有时 return nan 有时会忽略它?
Why does max() sometimes return nan and sometimes ignores it?
这个问题的动机是我刚才给的
假设我有一个这样的数据框
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
有时被忽略,有时却没有?
在第一种情况下,您使用的是 numpy max
函数,它知道如何处理 numpy.nan
。
在第二种情况下,您使用的是 python 中的内置 max
函数。这个不知道怎么处理numpy.nan
。据推测,这种效果是由于 numpy.nan
与浮点数的任何比较(>、<、== 等)都会导致 False。实现 max
的一种明显方法是迭代可迭代对象(在本例中为行)并检查每个值是否大于前一个值,如果是,则将其存储为最大值。由于当比较的值之一为 numpy.nan
时,此大于比较将始终为 False,因此记录的最大值是否为您想要的数字或 numpy.nan
完全取决于第一个值是否为 numpy.nan
与否。
两者不同: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
原因是 max
的工作原理是将第一个值作为 "max seen so far",然后检查其他值以查看它是否大于目前看到的最大值。但是 nan
被定义为与它的比较总是 return False --- 也就是说,nan > 1
是 false 但 1 > nan
也是 false。
所以如果你从nan
开始作为数组中的第一个值,之后的每次比较都会检查是否some_other_value > nan
。这将始终为 false,因此 nan
将保留其 "max seen so far" 的位置。另一方面,如果 nan
不是第一个值,那么当达到第一个值时,比较 nan > max_so_far
将再次为假。但在这种情况下,这意味着当前 "max seen so far"(不是 nan
)将保持目前看到的最大值,因此 nan 将始终被丢弃。
这是由于列表中元素的排序。首先,如果您输入
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
,所以在一种情况下 运行 maximum 替换为 nan
而在另一个则不是。
这个问题的动机是
假设我有一个这样的数据框
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
有时被忽略,有时却没有?
在第一种情况下,您使用的是 numpy max
函数,它知道如何处理 numpy.nan
。
在第二种情况下,您使用的是 python 中的内置 max
函数。这个不知道怎么处理numpy.nan
。据推测,这种效果是由于 numpy.nan
与浮点数的任何比较(>、<、== 等)都会导致 False。实现 max
的一种明显方法是迭代可迭代对象(在本例中为行)并检查每个值是否大于前一个值,如果是,则将其存储为最大值。由于当比较的值之一为 numpy.nan
时,此大于比较将始终为 False,因此记录的最大值是否为您想要的数字或 numpy.nan
完全取决于第一个值是否为 numpy.nan
与否。
两者不同: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
原因是 max
的工作原理是将第一个值作为 "max seen so far",然后检查其他值以查看它是否大于目前看到的最大值。但是 nan
被定义为与它的比较总是 return False --- 也就是说,nan > 1
是 false 但 1 > nan
也是 false。
所以如果你从nan
开始作为数组中的第一个值,之后的每次比较都会检查是否some_other_value > nan
。这将始终为 false,因此 nan
将保留其 "max seen so far" 的位置。另一方面,如果 nan
不是第一个值,那么当达到第一个值时,比较 nan > max_so_far
将再次为假。但在这种情况下,这意味着当前 "max seen so far"(不是 nan
)将保持目前看到的最大值,因此 nan 将始终被丢弃。
这是由于列表中元素的排序。首先,如果您输入
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
,所以在一种情况下 运行 maximum 替换为 nan
而在另一个则不是。