我有一个类似于下面的表,其中日期为列和一长串行。值是数字。我想添加一个新列,其中(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是最后一个):
index 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
我尝试过使用s.nonzero,lamda函数的各种组合,搜索了很多帖子,但没有得到一个好的答案。
感谢您的帮助。
答案 0 :(得分:2)
您可以先将DF转换为bool,然后在每行上找到max的列索引,这将给出开始日期,然后反转列的顺序,再次找到每行的最大列索引,从而得到结束日期。
df.assign(A=df.astype(int).astype(bool).idxmax(1),\
B=df.astype(int).astype(bool)[df.columns[::-1]].idxmax(1))
答案 1 :(得分:0)
广告素材
mask
和first_valid_index
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
答案 2 :(得分:0)
我在堆叠后使用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