【问题标题】:mapply with multiple arguments where one argument is constant (data)具有多个参数的映射,其中一个参数是常量(数据)
【发布时间】:2019-10-19 23:37:37
【问题描述】:

我正在努力在我构造的函数上使用 mapply,因为我在更大的环境中编程,所以我需要一个或多个参数,例如,如果我编写一个参数之一是 data 的函数.

fun_test <- function(data,col,val1,val2){return(data[col][1,] * val1-val2)}

所以 datacol 例如可以是常数,但我想根据 val1 改变函数的输出>val2:

> mapply(FUN=fun_test,mtcars,"cyl",mtcars$cyl,mtcars$cyl*2)
Error in data[col][1, ] : incorrect number of dimensions

我正在尝试了解 mapply 的工作原理;我肯定不能通过 mtcars 和“cyl”作为向量,可以吗?

编辑:我有一个数据可能会发生变化的环境,例如有时我使用 mtcars,有时它是另一个数据集。所以我无法将数据硬编码到函数中

EDIT2: 1)我有一些数据集, 2) 我有不同的 Excel 文件读入 R, 3)我做了一个查找函数,从R中的这些Excel文件中提取信息, 4) 当我进入我创建的查找函数并提取信息时,对于一个或两个变量(来自数据集)。

因此,这些查找函数取决于数据(我需要查找的变量)和用于查找的 Excel 文件。

【问题讨论】:

  • @akrun:你确定这是重复的吗?我很难看到这对我有什么帮助。
  • Mapmapply 的包装我猜问题是其中一个参数是一个常数。所以你需要把它包装在一个列表中,这是欺骗链接中提供的解决方案。如果您不同意,我可以重新打开
  • @akrun:我明白了,也许我写“常数”时太模糊了。我的意思是参数不会改变,但常量参数本身不是常量,而是我的数据。
  • 我的意思是每个列表元素都重复数据或输入。这就是您使用mapply(FUN=fun_test, list(mtcars),"cyl",mtcars$cyl,mtcars$cyl*2) 回答的原因,其中数据包装在list
  • @akrun:感谢您的详细说明! Tbh,我不明白它们是相关的,我在提问之前阅读了那个答案,但如果你想关闭它,我理解

标签: r mapply


【解决方案1】:

mapply 是一个多维的lapply。这意味着它不是只迭代一个对象(即 data.frame 的列或向量的元素),而是同时迭代多个对象。唯一的条件是这些对象的长度必须相同,即 data.frame 的列和向量的长度。所以,你不能传递常量(除非你传递相同常量的向量来匹配长度,但你为什么要这样做)。

尝试一个简单的例子(对向量的相同索引求和):

mapply(sum, 1:10, 11:20)

因此,在您的情况下,只需将常量直接传递到函数中:

fun_test <- function(val1, val2){return(mtcars['cyl'] * val1 - val2)}

mapply(FUN=fun_test, mtcars$cyl, mtcars$cyl*2)

更新:

那么我认为你需要在你的函数中包含mapply。通过这种方式,您可以添加任何您喜欢的参数(常量和变量)。它看起来像这样:

myfunc <- function(data, col, val1, val2) {

  fun_test <- function(val1, val2) {
    data[col] * val1 - val2 
  }

  mapply(FUN=fun_test, val1, val2)

}

myfunc(mtcars, 'cyl', mtcars$cyl, mtcars$cyl*2)

【讨论】:

  • 对不起,也许我不够清楚,但我有一个数据可能会发生变化的环境,例如有时我使用 mtcars,有时它是另一个数据集。所以我无法将数据硬编码到函数中。
【解决方案2】:

如果您想将数据帧作为常量值传递,请将其作为列表传递,以便完全回收,否则它将在 mapply 中分别传递每一列

fun_test <- function(data,col,val1,val2){return(data[1, col] * val1-val2)}

mapply(FUN=fun_test, list(mtcars),"cyl",mtcars$cyl,mtcars$cyl*2)
#[1] 24 24 16 24 32 24 32 16 16 24 24 ......

所以输出中的第一个值24可以被复制出来

mtcars[1, "cyl"] * mtcars$cyl[1] - mtcars$cyl[1]*2
#[1] 24

我知道这是一个示例,实际实现有所不同,但您可以通过这样做直接获得相同的输出

mtcars[1, "cyl"] * mtcars$cyl - mtcars$cyl*2

要了解这两种调用之间的区别,我们可以调试函数,在函数中添加browser()

fun_test <- function(data,col,val1,val2){
   browser()
   return(data[1, col] * val1-val2)
}

现在,调用函数并检查函数中的参数

mapply(FUN=fun_test, mtcars,"cyl",mtcars$cyl,mtcars$cyl*2)
Browse[1]> data
# [1] 21.0 21.0 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 17.8 16.4 17.3 15.2 
#     10.4 10.4 14.7 32.4 30.4 33.9 21.5 15.5 15.2 13.3 19.2 27.3 26.0 30.4 
#     15.8 19.7 15.0 21.4

这是mtcars 中的第一列,即mpg(检查mtcars$mpg)。

它是一个数字向量,现在您尝试对 mpg 列进行子集化并从中索引 1,这会给您同样的错误

mtcars$mpg["cyl"][1, ]

mtcars$mpg["cyl"][1, ] 中的错误:维数不正确

现在在第二种情况下,当我们将数据帧作为列表传递时,请检查 data

 mapply(FUN=fun_test, list(mtcars),"cyl",mtcars$cyl,mtcars$cyl*2)

Browse[1]> data
#                     mpg cyl  disp  hp drat    wt  qsec vs am gear carb
#Mazda RX4           21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
#Mazda RX4 Wag       21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
#Datsun 710          22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
#Hornet 4 Drive      21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
#Hornet Sportabout   18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2
#Valiant             18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1
#....

这是完整的数据框,然后您可以从中提取子集

>data[1, "cyl"]
#[1] 6

PS - 我不知道为什么这样做的背景,我相信会有更好的方法来处理它。

【讨论】:

  • 您能否详细说明您所说的清单被完全回收的含义?至于上下文,正如我在我的 OP 中的编辑中提到的:1)我有一些数据集,2)我有不同的 Excel 文件,我读入 R,3)我创建了一个查找函数,从这些 Excel 中提取信息-在我进入创建的查找函数并提取信息时,R 中的文件,4) 用于一个或两个变量(来自数据集)。
  • @Erosennin 我已经添加了一些解释。
  • 我认为这应该添加到 R 文档中,因为 MoreArgs 参数的存在会造成混淆。
猜你喜欢
  • 1970-01-01
  • 2019-11-26
  • 2020-02-01
  • 2019-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-28
相关资源
最近更新 更多