【问题标题】:How do I apply a multi-parameter function in R?如何在 R 中应用多参数函数?
【发布时间】:2012-01-05 00:55:03
【问题描述】:

我有以下数据框和向量。

> y
  v1 v2 v3
1  1  6 43
2  4  7  5
3  0  2 32

> v
 [1] 1 2 3

我想将以下函数应用于该数据框中的每个 ROW,以便将 v 添加到 y 的每个 ROW

x <- function(vector1,vector2) {
    x <- vector1 + vector2
}

...为了得到这些结果:

  v1 v2 v3
1  2  8 46
2  5  9  8
3  1  4 35

mapply 将函数应用于COLUMNS

> z <- mapply(x, y, MoreArgs=list(vector2=v))
> z
     v1 v2 v3
[1,]  2  7 44
[2,]  6  9  7
[3,]  3  5 35

我尝试过转置数据框,以便将函数应用于行而不是列,但在转置后,mapply 给了我奇怪的结果:

> transposed <- t(y)
> transposed
   [,1] [,2] [,3]
v1    1    4    0
v2    6    7    2
v3   43    5   32

> z <- mapply(x, transposed, MoreArgs=list(vector2=v))
> z
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
[1,]    2    7   44    5    8    6    1    3   33
[2,]    3    8   45    6    9    7    2    4   34
[3,]    4    9   46    7   10    8    3    5   35

...帮助?

############################编辑################## #######

感谢所有答案!我正在学习大量以前从未见过的新 R 函数,这太棒了。

我想稍微澄清一下我之前的问题。我真正要问的是一个更普遍的问题 - 如何将多参数函数应用于 R 中的每一行(目前,我很想得出结论,我应该只使用一个循环,但我想弄清楚是否可行,仅供将来参考...)(我也故意避免展示我正在使用的代码,因为它有点乱)。

我尝试按照建议使用扫描功能,但出现以下错误:

testsweep <- function(vector, z, n) {
   testsweep <- z
}
> n <- names(Na_exp)
> n
[1] "NaCl.10000.2hr.AVG_Signal" "NaCl.10000.4hr.AVG_Signal"


> t <- head(Li_fcs,n=1)
> t
  LiCl.1000.1hr.FoldChange LiCl.2000.1hr.FoldChange LiCl.5000.1hr.FoldChange
[1,]              -0.05371838               -0.1010928              -0.01939986
     LiCl.10000.1hr.FoldChange LiCl.1000.2hr.FoldChange
[1,]                 0.1275617                -0.107154
    LiCl.2000.2hr.FoldChange LiCl.5000.2hr.FoldChange
[1,]              -0.06760782              -0.09770226
    LiCl.10000.2hr.FoldChange LiCl.1000.4hr.FoldChange
[1,]                -0.1124188              -0.06140386
    LiCl.2000.4hr.FoldChange LiCl.5000.4hr.FoldChange
[1,]              -0.04323497              -0.04275953
    LiCl.10000.4hr.FoldChange LiCl.1000.8hr.FoldChange
[1,]                0.03633496               0.01879461
    LiCl.2000.8hr.FoldChange LiCl.5000.8hr.FoldChange
[1,]                 0.257977              -0.06357423
    LiCl.10000.8hr.FoldChange
[1,]                0.07214176


> z <- colnames(Li_fcs)
> z
 [1] "LiCl.1000.1hr.FoldChange"  "LiCl.2000.1hr.FoldChange" 
 [3] "LiCl.5000.1hr.FoldChange"  "LiCl.10000.1hr.FoldChange"
 [5] "LiCl.1000.2hr.FoldChange"  "LiCl.2000.2hr.FoldChange" 
 [7] "LiCl.5000.2hr.FoldChange"  "LiCl.10000.2hr.FoldChange"
 [9] "LiCl.1000.4hr.FoldChange"  "LiCl.2000.4hr.FoldChange" 
[11] "LiCl.5000.4hr.FoldChange"  "LiCl.10000.4hr.FoldChange"
[13] "LiCl.1000.8hr.FoldChange"  "LiCl.2000.8hr.FoldChange" 
[15] "LiCl.5000.8hr.FoldChange"  "LiCl.10000.8hr.FoldChange"

