4

我有足够大的数据data.table,这是有史以来第一次需要,而且我对到目前为止它的简单程度感到非常满意。我今天已经阅读了相当多的文档(当然不是几乎全部),但我还没有找到这个。

我有一个由placeid和键控的数据表t2,另一列是t1。我想做的是在每一行中设置t1为最小值,按.0t2placeid

## 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语句一起工作,但是有没有更好的方法来使用 的i参数来做到这一点[.data.table

我希望其中一个能起作用,尽管稍微多想一点,他们没有这样做是有道理的:

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
4

1 回答 1

7

因为您知道它是由anddt键入(即排序)的,所以第一行 by是您希望更新的行。placeidt2placeid

mult = 'first'只有在加入唯一值时才能使用匹配第一行placeid

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 == min(t2) 的情况下您可能希望更新多行,您可以使用.I[t2==min(t2)]以下方式标识这些行placeid

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

请注意,这将比上面的二进制搜索选项慢。

于 2013-09-30T23:46:23.013 回答