【问题标题】:find the last value and the corresponding column name in a dataframe在数据框中找到最后一个值和相应的列名
【发布时间】:2018-03-09 16:45:18
【问题描述】:

在下面的数据框中,我想找出每一行中的最后一个值是什么,以及包含最后一个值的列名

df

 ID   c1   c4   c3    c2   c8   c7
 1     1    2    2    1    NaN  NaN
 2     1    2    1    NaN  NaN  NaN
 3     1    1    NaN  NaN  2     1

预期输出

 ID     Colname    lastValue
 1        c2         1
 2        c3         1
 3        c7         1

我的代码只能找到最后一个值

df['lastValue'] = df.ffill(axis = 1).iloc[:, -1]

我怎样才能找到 colname?

谢谢!

【问题讨论】:

    标签: python pandas indexing


    【解决方案1】:

    last_valid_index+lookup

    s=df.apply(pd.Series.last_valid_index, 1)
    df['Last']=df.lookup(s.index,s)
    df['Col']=s
    df
    Out[49]: 
       ID  c1  c4   c3   c2   c8   c7  Last Col
    0   1   1   2  2.0  1.0  NaN  NaN   1.0  c2
    1   2   1   2  1.0  NaN  NaN  NaN   1.0  c3
    2   3   1   1  NaN  NaN  2.0  1.0   1.0  c7
    

    【讨论】:

    • 不需要 lambda;可以直接参考pd.Series.last_valid_index
    • 您可能应该将s 添加到 df 中,否则您不会炫耀您拥有这些名称。
    • @DSM 是的,忘记那部分 :-) 非常感谢!
    【解决方案2】:

    沿第一轴取notnull掩码的argmax

    i = np.argmax(df.notnull().cumsum(1), axis=1)
    

    或者,

    i = (~np.isnan(df.values)).cumsum(1).argmax(1)  # pure numpy
    

    现在,

    df.columns[i]
    Index(['c2', 'c3', 'c7'], dtype='object')
    

    还有,

    df.values[np.arange(len(df)), i]
    array([1., 1., 1.])
    

    把它放在一起,

    pd.DataFrame({
         'ID' : df.ID, 
         'Colname' : df.columns[i], 
         'lastValue' : df.values[np.arange(len(df)), i]
    })
    
       ID Colname  lastValue
    0   1      c3        2.0
    1   2      c1        1.0
    2   3      c1        1.0
    

    【讨论】:

      【解决方案3】:

      numpy 可以做到这一点。 argmax algorithm@piRSquared 提供。

      A = df.values
      
      idx = A.shape[1] - (~np.isnan(A))[:, ::-1].argmax(1) - 1
      cols = df.columns[idx]
      
      res = pd.DataFrame({'ID': df['ID'], 'col': cols,
                          'last': A[range(A.shape[0]), idx]})
      
      #    ID col  last
      # 0   1  c2   1.0
      # 1   2  c3   1.0
      # 2   3  c7   1.0
      

      性能基准测试

      import random
      import pandas as pd
      
      %timeit cs(df)   # 10 loops, best of 3: 63.5 ms per loop
      %timeit jp(df)   # 100 loops, best of 3: 2.76 ms per loop
      %timeit wen(df)  # 10 loops, best of 3: 346 ms per loop
      
      # create dataframe with randomised np.nan
      
      df = pd.DataFrame(np.random.randint(0, 9, (1000, 1000)), dtype=float)
      df = df.rename(columns={0: 'ID'})
      ix = [(row, col) for row in range(df.shape[0]) for col in range(df.shape[1])]
      for row, col in random.sample(ix, int(round(.1*len(ix)))):
          df.iat[row, col] = np.nan
      
      def jp(df):
          A = df.values
      
          idx = A.shape[1] - (~np.isnan(A))[:, ::-1].argmax(1) - 1
          cols = df.columns[idx]
      
          res = pd.DataFrame({'ID': df['ID'], 'col': cols,
                              'last': A[range(A.shape[0]), idx]})
      
          return df
      
      def wen(df):
      
          s=df.apply(pd.Series.last_valid_index, 1)
          df['Last']=df.lookup(s.index,s)
          df['Col']=s
      
          return df
      
      def cs(df):
          i = (~np.isnan(df.values)).cumsum(1).argmax(1)  # pure numpy
      
          df = pd.DataFrame({
               'ID' : df.ID, 
               'Colname' : df.columns[i], 
               'lastValue' : df.values[np.arange(len(df)), i]
          })
          return df
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-03-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-09-05
        • 2019-03-07
        • 1970-01-01
        相关资源
        最近更新 更多