如何更新每个分组中的单行?

4
我第一次使用data.table处理大量数据,迄今为止,我非常满意它的易用性。今天我已经阅读了相当多的文档(当然不是全部),但我还没有找到这个问题的解决方法。
我的数据表以placeid和t2为关键字,有一个其他列t1。我想做的是,在每行中将t1设置为0,其中t2是最小值,按placeid分组。
## Sample data
set.seed(47)
require(data.table)
dt <- data.table(placeid = rep(letters[1:3], each = 3), t1 = runif(9), t2 = runif(9))
setkeyv(dt, cols=c("placeid", "t2"))

作为“t2”在键中,我想要更改的行是每个分组内的第一行。我能够使用“ifelse”语句使其正常工作,但是是否有更好的方法使用“[.data.table”的“i”参数来完成它?
我希望这些中的一个能够奏效,虽然再想一想,它们不起作用是有道理的:
dt[1, t1 := 0, by = placeid] ## changes only first row
dt[which.min(t2), t1 := 0, by = placeid] ## changes only global min row

我发现以下方法可行(结果为期望的输出):
dt[, t1 := ifelse(t2 == min(t2), 0, t1), by = placeid]  # works

1
这里还有另一种可能性:dt[,t1:=t1*(t2!=min(t2)),by='placeid'] - Josh O'Brien
1个回答

7
因为你知道dt是根据placeidt2进行排序的,所以第一行是你想要更新的placeid行。
当在唯一值placeid上进行连接时,您可以使用mult = 'first'来仅匹配第一行。
dt[unique(placeid),t1 := 0,mult='first']
dt
#    placeid        t1         t2
# 1:       a 0.0000000 0.13879758
# 2:       a 0.7615020 0.70198720
# 3:       a 0.9769620 0.92489205
# 4:       b 0.0000000 0.16219364
# 5:       b 0.6914124 0.50603611
# 6:       b 0.5735444 0.59930702
# 7:       c 0.0000000 0.03094497
# 8:       c 0.4689460 0.40050280
# 9:       c 0.3890619 0.90197352

如果存在这样的情况,即在t2等于最小值的多个行中希望更新不止一行,则可以使用.I[t2==min(t2)]通过placeid标识这些行。

dt[dt[,.I[t2 == min(t2)],by='placeid']$V1, t1 := 0]

请注意,这种方法比上面的二分查找选项要慢。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接