I've got data big enough to need data.table for the first time ever, and I've been very pleased with how easy it's been so far. I've read quite a bit of documentation today (certainly not nearly all of it), but I haven't found this yet.
I've got a data table keyed by placeid and t2, with one other column, t1. What I'd like to do is set t1 to 0 in each row where t2 is at its minimum, by 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"))
As t2 is in the key, the row I want to change is the first one within each grouping. I was able to get it to work with an ifelse statement, but is there a better way to do it using the i argument of [.data.table?
I was hoping one of these would work, though on thinking tiny bit more it makes sense that they don't:
dt[1, t1 := 0, by = placeid] ## changes only first row
dt[which.min(t2), t1 := 0, by = placeid] ## changes only global min row
What I did find to work (the result being the desired output):
dt[, t1 := ifelse(t2 == min(t2), 0, t1), by = placeid] # works
Because you know that dt is keyed (ie sorted) by placeid and t2, then the first row by placeid is the row you wish to update.
You can use mult = 'first' to match the first row only when joining on the unique values of 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
If there is the possibility that you wish to update more than one row in the case where there are multiple rows where t2 == min(t2), you can use .I[t2==min(t2)] to identify these rows by placeid
dt[dt[,.I[t2 == min(t2)],by='placeid']$V1, t1 := 0]
Note that this will be slower as than the binary search option above.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With