【问题标题】:Find index of the first and/or last value in a column that is not NaN查找非 NaN 列中第一个和/或最后一个值的索引
【发布时间】:2019-12-09 03:14:48
【问题描述】:

我正在处理来自钻孔的地下测量,其中每种测量类型涵盖不同的深度范围。在这种情况下,深度被用作索引。

我需要为每种测量类型找到第一次和/或最后一次出现的数据(非 NaN 值)的深度(索引)。

获取数据帧第一行或最后一行的深度(索引)很容易:df.index[0]df.index[-1]。诀窍在于找到任何给定列的第一个或最后一个非 NaN 出现的索引。

df = pd.DataFrame([[500, np.NaN, np.NaN,     25],
                   [501, np.NaN, np.NaN,     27],
                   [502, np.NaN,     33,     24],
                   [503,      4,     32,     18],
                   [504,     12,     45,      5],
                   [505,      8,     38, np.NaN]])
df.columns = ['Depth','x1','x2','x3']
df.set_index('Depth')

理想的解决方案会为第一次出现 x1 生成索引(深度)503,为第一次出现 x2 生成 502,为最后一次出现 x3 生成 504。

【问题讨论】:

  • 但是您如何确定'x3' 必须是last valid index 而不是first
  • 需要知道每个变量的第一个或最后一个有效索引。诀窍是当列具有NaN 值时,调用df 的第一行或最后一行索引不能用作解决方法。
  • 您的预期输出是什么样的?列表?数据框?系列?
  • 预期的输出最容易被可视化为列出每个变量及其最大和最小深度的数据框。能够以depth_df['x1']['min']depth_df['x3']['max'] 格式调用值也很方便。谢谢。
  • 向 anky_91 道歉,因为没有指定额外的任务。我面临的主要挑战是获取索引。将输出作为数据框是一个方便的奖励。我很高兴看到您和其他人完成任务的方法。

标签: python pandas numpy dataframe


【解决方案1】:

你可以agg

df.notna().agg({'x1':'idxmax','x2':'idxmax','x3':lambda x: x[::-1].idxmax()})
#df.notna().agg({'x1':'idxmax','x2':'idxmax','x3':lambda x: x[x].last_valid_index()})

x1    503
x2    502
x3    504

另一种方法是检查第一行是否为 nan 并根据该条件应用:

np.where(df.iloc[0].isna(),df.notna().idxmax(),df.notna()[::-1].idxmax())

[503, 502, 504]

【讨论】:

  • 我认为 OP 希望自动检测应用了 [::-1].idxmax() 的列和应用了 idxmax() 的列。
  • @QuangHoang 在此基础上添加了另一个解决方案
【解决方案2】:

IIUC

df.stack().groupby(level=1).head(1)
Out[619]: 
Depth    
500    x3    25.0
502    x2    33.0
503    x1     4.0
dtype: float64

【讨论】:

    【解决方案3】:

    first_valid_index() 和 last_valid_index() 都可以使用。

        >>> df
                 x1    x2    x3
        Depth
        500     NaN   NaN  25.0
        501     NaN   NaN  27.0
        502     NaN  33.0  24.0
        503     4.0  32.0  18.0
        504    12.0  45.0   5.0
        505     8.0  38.0   NaN
        >>> df["x1"].first_valid_index()
        503
        >>> df["x2"].first_valid_index()
        502
        >>> df["x3"].first_valid_index()
        500
        >>> df["x3"].last_valid_index()
        504
    

    【讨论】:

      【解决方案4】:

      如果我理解正确,让我们试试这个:

      pd.concat([df.apply(pd.Series.first_valid_index),
                 df.apply(pd.Series.last_valid_index)], 
                 axis=1, 
                 keys=['Min_Depth', 'Max_Depth'])
      

      输出:

            Min_Depth   Max_Depth
      x1          503         505
      x2          502         505
      x3          500         504
      

      或转置输出:

      pd.concat([df.apply(pd.Series.first_valid_index),
                 df.apply(pd.Series.last_valid_index)], 
                 axis=1, 
                 keys=['Min_Depth', 'Max_Depth']).T
      

      输出:

                  x1   x2   x3
      Min_Depth  503  502  500
      Max_Depth  505  505  504
      

      将 apply 与 func 列表一起使用:

      df.apply([pd.Series.first_valid_index, pd.Series.last_valid_index])
      

      输出:

                          x1   x2   x3
      first_valid_index  503  502  500
      last_valid_index   505  505  504
      

      稍微重命名:

      df.apply([pd.Series.first_valid_index, pd.Series.last_valid_index])\
        .set_axis(['Min_Depth', 'Max_Depth'], axis=0, inplace=False)
      

      输出:

                  x1   x2   x3
      Min_Depth  503  502  500
      Max_Depth  505  505  504
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-11-19
        • 2010-10-06
        • 1970-01-01
        • 1970-01-01
        • 2014-04-19
        • 2022-01-09
        • 1970-01-01
        • 2014-10-11
        相关资源
        最近更新 更多