R: преобразовать вложенный в l oop, чтобы применить функцию - PullRequest
3 голосов
/ 30 марта 2020

вот мой минимальный пример:

calA_fun <- function(list_A){
for (k in 1:length(list_A)){
  out_level = list()
  out_level[[k]] <- unlist( lapply(list_A[[k]], sqrt) )
  for (j in 1:length(list_A[[k]]) ){
      out_level_level = list()
      out_level_level[[j]] <- lapply(list_A[[k]][[j]], function(x) x+ out_level[[k]] ) 
      print(out_level_level[[j]])
  }
}
}
list_A <- list(aa = c(1, 2, 4), bb = c(6,2))
calA_fun(list_A)

Я переписываю эту функцию, используя apply () family или map () вместо l oop, но я не знаю, возможно ли это с j вложено в k, так что это иерархическая структура.

Спасибо!

Ответы [ 3 ]

3 голосов
/ 30 марта 2020

Мы можем использовать rapply (рекурсивное применение), которое точно создано для этой задачи.

Использование данных @Marcelo Fernando Befumo

rapply(xx, sum)
#   aa    bb cc.a2 cc.b2 cc.a3 cc.b3 
#   45   145   110     0   275    54 

Или, если вы хотите вывести в виде списка

rapply(xx, sum, how = "list")

#$aa
#[1] 45

#$bb
#[1] 145

#$cc
#$cc$a2
#[1] 110

#$cc$b2
#[1] 0

#$cc[[3]]
#$cc[[3]]$a3
#[1] 275

#$cc[[3]]$b3
#[1] 54
1 голос
/ 30 марта 2020

Рекурсивные функции могут работать с произвольным вложением

recursiveListSum <- function(x) {
  if (is.list(x)) {
    lapply(x, recursiveListSum)  
  } else {
    sum(x)
  }
}

xx <- list(
  "aa" = 1:9,
  "bb" = 10:19,
  "cc" = list(
    "a2" = 5:15,
    "b2" = -2:2,
    list(
      "a3" = 20:30,
      "b3" = -1:10
    )
  )
) 
# results
> recursiveListSum(xx)
$aa
[1] 45

$bb
[1] 145

$cc
$cc$a2
[1] 110

$cc$b2
[1] 0

$cc[[3]]
$cc[[3]]$a3
[1] 275

$cc[[3]]$b3
[1] 54
1 голос
/ 30 марта 2020

ОБНОВЛЕНИЕ: разделенное и более удобочитаемое решение:

calA_fun <- function (list_A) {
  Reduce(c, list_to_sums(list_A))
}

list_to_sums <- function (list_A) {
  lapply(val_and_sqrt(list_A), get_sums)
}

val_and_sqrt <- function (list_A) {
  lapply(list_A, function (x) {
    list(val = x, sqrt = sqrt(x))
  })
}

get_sums <- function(l) {
  lapply(l$val, function(x) { x + l$sqrt })
}

(оригинальное решение)

calA_fun <- function(list_A) {
  Reduce(
    c,    # make flat list
    lapply(
      lapply(list_A, function (x) { list(x, sqrt(x)) }),  # calculate sqrt
      function(x) {       # process every outer-level list item
        lapply(x[[1]], function (y) { y + x[[2]] })  # replace with vector of each square root + raw value y
      }
    )
  )
}
...