Применить функцию к столбцам в списке фреймов данных и добавить результаты
Я хочу применить функцию к списку фреймов данных. функция берет элементы из двух столбцов в каждом фрейме данных, добавляет их, а затем добавляет выходные данные в каждый фрейм данных в новом столбце.
Создать фиктивные данные:
df.1 <- data.frame(data=cbind(rnorm(5, 0), rnorm(5, 2), rnorm(5, 5)))
df.2 <- data.frame(data=cbind(rnorm(5, 0), rnorm(5, 2), rnorm(5, 5)))
names(df.1) <- c("a", "b", "c")
names(df.2) <- c("a", "b", "c")
ls.1<- list(df.1,df.2)
names(ls.1) <- c("cat", "dog")
ls.1
посмотрите на данные:
> ls.1
$cat
a b c
1 0.7031868 1.730499 4.286386
2 0.1527551 2.794084 4.348707
3 1.1151157 0.154562 4.647605
4 0.5786497 1.407386 4.118078
5 0.9223104 2.995469 5.065981
$dog
a b c
1 0.04024872 1.6760609 5.013490
2 0.18095899 2.1015250 3.452313
3 -0.86588484 2.1371948 6.389203
4 -0.39499567 0.5996709 5.399724
5 -1.31850123 3.0058084 5.530989
Псевдокод того, что я хочу сделать:
my.fun <- function(b, c) {
out.put <- b + c
ls.1[i]$d <- out.put
}
Как я хочу, чтобы выходные данные выглядели так:
> ls.1
$cat
a b c d
1 0.7031868 1.730499 4.286386 6.689551
2 0.1527551 2.794084 4.348707 5.553838
3 1.1151157 0.154562 4.647605 8.526398
4 0.5786497 1.407386 4.118078 5.999395
5 0.9223104 2.995469 5.065981 8.536797
$dog
a b c d
1 0.04024872 1.6760609 5.013490 6.689551
2 0.18095899 2.1015250 3.452313 5.553838
3 -0.86588484 2.1371948 6.389203 8.526398
4 -0.39499567 0.5996709 5.399724 5.999395
5 -1.31850123 3.0058084 5.530989 8.536797
Я думаю, что это должно быть легко достижимо с mapply или чем-то подобным, но я не могу понять это....
3 ответа
Решение
lapply
отлично работает здесь. Обратите внимание, что return(x)
здесь необходимо, иначе мы просто вернем новый вектор.
res <- lapply(ls.1, function(x){
x$d <- x$b + x$c
return(x)
})
lapply
Ваша функция над каждым элементом списка. Функция должна добавить два столбца и затем вернуть измененный объект:
my.fun <- function(data,x,y,out) {data[out] <- data[[x]] + data[[y]]; data}
lapply(ls.1, my.fun, x="b", y="c", out="d")
#$cat
# a b c d
#1 -0.3762835 0.8775672 3.599283 4.476851
#2 1.4728001 2.2384841 3.093956 5.332440
#...
#
#$dog
# a b c d
#1 -0.7669203 2.8219880 4.284088 7.106076
#2 0.4413280 1.1619882 4.440192 5.602180
#...
Вот альтернативное решение с использованием цикла for
for (e in names(ls.1)) {
ls.1[[e]]$d <- ls.1[[e]]$b + ls.1[[e]]$c
}
$cat
a b c d
1 1.2720987 2.03251108 4.395936 6.428447
2 0.1048982 1.47652374 3.556955 5.033479
3 0.1332581 2.97334172 5.262912 8.236254
4 0.8064055 2.44649336 6.605434 9.051927
5 -1.5200194 -0.08463335 4.279925 4.195292
$dog
a b c d
1 0.73350259 1.133349 5.223977 6.357326
2 0.40957903 1.431519 5.332924 6.764442
3 -0.92179742 3.778318 6.924693 10.703011
4 1.92143657 1.055262 4.318544 5.373806
5 -0.07847994 2.045227 6.311894 8.357121