Как я могу заменить вложенный l oop, используя lapply в R? - PullRequest
1 голос
/ 21 февраля 2020

Добрый день,

Я разработал эту функцию R, которая хэширует данные в сегментах:

#   The used packages 
    library("pacman")
    pacman::p_load(dplyr, tidyr, devtools, MASS, pracma, mvtnorm, interval, intervals) 
    pacman::p_load(sprof, RDocumentation, helpRFunctions, foreach , philentropy , Rcpp , RcppAlgos) 


  hash<-function(v,p){
  if(dot(v,p)>0) return(1) else (0)   }

  LSH_Band<-function(data,K ){

  # We retrieve numerical columns of data 
  t<-list.df.var.types(data)
  df.r<-as.matrix(data[c(t$numeric,t$Intervals)])
  n=nrow(df.r)

  # we create K*K matrice using normal law
  rn=array(rnorm(K*K,0,1),c(K,K))
  # we create K*K matrice of integers using uniform law , integrs are unique in each column
  rd=unique.array(array(unique(ceiling(runif(K*K,0,ncol(df.r)))),c(K,K)))

  buckets<-array(NA,c(K,n)) 
    for (i in 1:K) {
      for (j in 1:n) {
        buckets[i,j]<-hash(df.r[j,][rd[,i]],rn[,i])
      }
    }   
  return(buckets)   
}
> df.r
  age height salaire.1 salaire.2
1  27    180         0      5000
2  26    178         0      5000
3  30    190      7000     10000
4  31    185      7000     10000
5  31    187      7000     10000
6  38    160     10000     15000
7  39    158     10000     15000
> LSH_Band(df.r, 3 )
     [,1] [,2] [,3] [,4] [,5] [,6] [,7]
[1,]    1    1    1    1    1    1    1
[2,]    1    1    0    0    0    0    0
[3,]    0    0    0    0    0    0    0

Функция точек - скалярное произведение двух векторов.

  • Моя функция L sh берет строку моих данных, затем часть полученной строки, используя df.r[j,][rd[,i]]. df.r[j,] - это строка данных в j-стиле.
  • rd[,i]: rd - это K * K-матрица целых чисел от 1 до ncol (df.r), каждый столбец матрицы содержит только уникальные целые числа.

  • rn[,i]: rn - матрица K * K, содержащая значения закона N (0,1).

  • В результирующем Таблица наблюдений представлена ​​в столбцах. У меня будет k рядов. Для последней строки я вычислю скалярное произведение между df.r[j,][rd[,K]] и rn[,K]. Я получу 1, если скалярное произведение положительно. rd[,K] и rn[,K] будут использоваться только для последней строки в итоговой таблице и для всех наблюдений в этой строке.

Мой вопрос:

Заменить ли циклы переменными i и j на a lapply function ?

Мои реальные данные будут большими, поэтому я задаю этот вопрос.

Спасибо!

1 Ответ

2 голосов
/ 21 февраля 2020

Следующее является слишком длинным комментарием, поэтому вот несколько указателей / проблем / замечаний:

  1. Прежде всего, я должен сказать, что изо всех сил пытаюсь понять, что LHS_Band делает Возможно, какой-то контекст поможет здесь.

  2. Я не понимаю назначения некоторых функций, таких как helpRFunctions::list.df.var.type, которые, кажется, просто возвращают имена столбцов data в list. Также обратите внимание, что t$Intervals возвращает NULL на основе предоставленных вами данных примера. Так что я не уверен, что там происходит.

  3. Я также не вижу смысла функции pracma::dot. Точечное произведение между двумя векторами может быть вычислено в основании R с использованием %*%. В действительности нет необходимости в дополнительном пакете.

  4. Функция hash может быть записана более компактно как

    hash <-  function(v, p) +(as.numeric(v %*% p) > 0)
    

    Это позволяет избежать условного if, который является медленным .


Несмотря на мое непонимание того, что вы пытаетесь сделать, вот несколько настроек вашего кода

hash <-  function(v, p) +(as.numeric(v %*% p) > 0)

LSH_Band <- function(data, K, seed = NULL) {

    # We retrieve numerical columns of data
    data <- as.matrix(data[sapply(data, is.numeric)])
    # we create K*K matrice using normal law
    if (!is.null(seed)) set.seed(seed)
    rn <- matrix(rnorm(K * K, 0, 1), nrow = K, ncol = K)
    # we create K*K matrice of integers using uniform law , integrs are unique in each column
    rd <- sapply(seq_len(K), function(col) sample.int(ncol(data), K))
    buckets <- matrix(NA, nrow = K, ncol = nrow(data))
    for (i in 1:K) {
        buckets[i, ] <- apply(data, 1, function(row) hash(row[rd[, i]], rn[, i]))
    }
    buckets
}
  1. Всегда добавляйте опцию для использования воспроизводимого seed при работе со случайными числами. Это сделает отладку намного проще.
  2. Вы можете заменить хотя бы один for l oop на apply (который при использовании MARGIN = 1 выполняет итерацию по строкам matrix (или array)).
  3. Я удалил все ненужные зависимости пакетов и заменил функциональность на базовые функции R.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...