【问题标题】:loop/apply function to run two or more lists one by one循环/应用函数以一一运行两个或多个列表
【发布时间】:2015-11-03 23:11:50
【问题描述】:

假设我有一个用户定义的乐趣

fun <- function(i,j,k){}

我正在寻找一个函数(),

function(fun, c(x1, x2), c(y1,y2), c(z1,z2))

执行为

fun(x1,y1,z1)
fun(x1,y2,z1)
fun(x2,y1,z1)
fun(x2,y2,z1)    
fun(x1,y1,z2)
fun(x1,y2,z2)
fun(x2,y1,z2)
fun(x2,y2,z2)

我虽然申请家庭可以做这项工作。但是我没有找到合适的。

================================================ =======================

这是我正在研究的一个真实示例,但仍然无法解决。

data <- read.table(header = TRUE, stringsAsFactors = FALSE,
                   text = "ID x1 x2  y1  y2
                   1   a  T 100  2
                   2   b  T 210  4
                   3   b  F 112  5
                   4   a  F 121  1
                   5   b  F 412  1")

boxplot <- function(i,j){
  print(ggplot(data, 
               aes_string(x=colnames(data)[i], 
                   y=colnames(data)[j],
                   col=colnames(data)[i]))+
                 geom_boxplot())
}

那么您可以使用boxplot(2,4) 来绘制绘图,boxplot(3,4)、boxplot(2,5)、boxplot(3,5) 也是如此。

然后我从答案中尝试了 do.call 和 apply 方法。

do.call(boxplot, as.list(unname(expand.grid(c(2, 3), c(4,5)))))

或

apply(expand.grid(c(2,3), c(4,5)),1,boxplot)

但是它们没有按预期工作。 do.call 方法只返回一个图,应用一个返回 8 个图,但都以 y 轴为 ID。

================================================ =======

for 循环使它工作。有cmets吗?

for (i in 2:3) {
  for (j in 4:5) {
  boxplot(i,j)
  }
}

【问题讨论】:

    标签: r loops ggplot2


    【解决方案1】:

    试试这个:

    sum3 <- function(x, y, z) x+y+z  # test function
    mapply(sum3, 1:3, 11:13, 21:23)
    ## [1] 33 36 39
    

    这里sum3(1, 11, 21) 是 33,sum3(2, 12, 22) 是 36,sum3(3, 13, 23) 是 39。?mapply 帮助页面上有更多示例。

    这也有效并返回一个列表:

    Map(sum3, 1:3, 11:13, 21:23)
    

    【讨论】:

    • 实际上,mapply 正是所要求的。它传递不同的参数,而不是单个向量。 sum 函数可以接受任意数量的参数。
    • 您好,感谢您的回答。我的问题可能不清楚。我对您的示例的预期结果将是总共 9 个 sum3(),它会遍历三个组中三个数字的所有组合。
    • 嗨,我添加了一个示例。如果我的问题得到澄清,请告诉我。
    【解决方案2】:

    x如果您提供reproducible example 会很好,这样我们可以验证可能的解决方案,但我认为您可以通过exapand.grid 和do.call 获得您想要的。怎么样

    do.call(fun, as.list(unname(expand.grid(c(x1, x2), c(y1,y2), c(z1,z2)))))
    

    如果有的话就去做

    fun <- function(i,j,k){i+j+k}
    x1<-1; x2<-2;
    y1<-10; y2<-20;
    z1<-100; z2<-200;
    

    你会得到

    [1] 111 112 121 122 211 212 221 222
    # x1+y1+z1, x2+y1+z1, x1+y2+z1, x2+y3+z1, ...
    

    【讨论】:

    • 很高兴看到我的推理与经验丰富的堆栈溢出成员产生了某种共鸣:)
    • 谢谢弗里克先生。你有一个可重复的好例子,不是吗;)
    • 嗨,弗里克先生,我在问题中添加了一个示例,但您的方法不太奏效。可以再看一遍吗?
    • 在您的示例中,什么对应于x 和y 值的向量?我在那里没有看到两个来源。您想要的确切的函数调用系列是什么?另外,我假设你的函数会被正确地向量化,但你的例子不是。这可以通过Vectorize() 解决,但不清楚您想要的输出到底是什么。通常你一次只能打印一个图而不做额外的工作,
    • 我希望 x 成为 x1 和 x2 列,y 成为 y1 和 y2 列。我想通过指定 i 和 j 作为列号来调用它们。对于给定的数据,x1 和 x2 列将由 i = c(2,3) 引用,y1 和 y2 列将由 j=c(4,5) 引用。我希望这能澄清来源问题。我将研究函数向量化。但是,有没有办法一次生成多个图?谢谢!
    【解决方案3】:

    如果我理解正确的话,这应该很简单

    apply(expand.grid(c(x1, x2), c(y1,y2), c(z1,z2)),1,fun)
    

    编辑:添加示例

    x <-c(13,14)
    y <- c(21,22)
    z<- c(35,36)
    apply(expand.grid(x,y,z),1,mean)
    [1] 23.00000 23.33333 23.33333 23.66667 23.33333 23.66667 23.66667 24.00000
    

    【讨论】:

    • 很高兴它有帮助。
    • 嗨,BG,我在问题中添加了我的真实示例,但该方法不太奏效。可以再看一遍吗?
    • 我认为这与你的箱线图函数有关,你只能使用像“平均”这样的矢量化函数。
    猜你喜欢
    • 2020-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-14
    • 1970-01-01
    • 2022-01-06
    相关资源
    最近更新 更多