如何查找:每列中的第一个非NaN值是否是DataFrame中该列的最大值?

时间:2018-09-15 22:49:17

标签: python pandas max nan

例如:

      0     1
0  87.0   NaN
1   NaN  99.0
2   NaN   NaN
3   NaN   NaN
4   NaN  66.0
5   NaN   NaN
6   NaN  77.0
7   NaN   NaN
8   NaN   NaN
9  88.0   NaN

我的预期输出是:[False, True],因为87是第一个!NaN值,但不是列0中的最大值。 99是第一个!NaN值,并且实际上是该列中的最大值。

5 个答案:

答案 0 :(得分:6)

选项a):只需对groupbyfirst

(可能不是100%reliable

df.groupby([1]*len(df)).first()==df.max()
Out[89]: 
       0     1
1  False  True

选项b)bfill

或使用bfill(用该列中的向后值填充任何NaN值,然后bfill之后的第一行是第一个非NaN值)

df.bfill().iloc[0]==df.max()
Out[94]: 
0    False
1     True
dtype: bool

选项c)stack

df.stack().reset_index(level=1).drop_duplicates('level_1').set_index('level_1')[0]==df.max()
Out[102]: 
level_1
0    False
1     True
dtype: bool

选项d)idxmaxfirst_valid_index

df.idxmax()==df.apply(pd.Series.first_valid_index)
Out[105]: 
0    False
1     True
dtype: bool

选项e)(来自Pir)idxmaxisna

df.notna().idxmax() == df.idxmax()     
Out[107]: 
0    False
1     True
dtype: bool

答案 1 :(得分:4)

使用纯numpy(我认为这非常快)

>>> np.isnan(df.values).argmin(axis=0) == df.fillna(-np.inf).values.argmax(axis=0)
array([False,  True])

想法是比较第一个非Nan的索引是否也是argmax的索引。

时间

df = pd.concat([df]*1000).reset_index(drop=True) # setup

%timeit np.isnan(df.values).argmin(axis=0) == df.fillna(-np.inf).values.argmax(axis=0)
207 µs ± 8.83 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit df.groupby([1]*len(df)).first()==df.max()
9.78 ms ± 339 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit df.bfill().iloc[0]==df.max()
824 µs ± 47.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit df.stack().reset_index(level=1).drop_duplicates('level_1').set_index('level_1')[0]==df.max()
3.55 ms ± 249 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit df.idxmax()==df.apply(pd.Series.first_valid_index)
1.5 ms ± 25 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit df.values[df.notnull().idxmax(), np.arange(df.shape[1])] == df.max(axis=0)
1.13 ms ± 14.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit df.values[(~np.isnan(df.values)).argmax(axis=0), np.arange(df.shape[1])] == df.max(axis=0).values
450 µs ± 20.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

答案 2 :(得分:3)

我们可以在此处使用numpy的{​​{1}}作为有效的解决方案:

nanmax

a = df.values
np.nanmax(a, 0) == a[np.isnan(a).argmin(0), np.arange(a.shape[1])]

时间 (此处提供了很多选项):


功能

array([False,  True])

设置

def chris(df):
    a = df.values
    return np.nanmax(a, 0) == a[np.isnan(a).argmin(0), np.arange(a.shape[1])]

def bradsolomon(df):
    df.values[df.notnull().idxmax(), np.arange(df.shape[1])] == df.max(axis=0).values

def wen1(df):
    return df.groupby([1]*len(df)).first()==df.max()

def wen2(df):
    return df.bfill().iloc[0]==df.max()

def wen3(df):
    return df.idxmax()==df.apply(pd.Series.first_valid_index)

def rafaelc(df):
    return np.isnan(df.values).argmin(axis=0) == df.fillna(-np.inf).values.argmax(axis=0)

def pir(df):
    return df.notna().idxmax() == df.idxmax()

结果

enter image description here

答案 3 :(得分:2)

您可以对底层的Numpy数组执行类似于Wens的回答:

>>> df.values[df.notnull().idxmax(), np.arange(df.shape[1])] == df.max(axis=0).values
array([False,  True])

df.max(axis=0)给出列级最大值。

左侧索引df.values是2d数组,使其成为1d数组,并将其逐元素与每列的最大值进行比较。

如果从右侧排除.values,则结果将只是熊猫系列:

>>> df.values[df.notnull().idxmax(), np.arange(df.shape[1])] == df.max(axis=0)
0    False
1     True
dtype: bool

答案 4 :(得分:0)

发布问题后,我想到了这一点:

<div class="content">
  <span class="linedown1"></span>
  <span class="linedown2"></span>
</div>

这似乎可行,但还不确定!