Vasily A
Vasily A

Reputation: 8626

modify values of multiple columns in a table

So, here is my sample data:

library(data.table)
mydata <- fread(
"sample,neg1,neg2,neg3,gen1,gen2
sample1,   0,   1,   2,  30, 60
sample2,   1,   0,   1,  15, 30
sample3,   2,   1,   0,  10, 20
")

and in each row I want to subtract background (mean of "neg" columns). My current code is the following:

negatives <- names(mydata)[grep("^neg", names(mydata))] # "neg1" "neg2" "neg3"
mydata[, names(mydata)[-1]:={
  bg <- mean(unlist(.SD[, negatives, with=F]));
  .SD - as.integer(bg);
}, with=F, by=sample]

# mydata
#    sample neg1 neg2 neg3 gen1 gen2
#1: sample1   -1    0    1   29   59
#2: sample2    1    0    1   15   30
#3: sample3    1    0   -1    9   19

it does the job, but works quite slow on my real bigger table - I assume, it's because of using .SD. Is there better way to do this task? using set somehow?

(this question is very similar to my previous one: the source data is in another form here, so I could not find the way to apply the same solution with set, hope it will not be considered a duplicate).

Upvotes: 1

Views: 89

Answers (1)

akrun
akrun

Reputation: 887118

You could get the rowMeans of the "neg", columns ("val"), then update all the columns (subtracting from "val") of the dataset except the 1st using set.

 indx <- grep('^neg', names(mydata))
 val <- as.integer(rowMeans(mydata[, ..indx]))
 for(j in 2:ncol(mydata)){
  set(mydata, i=NULL, j=j, value=mydata[[j]]-val)
 }

 mydata
 #    sample neg1 neg2 neg3 gen1 gen2
 #1: sample1   -1    0    1   29   59
 #2: sample2    1    0    1   15   30
 #3: sample3    1    0   -1    9   19

Upvotes: 1

Related Questions