удаление элемента из всех встроенных списков в списке в R - PullRequest
1 голос
/ 19 мая 2019

У меня есть список (g) списков, как показано ниже. Чтобы удалить элемент k из одного из встроенных списков (например, 1-й список), я могу сделать: g[[1]]$k <- NULL.

Но когда я пытаюсь удалить элемент k из всех встроенных списков, мой код lapply не выполняется? Есть ли исправление Base R?

g <- list(b1 = list(data.frame(a = 1:3), k = 4:6), b2 = list(data.frame(a = 8:9), k = 7:9))

lapply(1:length(g), function(i) g[[i]]$k <- NULL) ## FAILS to delete `k` from all embedded lists

Ответы [ 4 ]

3 голосов
/ 19 мая 2019

R - это функциональный язык, и поэтому передаются копии аргументов, а не указатели на них.Функции не должны вносить изменения в «оригиналы» аргументов.Поэтому не следует полагать, что изменения значений, к которым осуществляется доступ внутри функции, будут «видны» вне среды этой функции , если только не будет присвоено исходное имя (или альтернативное имя, например, как здесь):

> g2 <- lapply(g, function(i){ i$k <- NULL; i})
> g2
$b1
$b1[[1]]
  a
1 1
2 2
3 3


$b2
$b2[[1]]
  a
1 8
2 9

Также обратите внимание: необходимость возврата измененного элемента после обнуления значения "k".Казалось бы, прямее передавать фактические элементы, а не использовать индекс.Из правил <- и <<- разрешено неявное исключение из правила «не изменять аргументы».

3 голосов
/ 19 мая 2019

Вы можете сделать

lapply(g, function(x) x[names(x) != "k"])
#$b1
#$b1[[1]]
#  a
#1 1
#2 2
#3 3


#$b2
#$b2[[1]]
#  a
#1 8
#2 9

Или альтернативно

lapply(g, function(x) { x[names(x) == "k"] <- NULL; x })
2 голосов
/ 19 мая 2019

Вот вариант с discard

library(purrr)
map(g, ~ discard(.x, names(.x) == "k"))
#$b1
#$b1[[1]]
#  a
#1 1
#2 2
#3 3


#$b2
#$b2[[1]]
#  a
#1 8
#2 9
1 голос
/ 19 мая 2019

Аналогично @ 42 -:

lapply(g, '[[<-', 'k', NULL)

# $b1
# $b1[[1]]
#   a
# 1 1
# 2 2
# 3 3

# $b2
# $b2[[1]]
#   a
# 1 8
# 2 9
...