Python 按标签查找表中的第一个和最后一个非零列

Python 按标签查找表中的第一个和最后一个非零列,python,pandas,Python,Pandas,我有一个类似于下面的表格,其中日期列和一长串行。这些值是数字。我想添加一个新列,该列(1)是第一个显示日期索引的标签,(2)一个新列是最后一个显示日期索引的标签 dates = pd.date_range('20130101', periods=6) df = pd.DataFrame({dates[0] : list('000120'), dates[1] : list('011501'), dates[2] : list('11

我有一个类似于下面的表格,其中日期列和一长串行。这些值是数字。我想添加一个新列,该列(1)是第一个显示日期索引的标签,(2)一个新列是最后一个显示日期索引的标签

dates = pd.date_range('20130101', periods=6)
df = pd.DataFrame({dates[0] : list('000120'),
                dates[1] : list('011501'),
                dates[2] : list('111501'),
                dates[3] : list('011500'),
                dates[4] : list('011001'),
                dates[5] : list('010001')})
屈服

2013-01-01 2013-01-02 2013-01-03 2013-01-04 2013-01-05 2013-01-06 
0   0   0   1   0   0   0
1   0   1   1   1   1   1
2   0   1   1   1   1   0
3   1   5   5   5   0   0
4   2   0   0   0   0   0
5   0   1   1   0   1   1
其中,要添加的新列(仅作为示例显示)将是(A是第一个非零值,B是最后一个):

我尝试过使用s.nonzero、lamda函数的各种组合,并搜索了许多帖子,但没有找到好的答案


感谢您的帮助。

您可以先将DF转换为bool,然后在每行上找到max的列索引,这给出了开始日期,然后颠倒列的顺序,再次在每行上找到max的列索引,这给出了结束日期

df.assign(A=df.astype(int).astype(bool).idxmax(1),\
          B=df.astype(int).astype(bool)[df.columns[::-1]].idxmax(1))

创意方法
掩码
第一个有效索引

m = df.mask(df == '0')
fs = [pd.Series.first_valid_index, pd.Series.last_valid_index]
pd.concat([m.apply(f, 1) for f in fs], axis=1, keys=['A', 'B'])

           A          B
0 2013-01-03 2013-01-03
1 2013-01-02 2013-01-06
2 2013-01-02 2013-01-05
3 2013-01-01 2013-01-04
4 2013-01-01 2013-01-01
5 2013-01-02 2013-01-06
numpy
-fi

m = df.values != '0'
c = df.columns.values

first = c[m.argmax(1)]
last = c[m.shape[1] - m[:, ::-1].argmax(1) - 1]

pd.DataFrame(
    np.column_stack([first, last]),
    df.index, ['A', 'B']
)

           A          B
0 2013-01-03 2013-01-03
1 2013-01-02 2013-01-06
2 2013-01-02 2013-01-05
3 2013-01-01 2013-01-04
4 2013-01-01 2013-01-01
5 2013-01-02 2013-01-06

我会在堆叠后使用groupby执行此操作:

>>> d2 = df.astype(int)
>>> stacked = d2.where(d2 != 0).stack().reset_index()
>>> stacked.groupby("level_0")["level_1"].agg(['first', 'last'])
             first       last
level_0                      
0       2013-01-03 2013-01-03
1       2013-01-02 2013-01-06
2       2013-01-02 2013-01-05
3       2013-01-01 2013-01-04
4       2013-01-01 2013-01-01
5       2013-01-02 2013-01-06

@MaxU这是因为a)DF的类型是str,b)我们需要第一个非0元素而不是max元素。这是否正常:
DF.ne('0')。赋值(a=DF.idxmax(1),b=DF[DF.columns[::-1]]。idxmax(1))
>>> d2 = df.astype(int)
>>> stacked = d2.where(d2 != 0).stack().reset_index()
>>> stacked.groupby("level_0")["level_1"].agg(['first', 'last'])
             first       last
level_0                      
0       2013-01-03 2013-01-03
1       2013-01-02 2013-01-06
2       2013-01-02 2013-01-05
3       2013-01-01 2013-01-04
4       2013-01-01 2013-01-01
5       2013-01-02 2013-01-06