代码之家  ›  专栏  ›  技术社区  ›  Pratyush Goutam

如何在pandas中的DataFrame的每一行中找到包含第三个NaN值的列?

  •  1
  • Pratyush Goutam  · 技术社区  · 7 月前

    有人给我布置了一道作业题。以下是对我的问题的描述:

    在下面的单元格中,您有一个由10列浮点数组成的DataFrame df。每行中有5个条目是NaN值。 对于DataFrame的每一行,找到包含第三个NaN值的列。

    您应该返回一系列列标签: e, c, d, h, d

    nan = np.nan
    
    data = [[0.04,  nan,  nan, 0.25,  nan, 0.43, 0.71, 0.51,  nan,  nan],
            [ nan,  nan,  nan, 0.04, 0.76,  nan,  nan, 0.67, 0.76, 0.16],
            [ nan,  nan, 0.5 ,  nan, 0.31, 0.4 ,  nan,  nan, 0.24, 0.01],
            [0.49,  nan,  nan, 0.62, 0.73, 0.26, 0.85,  nan,  nan,  nan],
            [ nan,  nan, 0.41,  nan, 0.05,  nan, 0.61,  nan, 0.48, 0.68]]
    
    columns = list('abcdefghij')
    
    df = pd.DataFrame(data, columns=columns)
    
    # write a solution to the question here
    

    这是我的解决方案:

    result = df.apply(lambda row: row.isna().idxmax(), axis=1)
    print(result)
    

    我的代码返回 b, a, a, a, b, a ,而期望的输出为 e、 c、d、h、d 我的解决方案返回第一个NaN的索引,但根据问题,我希望每行中都有第三个NaN。我该怎么做?或者,是否有另一种解决方案可以提供所需的输出。

    1 回复  |  直到 7 月前
        1
  •  1
  •   mozway    7 月前

    idxmax 这是一种很好的方法,您可以将其与指示第三个NaN的掩码相结合,用于此用途 cumsum :

    m = df.isna()
    
    out = (m & m.cumsum(axis=1).eq(3)).idxmax(axis=1)
    

    输出:

    0    e
    1    c
    2    d
    3    h
    4    d
    dtype: object
    

    中间体:

    # m
           a     b      c      d      e      f      g      h      i      j
    0  False  True   True  False   True  False  False  False   True   True
    1   True  True   True  False  False   True   True  False  False  False
    2   True  True  False   True  False  False   True   True  False  False
    3  False  True   True  False  False  False  False   True   True   True
    4   True  True  False   True  False   True  False   True  False  False
    
    # m.cumsum(axis=1)
       a  b  c  d  e  f  g  h  i  j
    0  0  1  2  2  3  3  3  3  4  5
    1  1  2  3  3  3  4  5  5  5  5
    2  1  2  2  3  3  3  4  5  5  5
    3  0  1  2  2  2  2  2  3  4  5
    4  1  2  2  3  3  4  4  5  5  5
    
    # m.cumsum(axis=1).eq(3)
           a      b      c      d      e      f      g      h      i      j
    0  False  False  False  False   True   True   True   True  False  False
    1  False  False   True   True   True  False  False  False  False  False
    2  False  False  False   True   True   True  False  False  False  False
    3  False  False  False  False  False  False  False   True  False  False
    4  False  False  False   True   True  False  False  False  False  False
    
    # m & m.cumsum(axis=1).eq(3)
           a      b      c      d      e      f      g      h      i      j
    0  False  False  False  False   True  False  False  False  False  False
    1  False  False   True  False  False  False  False  False  False  False
    2  False  False  False   True  False  False  False  False  False  False
    3  False  False  False  False  False  False  False   True  False  False
    4  False  False  False   True  False  False  False  False  False  False
    

    或者,如果不能假设每行中有特定数量的NaN,则使用 melt + groupby.nth :

    N = 3
    out = (df.melt(ignore_index=False)              # reshape to long
             .loc[lambda x: x['value'].isna()]      # only keep NaNs
             .groupby(level=0)['variable'].nth(N-1) # keep 3rd row per group
          )
    

    输出:

    1    c
    2    d
    4    d
    0    e
    3    h
    Name: variable, dtype: object