web-dev-qa-db-fra.com

Un moyen plus rapide des vecteurs de sous-ensemble au hasard dans une liste?

Je cherche une solution rapide pour sous-servir de manière aléatoire des vecteurs imbriqués dans une liste.

Si nous simulons les données suivantes, nous obtenons une liste l qui contient 3 millions de vecteurs à l'intérieur, chacun est de longueur 5. Mais je veux que la longueur de chaque vecteur varie. J'ai donc pensé que je devrais appliquer une fonction qui sous-tia au hasard chaque vecteur. Le problème est que cette méthode n'est pas aussi rapide que je souhaite.

Simuler les données: la liste l

library(stringi)

set.seed(123)
vec_n <- 15e6
vec_vals  <- 1:vec_n
vec_names <- stringi::stri_Rand_strings(vec_n, 5)

my_named_vec <- setNames(vec_vals, vec_names)

split_func <- function(x, n) {
  unname(split(x, rep_len(1:n, length(x))))
}

l <- split_func(my_named_vec, n = vec_n / 5)

head(l)
#> [[1]]
#>    HmPsw    Qk8NP    Quo3T    8f0GH    nZmjN 
#>        1  3000001  6000001  9000001 12000001 
#> 
#> [[2]]
#>    2WtYS    ZaHFl    6YjId    jbGuA    tAG65 
#>        2  3000002  6000002  9000002 12000002 
#> 
#> [[3]]
#>    xSgZ6    jM5Uw    ujPOc    CTV5F    5JRT5 
#>        3  3000003  6000003  9000003 12000003 
#> 
#> [[4]]
#>    tF2Kx    r4ZCI    Ooklo    VOLHU    M6z6H 
#>        4  3000004  6000004  9000004 12000004 
#> 
#> [[5]]
#>    tgdze    w8d1B    FYERK    jlClo    NQfsF 
#>        5  3000005  6000005  9000005 12000005 
#> 
#> [[6]]
#>    hXaH9    gsY1u    CjBwC    Oqqty    dxJ4c 
#>        6  3000006  6000006  9000006 12000006

Maintenant que nous avons l, je souhaite sous-servir chaque vecteur au hasard: ce qui signifie que le nombre d'éléments étant sous-partage (par vecteur) sera aléatoire. Donc, une option est de définir la fonction d'utilité suivante:

randomly_subset_vec <- function(x) {
  my_range <- 1:length(x)
  x[-sample(my_range, sample(my_range))]
}

lapply(head(l), randomly_subset_vec)
#> [[1]]
#>   Quo3T 
#> 6000001 
#> 
#> [[2]]
#>   6YjId   jbGuA 
#> 6000002 9000002 
#> 
#> [[3]]
#>   xSgZ6   jM5Uw   ujPOc   CTV5F 
#>       3 3000003 6000003 9000003 
#> 
#> [[4]]
#>   Ooklo 
#> 6000004 
#> 
#> [[5]]
#> named integer(0)
#> 
#> [[6]]
#>    CjBwC    Oqqty    dxJ4c 
#>  6000006  9000006 12000006

Mais exécutez cette procédure sur l'ensemble de l prend pour toujours. J'ai essayé d'utiliser rrapply qui est un package rapide pour traiter des listes, et il faut "seulement" 110 secondes sur ma machine.

library(rrapply)
library(tictoc)

tic()
l_subsetted <- rrapply(object = l, f = randomly_subset_vec)
toc()
#> 110.23 sec elapsed

Je serai heureux avec l'un des suivants:

  1. Existe-t-il une alternative plus rapide à:
    rrapply(object = l, f = randomly_subset_vec)
    
  2. Ou plus généralement, existe-t-il un moyen plus rapide de commencer avec my_named_vec et arriver à l_subsetted?
7
Emman

Vous pouvez essayer le code ci-dessous

lapply(
  l,
  function(x) {
    head(sample(x), sample(length(x), 1))
  }
)
0
ThomasIsCoding