Операции со строками в выбранных столбцах на основе подстроки в data.table

Я хотел бы применить функцию к выбранным столбцам, которые соответствуют двум различным подстрокам. Я нашел этот пост, связанный с моим вопросом, но я не мог получить ответ оттуда.

Вот воспроизводимый пример с моей неудачной попыткой. Ради этого примера я хочу сделать построчную операцию, где я суммирую значения из всех столбцов, начинающихся со строки v и вычесть из среднего значения во всех столбцах, начиная с f,

Обновление: предлагаемое решение должно (а) использовать := оператор, чтобы максимально использовать data.table высокая производительность и (2) быть гибкими для других операций, а не mean а также sum, который я использовал здесь только для простоты

library(data.table)

# generate data
  dt <- data.table(id= letters[1:5],
                   v1= 1:5, 
                   v2= 1:5,
                   f1= 11:15,
                   f2= 11:15)

dt
#>    id v1 v2 f1 f2
#> 1:  a  1  1 11 11
#> 2:  b  2  2 12 12
#> 3:  c  3  3 13 13
#> 4:  d  4  4 14 14
#> 5:  e  5  5 15 15

# what I've tried
  dt[, Y := sum( .SDcols=names(dt) %like% "v" ) - mean( .SDcols=names(dt) %like% "f" ) by = id]

2 ответа

Решение

Мы melt набор данных в "длинный" формат, используя measure аргумент, получить разницу между sum из 'V' и mean из 'F', сгруппированные по 'ID', присоединиться on столбец id с исходным набором данных и назначить (:=) 'V1' как переменная 'Y'

dt[melt(dt, measure = patterns("^v", "^f"), value.name = c("v", "f"))[
         , sum(v) - mean(f), id], Y :=V1,  on = .(id)]

dt
#   id v1 v2 f1 f2  Y
#1:  a  1  1 11 11 -9
#2:  b  2  2 12 12 -8
#3:  c  3  3 13 13 -7
#4:  d  4  4 14 14 -6
#5:  e  5  5 15 15 -5

Или другой вариант с Reduce после создания столбцов index или 'v' и 'f'

nmv <- which(startsWith(names(dt), "v"))
nmf <- which(startsWith(names(dt), "f"))
l1 <- length(nmv)
dt[, Y := Reduce(`+`, .SD[, nmv, with = FALSE])- (Reduce(`+`, .SD[, nmf, with  = FALSE])/l1)]

rowSums а также rowMeans в сочетании с grep может сделать это.

dt$Y <- rowMeans(dt[,grep("f", names(dt)),with=FALSE]) - rowSums(dt[,grep("v", names(dt)),with=FALSE])
Другие вопросы по тегам