但是当我尝试应用扫描时...

> test <- sweep(t, 2, z, n, FUN="testsweep")
Error in if (check.margin) { : argument is not interpretable as logical
In addition: Warning message:
In if (check.margin) { :
  the condition has length > 1 and only the first element will be used

当我从这个测试示例中删除 n 参数时,扫描工作正常。这向我表明,除非提供给扫描的所有参数与 t 向量的列数相同或长度为 1,否则无法使用扫描。如果我弄错了,请纠正我...

【问题讨论】:

    标签: r apply


    【解决方案1】:

    我肯定会从 plyr 包中查看 mdply。这正是您想要做的:

    mdply(data.frame(mean = 1:5, sd = 1:5), rnorm, n = 2)
    

    【讨论】:

      【解决方案2】:

      我认为您在这里不需要mapply。直接使用t(),也可以使用rep()进行回收匹配:

      > set.seed(1)
      > mat <- matrix(sample(1:100, 9, TRUE), ncol = 3)
      > vec <- 1:3
      > 
      > mat
           [,1] [,2] [,3]
      [1,]   27   91   95
      [2,]   38   21   67
      [3,]   58   90   63
      #Approach 1 using t() 
      > ans1 <- t(t(mat) + vec)
      #Approach 2 using rep()
      > ans2 <- mat + rep(vec, each = nrow(mat))
      #Are they the same?
      > identical(ans1, ans2)
      [1] TRUE
      #Hurray!
      > ans1
           [,1] [,2] [,3]
      [1,]   28   93   98
      [2,]   39   23   70
      [3,]   59   92   66
      

      【讨论】:

        【解决方案3】:

        您要求使用“+”函数在 y 行中“扫描”v:

         sweep(y, 1,  v, FUN="+")
          v1 v2 v3
        1  2  7 44
        2  6  9  7
        3  3  5 35
        

        【讨论】:

        • 我认为MARGIN 需要为2,因为您想将v 应用于y 的列。
        • 我认为sweep正是我想要的。这个问题实际上比仅仅添加向量更复杂——我只是用它作为一个例子,因为它是最简单的事情。我真正想要的是一种轻松快速地将多参数函数应用于每一行的方法——这似乎就是扫描所做的。所以谢谢你!
        • 不,再想一想,这并没有解决我的问题:sweep 似乎无法获取具有任意数量值的向量。
        • 抱歉 - 澄清一下,我有一个函数作为参数:vector1、vector2、vector3。 Vector1 和vector2 的长度相同。 vector3 具有任意长度。我想将此函数应用于矩阵的每一行。但是任意长度 vector3 的存在似乎导致我的代码失败。我收到此错误: if (check.margin) { 中的错误:参数不可解释为逻辑此外:警告消息:在 if (check.margin) { 中:条件的长度 > 1,并且只会使用第一个元素
        • 您的问题听起来更像是对代码中某个函数的错误使用,而不是由于向量长度不等。我们只能在这一点上猜测。
        【解决方案4】:

        如果您的实际问题真的没有比这更复杂,您可以利用 R 的回收规则。您需要先转置y,然后添加,然后转置结果,因为R矩阵存储在column-major order中。

        t(t(y)+v)
          v1 v2 v3
        1  2  8 46
        2  5  9  8
        3  1  4 35
        

        【讨论】:

          【解决方案5】:

          使用apply怎么样?

           t(apply(y, 1, function(x) x + v))
               [,1] [,2] [,3]
          [1,]    2    8   46
          [2,]    5    9    8
          [3,]    1    4   35
          

          我不知道为什么 apply 将行作为列返回,所以需要转置。

          【讨论】:

          • 我肯定会从 plyr 包中查看 mdply。这正是您所要求的。
          • 我肯定会从 plyr 包中查看 mdply。这正是您所要求的。
          猜你喜欢
          • 2013-07-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-10-13
          • 2021-01-06
          • 1970-01-01
          • 2014-01-14
          • 2014-12-14
          相关资源
          最近更新 更多