繁体   English   中英

在pandas数据帧的每一行中查找第一个和最后一个非零列

[英]Find first and last non-zero column in each row of a pandas dataframe

我根据NameDate使用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 

应该在参考下一个定义时将StartFinish添加到dataFrame:

  1. Start行第一非零值从开始Jan17Apr19
  2. 按顺序Finish第一个非零值,顺序为4月Apr19至1月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 as: 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  

我如何才能找到Finish从最后一列(参考非零值方向Apr19 )到第一个( Jan17 )?

first_valid_indexlast_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

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 ,然后在反向列上分别查找第一个和最后一个有效索引。

在你的情况下尝试与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]

在底层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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM