首页 > 解决方案 > 添加新列,每行作为另一列的前一个组值

问题描述

我有一个数据框:

data = pd.DataFrame({'start':['2020-08-01','2020-08-02','2020-08-03','2020-08-04','2020-08-05','2020-08-06','2020-08-07','2020-08-08'],
                     'end':['2020-08-03','2020-08-03','2020-08-06','2020-08-06','2020-08-06','2020-08-07','2020-08-08','2020-08-08'],
                     'score':[74, 81, 38, 49, 79, 17, 53, 69]})

我需要添加一个新列,其中每一行都是end其前一组的日期。所需的数据框是:

         start         end    prev_end  score
0   2020-08-01  2020-08-03         NaN     74
1   2020-08-02  2020-08-03         NaN     81
2   2020-08-03  2020-08-06  2020-08-03     38
3   2020-08-04  2020-08-06  2020-08-03     49
4   2020-08-05  2020-08-06  2020-08-03     79
5   2020-08-06  2020-08-07  2020-08-06     17
6   2020-08-07  2020-08-08  2020-08-07     53
7   2020-08-08  2020-08-08  2020-08-07     69

这样我就可以标记start大于prev_end日期的行,如下所示:

         start         end    prev_end  mark  score
0   2020-08-01  2020-08-03         NaN     0     74
1   2020-08-02  2020-08-03         NaN     0     81
2   2020-08-03  2020-08-06  2020-08-03     0     38
3   2020-08-04  2020-08-06  2020-08-03     1     49
4   2020-08-05  2020-08-06  2020-08-03     1     79
5   2020-08-06  2020-08-07  2020-08-06     0     17
6   2020-08-07  2020-08-08  2020-08-07     0     53
7   2020-08-08  2020-08-08  2020-08-07     1     69

有没有简单的解决方案来做到这一点?还是一些无需创建的直接方式prev_end?非常感谢!

标签: pythonpandasdataframe

解决方案


您可以通过索引从列中删除重复项并通过省略第一个值end创建字典并传递给, 用于列比较 by并转换为by :zipSeries.mapmarkSeries.gt0,1Series.view

data[['start','end']] = data[['start','end']].apply(pd.to_datetime)

s = data['end'].drop_duplicates()
data['prev_end'] = data['end'].map(dict(zip(s[1:], s)))

data['mark'] = data['start'].gt(data['prev_end']).view('i1')
print (data)
       start        end  score   prev_end  mark
0 2020-08-01 2020-08-03     74        NaT     0
1 2020-08-02 2020-08-03     81        NaT     0
2 2020-08-03 2020-08-06     38 2020-08-03     0
3 2020-08-04 2020-08-06     49 2020-08-03     1
4 2020-08-05 2020-08-06     79 2020-08-03     1
5 2020-08-06 2020-08-07     17 2020-08-06     0
6 2020-08-07 2020-08-08     53 2020-08-07     0
7 2020-08-08 2020-08-08     69 2020-08-07     1

如果列的顺序很重要,则可以DataFrame.insert通过按预期顺序传递列列表来使用或更改顺序:

data[['start','end']] = data[['start','end']].apply(pd.to_datetime)

s = data['end'].drop_duplicates()
data.insert(2, 'prev_end', data['end'].map(dict(zip(s[1:], s))))
data.insert(3, 'mark', data['start'].gt(data['prev_end']).view('i1'))

print (data)
       start        end   prev_end  mark  score
0 2020-08-01 2020-08-03        NaT     0     74
1 2020-08-02 2020-08-03        NaT     0     81
2 2020-08-03 2020-08-06 2020-08-03     0     38
3 2020-08-04 2020-08-06 2020-08-03     1     49
4 2020-08-05 2020-08-06 2020-08-03     1     79
5 2020-08-06 2020-08-07 2020-08-06     0     17
6 2020-08-07 2020-08-08 2020-08-07     0     53
7 2020-08-08 2020-08-08 2020-08-07     1     69

data = data[['start', 'end', 'prev_end', 'mark', 'score']]

推荐阅读