在 r 中的嵌套数据帧列表上应用函数
Apply function over nested list of dataframes in r
抱歉,如果之前有人问过这个问题 - 我找到了一些与在嵌套列表上应用函数相关的答案,但还没有找到一个我可以应用于我的具体案例的答案。
我有一个包含两个数据帧列表的列表:
set.seed(1)
df1 <- data.frame(x = rnorm(10), y = rnorm(10))
df2 <- data.frame(x = rnorm(10), y = rnorm(10))
df3 <- data.frame(x = rnorm(10), y = rnorm(10))
df4 <- data.frame(x = rnorm(20), y = rnorm(20))
df5 <- data.frame(x = rnorm(20), y = rnorm(20))
df6 <- data.frame(x = rnorm(20), y = rnorm(20))
lista <- list(df1, df2, df3)
listb <- list(df4, df5, df6)
list <- list(lista, listb)
我想在两个数据帧列表上应用类似于以下函数的功能:
f <- function (constant1, constant2, dfa, dfb){
(constant1 * (sum(dfa$x) + sum(dfa$y))) + (constant2 * (sum(dfb$x) + sum(dfb$y)))
}
因此,对于上面定义的列表,该函数将在第一次迭代中使用 dfa = df1
和 dfb = df4
。对于第二次迭代,这些将变为 dfa = df2
和 dfb = df5
,依此类推。
两个常量都设置为1
,输出应该是一个包含三个项目的列表:
> output
[[1]]
[1] 8.242232
[[2]]
[1] -2.19834
[[3]]
[1] 4.330664
我猜我需要 mapply
来执行此操作,但不知道如何调用数据帧。
在许多其他尝试中,我尝试了以下(抛出错误 $ operator is invalid for atomic vectors
):
output <- mapply(function(a, b, c, d) f(constant1 = a, constant2 = b, dfa = c, dfb = d),
a = 1, b = 1, c = list[[1]][[1]], d = list[[2]][[1]])
您可以像这样使用 mapply
:
mapply(function(a, b) f(constant1 = 1, constant2 = 1, dfa = a, dfb = b),
list[[1]], list[[2]])
#[1] 8.242232 -2.198340 4.330664
或者更好:
mapply(f, list[[1]], list[[2]], MoreArgs = list(constant1 = 1, constant2 = 1))
一个tidyverse
解决方案
library(tidyverse)
foo <- function(x, constant1, constant2){
x %>%
bind_rows(.id = "gr") %>%
group_by(gr) %>%
summarise(res= sum(x,y)) %>%
mutate(gr1 = rep(1:(n()/2), n()/(n()/2))) %>%
group_by(gr1) %>%
summarise(res=sum(res[1]*constant1,res[2]*constant2)) %>%
pull(res)}
foo(list, constant1 = 1, constant2 = 1)
[1] 8.242232 -2.198340 4.330664
抱歉,如果之前有人问过这个问题 - 我找到了一些与在嵌套列表上应用函数相关的答案,但还没有找到一个我可以应用于我的具体案例的答案。
我有一个包含两个数据帧列表的列表:
set.seed(1)
df1 <- data.frame(x = rnorm(10), y = rnorm(10))
df2 <- data.frame(x = rnorm(10), y = rnorm(10))
df3 <- data.frame(x = rnorm(10), y = rnorm(10))
df4 <- data.frame(x = rnorm(20), y = rnorm(20))
df5 <- data.frame(x = rnorm(20), y = rnorm(20))
df6 <- data.frame(x = rnorm(20), y = rnorm(20))
lista <- list(df1, df2, df3)
listb <- list(df4, df5, df6)
list <- list(lista, listb)
我想在两个数据帧列表上应用类似于以下函数的功能:
f <- function (constant1, constant2, dfa, dfb){
(constant1 * (sum(dfa$x) + sum(dfa$y))) + (constant2 * (sum(dfb$x) + sum(dfb$y)))
}
因此,对于上面定义的列表,该函数将在第一次迭代中使用 dfa = df1
和 dfb = df4
。对于第二次迭代,这些将变为 dfa = df2
和 dfb = df5
,依此类推。
两个常量都设置为1
,输出应该是一个包含三个项目的列表:
> output
[[1]]
[1] 8.242232
[[2]]
[1] -2.19834
[[3]]
[1] 4.330664
我猜我需要 mapply
来执行此操作,但不知道如何调用数据帧。
在许多其他尝试中,我尝试了以下(抛出错误 $ operator is invalid for atomic vectors
):
output <- mapply(function(a, b, c, d) f(constant1 = a, constant2 = b, dfa = c, dfb = d),
a = 1, b = 1, c = list[[1]][[1]], d = list[[2]][[1]])
您可以像这样使用 mapply
:
mapply(function(a, b) f(constant1 = 1, constant2 = 1, dfa = a, dfb = b),
list[[1]], list[[2]])
#[1] 8.242232 -2.198340 4.330664
或者更好:
mapply(f, list[[1]], list[[2]], MoreArgs = list(constant1 = 1, constant2 = 1))
一个tidyverse
解决方案
library(tidyverse)
foo <- function(x, constant1, constant2){
x %>%
bind_rows(.id = "gr") %>%
group_by(gr) %>%
summarise(res= sum(x,y)) %>%
mutate(gr1 = rep(1:(n()/2), n()/(n()/2))) %>%
group_by(gr1) %>%
summarise(res=sum(res[1]*constant1,res[2]*constant2)) %>%
pull(res)}
foo(list, constant1 = 1, constant2 = 1)
[1] 8.242232 -2.198340 4.330664