I need to create a new column in my data.table
dt
. This column will contain data from a data.frame
df
. My data is as follows:
library(data.table)
df <- data.frame(letter = LETTERS[1:9], number = 1:9)
dt <- data.table(value = c(0.5, 2.5, 6, 8.5, 4.5, 1.6, 1.3, 7.8, 9.2))
Now, I want to create a new column called col
in dt
based on the value of value
that will contain the letter
from df
which corresponds to the smallest larger or equal value of number
than value
. To give an example, the first row of column col
should contain A
since 1
(that is the number
column from df
that corresponds to A
) is the smallest value larger than or equal to 0.5, the value
in the first row of dt
. I tried the following code:
dt[, col := df[which(value <= df[, 2])[1], 1]]
but that puts A
to all rows. I could this with data.frame
as follows:
setDF(dt)
for(i in 1:nrow(dt)) {
dt$col[i] <- as.character(df[which(dt$value[i] <= df[, 2])[1], 1])
}
which produces the desired output of A, C, F, I, E, B, B, H, and NA. How could I do this with data.table
?
You can do this with a rolling join. However, number
and value
will both have to be of the same type first:
setDT(df)
df[, number := as.numeric(number)]
dt[, v := df[.SD, on=.(number = value), roll=-Inf, letter]]
value col v
1: 0.5 A A
2: 2.5 C C
3: 6.0 F F
4: 8.5 I I
5: 4.5 E E
6: 1.6 B B
7: 1.3 B B
8: 7.8 H H
9: 9.2 NA NA
To catch problems like this (merging double with integer) more easily, use verbose
:
# when number is still an int...
df[dt, on=.(number = value), roll=-Inf, verbose=TRUE]
Calculated ad hoc index in 0 secs
Coercing double column i.'value' to integer to match type of x.'number'. Please avoid coercion for efficiency.
Starting bmerge ...done in 0 secs
letter number
1: A 0
2: B 2
3: F 6
4: H 8
5: D 4
6: A 1
7: A 1
8: G 7
9: I 9
You can set verbosity on for the full R session with options(datatable.verbose = TRUE)
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.