У меня есть матрица X
, два фрейма данных A
и B
и векторы индексов vec_a
и vec_b
. A
и B
содержат индексную переменную каждый, где значения соответствуют значениям в vec_a
и vec_b
. Помимо этого, A
и B
содержат столько значений, сколько столбцов в X
:
# original data
X <- matrix(rnorm(200),100,2)
# values to substract in data.frames
A <- data.frame(index_a = 1:4, value1 = rnorm(4), value2 = rnorm(4))
B <- data.frame(index_b = 1:4, value1 = rnorm(4), value2 = rnorm(4))
# indices, which values to substract (one for each row of X)
vec_a <- sample(1:4, nrow(X), replace = T)
vec_b <- sample(1:4, nrow(X), replace = T)
Я хочу добиться следующего: для каждой строки iii
в X
получить значения value1
и value2
из A
и B
на основе элементов iii
в векторах vec_a
и vec_b
. Затем вычтите эти значения из соответствующей строки в X
. Может показаться немного запутанным, но я надеюсь, что следующее решение проясняет цель:
# iterate over all rows of X
for(iii in 1:nrow(X)){
# get correct values
X_clean <- A[which(A$index_a == vec_a[iii]),-1] - # subtract correct A value
B[which(B$index_b == vec_b[iii]),-1] # subtract correct B value
# this intermediate step is necessary, otherwise we substract a data.frame from a matrix
X_clean <- as.numeric(X_clean)
# subtract from X
X[iii,] = X[iii,] - X_clean
}
Обратите внимание, что мы должны преобразовать в numeric
в моем решении l oop, иначе X
теряет класс matrix
, поскольку мы вычитаем data.frame
из matrix
. Мое решение работает нормально, пока вам не понадобится делать это для многих матриц, таких как A
и B
, и для миллионов наблюдений. Есть ли решение, которое не полагается на цикл по всем строкам?
EDIT
Спасибо, оба ответа значительно улучшают скорость кода. Я выбрал ответ StupidWolf, поскольку он более эффективен, чем использование data.table
:
Unit: microseconds
expr min lq mean median uq max neval cld
datatable 5557.355 5754.931 6052.402 5881.729 5975.386 14154.040 100 b
stupid.wolf 818.529 1172.840 1311.784 1187.593 1221.164 4777.743 100 a
loop 111748.790 115141.149 116677.528 116109.571 117085.048 156497.999 100 c