I am trying to assign NA for specific values (0 and 99) to a group of variables (9 variables, from p05_1 to p05_9) using data.table. I don't get any error, but nothing happens when I use this code:
Here a short example:
v_1 <- c(0,0,1,2,3,4,4,99)
v_2 <- c(1,2,2,2,3,99,1,0)
dat <- data.table(v_1,v_2)
for(n in 1:9) {
char <- sprintf('p05_%s', n)
st[eval(parse(text=char)) %in% c(0,99), eval(parse(text=char)) := NA_integer_]
}
Best.
This is related to this question and answer
For the data.table
to kick into use eval in j
mode, the whole call should be eval(...).
Otherwise, your call is parsed as
`:=`(eval(parse(text=char)), NA_integer_)
Which won't be picked up as I'm trying to use eval in j by [.data.table
. I haven't tested for i
, but it could be safe to do this anyway
something like
for(n in 1:2) {
chari <- paste0(sprintf('v_%s' ,n), ' %in% c(0,99)')
charj <- sprintf('v_%s := NA_integer_', n)
dat[eval(parse(text=chari)), eval(parse(text=charj))]
}
should work. Note I have fudged the call to %in%
to avoid sprintf
giving an error using %
as a regular character.
An alternative to the eval(parse(text=
route, in this case :
for (n in 1:2) {
vnam = paste0("v_",n)
set(dat, which(dat[[vnam]]%in%c(0,99)), vnam, NA_integer_)
}
Note that [[
in base R doesn't take a copy of the column (it's copy-on-write), so that can be a good way to refer to a single column. Looping set
and [[
can be worth it if there are a lot of columns (say 10,000+).
Here's another alternative using the replace() function:
> dat[, lapply(list(v_1, v_2), function(x) replace(x, x %in% c(0, 99), NA_integer_))]
V1 V2
1: NA 1
2: NA 2
3: 1 2
4: 2 2
5: 3 3
6: 4 NA
7: 4 1
8: NA NA
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.