Использование mapply () для сравнения строк столбцов

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

Цель состоит в том, чтобы взять каждый столбец точек данных из Data_1 и сравнить его с обеими точками данных в столбце Data_2. Таким образом, Data_1 [1,1] будет сравниваться только с Data_2 [1,1] и Data_2 [2,1]. Для большей ясности, столбец data1 в Data_1 будет сравниваться только с элементами dataA в Data_2, поэтому перекрестные сравнение столбцов.

Данные_1: NxM

  data1       data2       data3      data4
-0.710003   -0.714271   -0.709946   -0.713645
-0.710458   -0.715011   -0.710117   -0.714157
-0.71071    -0.714048   -0.710235   -0.713515
-0.710255   -0.713991   -0.709722   -0.713972

Данные_2: PxQ

  dataA       dataB       dataC      dataD
-0.71097    -0.714059   -0.70928    -0.714059
-0.710343   -0.714576   -0.709338   -0.713644

Ранее я написал алгоритм на основе цикла for() while(), но время выполнения было слишком большим, чем исходные данные. Затем я перешел к логике, основанной на apply(), но все еще оставались циклы внутри функции, которую я вызывал, так что это не ускоряло код. Основываясь на моем предыдущем вопросе, я нахожу лучший способ сделать это с помощью mapply().

Часть, которую я не могу визуализировать, - это сравнение столбца с строкой и то, как mapply() будет перемещаться по нему рекурсивно. Как я могу использовать mapply() или lapply(), чтобы сделать это эффективно?

Любые предложения будут полезны, спасибо.


person Chetan Arvind Patil    schedule 05.07.2017    source источник


Ответы (2)


Рассмотрим вложенный семейный вызов apply:

  • mapply() - внешний: попарная итерация между соответствующими столбцами Data_1 и Data_2
  • sapply - inner: векторная итерация каждого значения в столбце Data_1 для сравнения элементов

Ниже проверяется, находится ли каждое значение Data_1 между двумя значениями каждого столбца Data_2:

Данные

txt = '  data1       data2       data3      data4
-0.710003   -0.714271   -0.709946   -0.713645
-0.710458   -0.715011   -0.710117   -0.714157
-0.71071    -0.714048   -0.710235   -0.713515
-0.710255   -0.713991   -0.709722   -0.713972'

Data_1 <- read.table(text=txt, header=TRUE)

txt = ' dataA       dataB       dataC      dataD
-0.71097    -0.714059   -0.70928    -0.714059
-0.710343   -0.714576   -0.709338   -0.713644'

Data_2 <- read.table(text=txt, header=TRUE)

Код

check_inbetween <- function(x,y){
  sapply(x, function(i) (i > y[1] & i < y[2]))
}

inbetween_matrix <- mapply(check_inbetween, Data_1, Data_2)

inbetween_matrix
#      data1 data2 data3 data4
# [1,] FALSE FALSE FALSE  TRUE
# [2,]  TRUE FALSE FALSE FALSE
# [3,]  TRUE FALSE FALSE FALSE
# [4,] FALSE FALSE FALSE  TRUE
person Parfait    schedule 07.07.2017
comment
Спасибо @Parfait, думаю, даже sweep() можно использовать - person Chetan Arvind Patil; 07.07.2017
comment
Возможно. Я никогда не использовал sweep(). И у этой реализации есть интересная вложенная развертка. Моя попытка, похоже, не повторяет функцию, а работает только с первыми столбцами наборов данных: sweep(as.matrix(Data_1), 1, as.matrix(Data_2), FUN = function(x,y) (x > y[1] & x < y[2]), check.margin = FALSE) - person Parfait; 07.07.2017

Это одно решение, основанное на data.table, но если вы используете data.frame или матрицу, его будет легко адаптировать. Чтобы достичь того, чего вы хотите, вы должны использовать один lapply над другим lapply. Верхний из них выполняет итерацию по столбцам, вызывая другой цикл по строкам.

library(data.table)

# it gets all elements of column 'j' to do diff computation
get_column_diff <- function(dt_1, dt_2, j){

        get_point_diff <- function(i){
                # it should return a vector with all differences 
                # in comparison of the point (i,j)
                unlist(dt_1[i, ..j]) - unlist(dt_2[, ..j])
        }


        i_rows <- 1:nrow(dt_1)
        lapply(X=i_rows, FUN=get_point_diff)

}

j_cols <- 1:ncol(Data_1)
lapply(FUN=get_column_diff, dt_1=Data_1, dt_2=Data_2, X=j_cols)

Функция возвращает список из списка, каждый элемент которого является результатом столбца, а его элемент - списком с результатом строки.

Что касается прироста скорости, я не могу сказать, насколько он будет быстрым без сравнения тестов, но, вероятно, он будет быстрее на любом цикле.

person Rafael Toledo    schedule 05.07.2017
comment
Спасибо @RafaelToledo. Ваш ответ помогает, но мне нужно больше узнать, как работают unlist() и list(). Также строка j_cols <- 1:ncol(dt_1) приведет к ошибке, не так ли? как dt_1 назначается Data_1 после этого? - person Chetan Arvind Patil; 06.07.2017
comment
моя плохая, обновлю, внутри ncol должно быть Data_1. Чтобы организовать свой вывод, вы должны сначала подумать, как вы этого хотите, потому что ваш вывод будет примерно таким, как (n x n) x n. - person Rafael Toledo; 06.07.2017