【问题标题】:Find first and last non-zero column in each row of a pandas dataframe在熊猫数据框的每一行中查找第一列和最后一个非零列
【发布时间】:2019-06-25 15:08:00
【问题描述】:

鉴于Name 和Date,我有DataFrame,单元格中的权重值:

Name        Jan17  Jun18  Dec18    Apr19  count 
Nick         0      1.7     3.7      0     2
Jack         0       0      2.8     3.5    2       
Fox          0      1.7      0       0     1
Rex          1.0     0      3.0     4.2    3
Snack        0       0      2.8     4.4    2
Yosee        0       0       0      4.3    1 
Petty        0.5    1.3     2.8     3.5    4 

Start 和 Finish 应该添加到 dataFrame 以引用下一个定义:

  1. Start 行中的第一个非零值从 Jan17 开始 列到Apr19
  2. Finish 中的第一个非零值 序列Apr19 直到Jan17

另外,如果行中只有一个非零值,那么Start 和Finish 是相同的。

为了找到行中的第一个非零元素,我尝试了data[col].keys, np.argmax(),它按预期工作。

date_col_list = ['Jan17','Jun18','Dec18', 'Apr19']

data['Start']=data[date_col_list].keys([np.argmax(data[date_col_list].values!=0, axis=1)]

结果是:

Name        Jan17  Jun18  Dec18    Apr19  count   Start 
Nick         0      1.7     3.7      0     2      Jun18        
Jack         0       0      2.8     3.5    2      Dec18           
Fox          0      1.7      0       0     1      Jun18    
Rex          1.0     0      3.0     4.2    3      Jan18    
Snack        0       0      2.8     4.4    2      Dec18    
Yosee        0       0       0      4.3    1      Apr19     
Petty        0.5    1.3     2.8     3.5    4      Jan17

要检测 Finish 列的值,我尝试使用: np.apply_along_axis 为: def func_X(i): return np.argmax(np.where(i!=0))

np.apply_along_axis(func1d = func_X, axis=1, arr=data[date_col_list].values)

结果错误: 'tuple' object has no attribute 'argmax'

预期的数据框是:

Name        Jan17  Jun18  Dec18    Apr19  count   Start  Finish
Nick         0      1.7     3.7      0     2      Jun18   Dec18     
Jack         0       0      2.8     3.5    2      Dec18   Apr19        
Fox          0      1.7      0       0     1      Jun18   Jun18 
Rex          1.0     0      3.0     4.2    3      Jan18   Apr19 
Snack        0       0      2.8     4.4    2      Dec18   Apr19 
Yosee        0       0       0      4.3    1      Apr19   Apr19  
Petty        0.5    1.3     2.8     3.5    4      Jan17   Apr19  

如何在从最后一列 (Apr19) 到第一列 (Jan17) 的方向上找到非零值的 Finish?

【问题讨论】:

    标签: python pandas dataframe argmax


    【解决方案1】:

    first_valid_index 和 last_valid_index

    d = df.mask(df == 0).drop(['Name', 'count'], 1)
    df.assign(
        Start=d.apply(pd.Series.first_valid_index, 1),
        Finish=d.apply(pd.Series.last_valid_index, 1)
    )
    
        Name  Jan17  Jun18  Dec18  Apr19  count  Start Finish
    0   Nick    0.0    1.7    3.7    0.0      2  Jun18  Dec18
    1   Jack    0.0    0.0    2.8    3.5      2  Dec18  Apr19
    2    Fox    0.0    1.7    0.0    0.0      1  Jun18  Jun18
    3    Rex    1.0    0.0    3.0    4.2      3  Jan17  Apr19
    4  Snack    0.0    0.0    2.8    4.4      2  Dec18  Apr19
    5  Yosee    0.0    0.0    0.0    4.3      1  Apr19  Apr19
    6  Petty    0.5    1.3    2.8    3.5      4  Jan17  Apr19
    

    stack 然后groupby

    d = df.mask(df == 0).drop(['Name', 'count'], 1)
    def fl(s): return s.xs(s.name).index[[0, -1]]
    s, f = d.stack().groupby(level=0).apply(fl).str
    df.assign(Start=s, Finish=f)
    
        Name  Jan17  Jun18  Dec18  Apr19  count  Start Finish
    0   Nick    0.0    1.7    3.7    0.0      2  Jun18  Dec18
    1   Jack    0.0    0.0    2.8    3.5      2  Dec18  Apr19
    2    Fox    0.0    1.7    0.0    0.0      1  Jun18  Jun18
    3    Rex    1.0    0.0    3.0    4.2      3  Jan17  Apr19
    4  Snack    0.0    0.0    2.8    4.4      2  Dec18  Apr19
    5  Yosee    0.0    0.0    0.0    4.3      1  Apr19  Apr19
    6  Petty    0.5    1.3    2.8    3.5      4  Jan17  Apr19
    

    【讨论】:

      【解决方案2】:

      在您的情况下,尝试使用 dot 进行不同的操作

      s=df.loc[:,'Jan17':'Apr19'].ne(0)
      s=s.dot(s.columns+',').str[:-1].str.split(',')
      s.str[0],s.str[-1]
      Out[899]: 
      (0    Jun18
       1    Dec18
       2    Jun18
       3    Jan17
       4    Dec18
       5    Apr19
       6    Jan17
       dtype: object, 0    Dec18
       1    Apr19
       2    Jun18
       3    Apr19
       4    Apr19
       5    Apr19
       6    Apr19
       dtype: object)
       #df['Start'],df['End']=s.str[0],s.str[-1]
      

      【讨论】:

        【解决方案3】:

        在底层array上使用cumsum

        m = df.drop(['Name', 'count'], axis=1)
        u = m.to_numpy().cumsum(1)
        
        start = (u!=0).argmax(1)
        end = u.argmax(1)
        
        df.assign(start=m.columns[start], end=m.columns[end])
        

            Name  Jan17  Jun18  Dec18  Apr19  count  start    end
        0   Nick    0.0    1.7    3.7    0.0      2  Jun18  Dec18
        1   Jack    0.0    0.0    2.8    3.5      2  Dec18  Apr19
        2    Fox    0.0    1.7    0.0    0.0      1  Jun18  Jun18
        3    Rex    1.0    0.0    3.0    4.2      3  Jan17  Apr19
        4  Snack    0.0    0.0    2.8    4.4      2  Dec18  Apr19
        5  Yosee    0.0    0.0    0.0    4.3      1  Apr19  Apr19
        6  Petty    0.5    1.3    2.8    3.5      4  Jan17  Apr19
        

        【讨论】:

          【解决方案4】:

          idxmax

          mask = df.drop(['Name', 'count'], axis=1) > 0
          df.assign(start=mask.idxmax(axis=1), end=mask.iloc[:,::-1].idxmax(axis=1))
          
              Name  Jan17  Jun18  Dec18  Apr19  count  start    end
          0   Nick    0.0    1.7    3.7    0.0      2  Jun18  Dec18
          1   Jack    0.0    0.0    2.8    3.5      2  Dec18  Apr19
          2    Fox    0.0    1.7    0.0    0.0      1  Jun18  Jun18
          3    Rex    1.0    0.0    3.0    4.2      3  Jan17  Apr19
          4  Snack    0.0    0.0    2.8    4.4      2  Dec18  Apr19
          5  Yosee    0.0    0.0    0.0    4.3      1  Apr19  Apr19
          6  Petty    0.5    1.3    2.8    3.5      4  Jan17  Apr19
          

          删除不相关的列,然后首先在列上使用idxmax,然后在反转的列上分别找到第一个和最后一个有效索引。

          【讨论】:

            猜你喜欢
            • 2019-04-07
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-10-27
            • 1970-01-01
            相关资源
            最近更新 更多