pandas转换为匹配最大值的布尔列

0 投票
1 回答
502 浏览
提问于 2025-04-18 13:46

在帮忙解答这个帖子 从现有数据集中生成新的时间序列索引 时,我自己也遇到了一个问题,假设有一个像这样的数据表:

In [44]: newdf
Out[44]: 
           date
id             
3001 2000-01-01
3001 2000-01-02
3001 2000-01-03
3001 2000-01-04
3001 2000-01-05
3849 2001-01-05
3849 2001-01-06
3849 2001-01-07
3849 2001-01-08
8927 2006-01-06
8927 2006-01-07
8927 2006-01-08
8927 2006-01-09

我想添加一个第三列,这一列在每一行都是零,只有每个ID的最后一个日期那一行是1。也就是说,对于每个结束日期,它的值应该是1。

我修改了我的回答来实现这个:

In [32]: b = newdf.reset_index().groupby( 'id').date.transform( 
lambda ii : ii.max())
In [37]: newdf['new_col'] = (newdf.date == b).astype(int) 

但是我不知道为什么我不能直接这样做:

newdf['new_col'] = newdf.reset_index().groupby( 'id').date.transform( lambda ii : ii == ii.max())

这样做会出现错误:

ValueError: new type not compatible with array.

1 个回答

0

我稍微改了一下,效果不错:

newdf['new_col'] = [v for v in newdf.reset_index().groupby( 'id').date.transform( lambda ii : ii == ii.max())]

或者,你也可以这样做:

df2 = newdf.reset_index()
df2['new_col'] = df2.groupby( 'id').date.transform( lambda ii : ii == ii.max())

你用的 ....groupby( 'id').date.transform( lambda ii : ii == ii.max()) 这段代码的结果是一个序列,但这个序列的索引是从0到数据框长度的范围。当你尝试用 newdf['new_col'] = new series 这行代码时,它会试图匹配索引。如果把序列转换成列表,pandas就会忽略这些索引,或者先重置索引也能让索引对齐。

顺便提一下,为了提高速度,你的数据看起来是按 ('id','date') 排序的,这样的特性很好用(因为在处理大数据框时,groupby会变得很慢):

# guarantee sorting
newdf.reset_index(inplace=True).sort(('id','date'), inplace=True).set_index('id')
# init new column
newdf['is_last'] = 0
curr_id = None
for i, (id, row) in enumerate(newdf.iterrows()):
    if i > 0 and id != curr_id:
        newdf.iloc[i-1]['is_last'] = 1

撰写回答