Как избежать циклов for, если мы хотим условно добавить столбцы по ссылке? (условие оценивается отдельно в каждой строке) - PullRequest
2 голосов
/ 18 июня 2020

У меня есть таблица data.table с множеством пронумерованных столбцов. В качестве более простого примера у меня есть следующее:

dat <- data.table(cbind(col1=sample(1:5,10,replace=T),
                            col2=sample(1:5,10,replace=T),
                            col3=sample(1:5,10,replace=T),
                            col4=sample(1:5,10,replace=T)),
oneMoreCol='a')

Я хочу создать новый столбец следующим образом: в каждой строке мы добавляем значения в столбцы из col1-col4, если значение не NA или 1.

Мой текущий код для этого имеет два цикла for, что явно не подходит для этого:

for(i in 1:nrow(dat)){
  dat[i,'sumCol':={temp=0;
  for(j in 1:4){if(!is.na(dat[i,paste0('col',j),with=F])&
                   dat[i,paste0('col',j),with=F]!=1
                                 ){temp=temp+dat[i,paste0('col',j),with=F]}};
  temp}]}

Я был бы признателен за любой совет, как удалить эти циклы for . Мой код работает на более крупной таблице data.table, и его выполнение занимает много времени.

1 Ответ

2 голосов
/ 18 июня 2020

Возможное решение:

dat[, sumCol := rowSums(.SD * (.SD != 1), na.rm = TRUE), .SDcols = col1:col4]

, что дает:

> dat
    col1 col2 col3 col4 oneMoreCol sumCol
 1:    4    5    5    3          a     17
 2:    4    5   NA    5          a     14
 3:    2    3    4    3          a     12
 4:    1    2    3    4          a      9
 5:    4    3   NA    5          a     12
 6:    2    2    1    4          a      8
 7:   NA    2   NA    5          a      7
 8:    4    2    2    4          a     12
 9:    4    1    5    4          a     13
10:    2    1    5    1          a      7

Используемые данные:

set.seed(20200618)
dat <- data.table(cbind(col1=sample(c(NA, 1:5),10,replace=T),
                        col2=sample(1:5,10,replace=T),
                        col3=sample(c(1:5,NA),10,replace=T),
                        col4=sample(1:5,10,replace=T)),
                  oneMoreCol='a')
...