Для этого необходимо использовать другой ввод в зависимости от того, какое значение оценивается - PullRequest
0 голосов
/ 06 января 2020

Скажем, у меня есть список c из трех фреймов данных:

> c
$first
           a          b
1          1          2
2          2          3
3          3          4

$second
           a          b
1          2          4
2          4          6
3          6          8

$third
           a          b
1          3          6
2          6          9
3          9         12

Я хочу запустить laply для c, который будет выполнять пользовательскую функцию для каждого фрейма данных. Пользовательская функция зависит от трех чисел, и я хочу, чтобы функция использовала другое число в зависимости от того, какой фрейм данных она оценивает.

Я думал об использовании имен «first», «second» и «third» , но я не уверен, как получить эти имена, когда они внутри функции lapply. Это выглядело бы примерно так:

lapply(c, function(list, num1 = 1, num2 = -1, num3 = 0) {num <- ifelse(names(list) == "first", num1, ifelse(names(list) == "second", num2, num3)); return(list*num)})

Таким образом, результат, который я бы хотел получить, был бы сначала умножен на 1, второй умножен на -1, а третий умножен на 0.

Функция names дает значения a и b (имена столбцов) вместо имени самого фрейма данных, так что это не работает. Есть ли функция, которая могла бы дать мне значения «first», «second» и «третьего», которые мне нужны?

Или, альтернативно, есть ли лучший способ сделать это в функции lapply?

Ответы [ 2 ]

1 голос
/ 06 января 2020

Может быть, было бы проще с Map. Мы передаем интересующее число в нужном нам порядке и делаем простое умножение

Map(`*`, lst1,  c(1, -1, 0))

Если числа названы

num1 <- setNames(c(1, -1, 0), c("first", "third", "second"))

, то сопоставим с names из list

Map(`*`, lst1,  num1[names(lst1)])
#$first
#  a b
#1 1 2
#2 2 3
#3 3 4

#$second
#  a b
#1 0 0
#2 0 0
#3 0 0

#$third
#   a   b
#1 -3  -6
#2 -6  -9
#3 -9 -12

Или, если мы решим go с lapply, l oop над names из list, извлечь элемент list на основе имя, а также соответствующий элемент vector (named vector)

lapply(names(lst1), function(nm) lst1[[nm]] * num1[nm])

Или с sapply

sapply(names(lst1), function(nm) lst1[[nm]] * num1[nm], simplify = FALSE)

Или другой параметр map2 от purrr

library(purrr)
map2(lst1, num1[names(lst1)], `*`)

Примечание: c - это имя функции, и не рекомендуется создавать имена объектов с именами функций

data

lst1 <- list(first = structure(list(a = 1:3, b = 2:4), class = "data.frame",
row.names = c("1", 
"2", "3")), second = structure(list(a = c(2L, 4L, 6L), b = c(4L, 
6L, 8L)), class = "data.frame", row.names = c("1", "2", "3")), 
    third = structure(list(a = c(3L, 6L, 9L), b = c(6L, 9L, 12L
    )), class = "data.frame", row.names = c("1", "2", "3")))
0 голосов
/ 06 января 2020

Помимо решений @ akrun , вы также можете попробовать следующий код

mapply(`*`, lst1,  c(1, -1, 0),SIMPLIFY = F)

или

lapply(seq_along(lst1), function(k) lst1[[k]]*c(1,-1,0)[k])
...