tobinz
tobinz

Reputation: 335

Modify rows of multiple data.table files

I have two datasets dt1 and dt2:

N = 100
dt1 <- data.table(x = rnorm(N), y=rnorm(N))
dt2 <- data.table(x = rnorm(N), z=rnorm(N))
list_dt <- list(dt1 = dt1, dt2 = dt2)

If y and z are negative, they are forced to be 0. I implement it by this:

naming <- c("y","z")
for (i in seq_along(naming)){
   list_dt[[i]] <- setDT( list_dt[[i]] )[ noquote(naming[i]) < 0, noquote(naming[i]) := 0  ] 
}

But it's not working. I see the problem may be owing to the function noquote(), but I don't know why. Any advice is appreciated!

Upvotes: 1

Views: 67

Answers (4)

Peace Wang
Peace Wang

Reputation: 2419

Based on your code, it can be corrected as

naming <- c("y","z")
for (i in seq_along(naming)){
     list_dt[[i]][,noquote(naming[i]) := 
                   fifelse(get(naming[i]) < 0, 0, get(naming[i]))] 
}

Upvotes: 2

Ronak Shah
Ronak Shah

Reputation: 389265

Using lapply :

library(data.table)

naming <- c("y","z")

lapply(list_dt, function(x) {
  cols <- intersect(names(x), naming)
  x[get(cols) < 0, (cols) := 0]
})

Upvotes: 2

Kestutis Vinciunas
Kestutis Vinciunas

Reputation: 63

lapply(list_dt,
       function(.x){
         .x[, lapply(.SD,
                     function(x) fifelse(x<0, 0, x)) , 
            by = "x"]     
       }
)    

Upvotes: 2

tmfmnk
tmfmnk

Reputation: 40171

An option using dplyr and purrr could be:

map(.x = list_dt, 
    ~ .x %>%
     mutate(across(any_of(c("y", "z")), ~ pmax(., 0))))

Upvotes: 1

Related Questions