仅在缺少函数参数时才创建变量

时间:2016-07-14 11:03:41

标签: r

我需要编写一个将dataframe列作为参数的函数,并且如果缺少任何这些,将向数据框添加新变量,例如从

开始
    foo bar
1    1   1
2    2   2
3    3   3
4    4   4
5    5   5
6    6   6
7    7   7
8    8   8
9    9   9
10  10  10

为:

   foo bar  arg3
1    1   1 NA
2    2   2 NA
3    3   3 NA
4    4   4 NA
5    5   5 NA
6    6   6 NA
7    7   7 NA
8    8   8 NA
9    9   9 NA
10  10  10 NA

。到目前为止,我有这个例子:

df <- data.frame(foo = 1:10, bar = 1:10)

CheckData <- function(data, arg1 = NULL, arg2 = NULL, arg3 = NULL) {

  list_args <- list(arg1, arg2, arg3)

  # lapply(list_args, function(x) if(is.null(x)) data[[x]] <<- NA)
  # lapply(list_args, function(x) if(is.null(x)) data$x <<- NA)

  return(data)

}

CheckData(df, arg1 = 'foo', arg2 = 'bar')

所以,我传递了一个带有2列数据帧的函数,foo&amp; bar,允许arg3为NULL,默认值。在注释掉的2行中,我们有2个选项 -

  1. 第一个理想情况下会看到,arg3中的list_argsNULL,应创建一个新变量data[[arg3]]&amp;填充NA s。但是,这不起作用,我想知道是否有一些非标准的评估可能会对此有所帮助,因此它不会将其视为NULL对象而是名称/字符串。
  2. 第二个以这种方式工作,但创建了一个名为df$x的变量,而不是df$arg3
  3. 我可以逐个明确地这样做,例如

    CheckData <- function(data, arg1 = NULL, arg2 = NULL, arg3 = NULL) {
    
      if(is.null(arg1)) data$arg1 <- NA
      if(is.null(arg2)) data$arg2 <- NA
      if(is.null(arg3)) data$arg3 <- NA      
    
      return(data)
    
    }
    
    CheckData(df, arg1 = 'foo', arg2 = 'bar')
    

    但这样做不够优雅,需要事先了解所有可能的变量,这对我的需求来说是不现实的。

    对于高级R程序员来说,这似乎应该是一个相当直接的问题,但是我被阻止了,尽管经过了几个小时的搜索和反复试验,却无法找到解决方案。非常感谢您的帮助

2 个答案:

答案 0 :(得分:1)

以下是您想要的:

CheckArgs = function (df, ...) {
    args = list(...)
    for (arg in names(args)) {
        if (! arg %in% names(df))
            df[[arg]] = args[[arg]]
    }

    df
}

或者,以下内容相同,但没有循环:

CheckArgs = function (df, ...) {
    args = list(...)
    missing = ! names(args) %in% names(df)
    df[names(args)[missing]] = args[missing]
    df
}

用法:

df = CheckArgs(df, a = NA, b = NA, c = NA)

如果您只想用NA s填充向量,那么更好的解决方案是使用一个允许您只指定所需名称的函数:

df = CheckArgs(df, c('a', 'b', 'c'))

...或者沿着这些方向的东西。这当然可以很容易地以同样的方式完成:

CheckArgs = function (df, required_names) {
    missing = ! required_names %in% names(df)
    df[required_names[missing]] = NA
    df
}

答案 1 :(得分:0)

我设法找到了一个解决方案,使用plyr包中的一些固有功能,并使用assign代替赋值运算符(<-),这使我可以拥有映射到变量的参数,如下所示:

library(magrittr)
dat <- data.frame(foo = 1:10, bar = letters[1:10])

CheckData <- function(data, arg1 = NULL, arg2 = NULL, arg3 = NULL, arg4 = NULL) {

  # create dataframe of missing/unmatched arguments
  list_args <- 
    list(arg1, arg2, arg3, arg4) %>% 
    setNames(c('arg1', 'arg2', 'arg3', 'arg4')) %>% 
    plyr::ldply(function(x) if(is.null(x)) NA)

  # create new variables based on these missing arguments; map the arguments to these variables
  for(i in list_args[[1]]) {data[[i]] <- NA; assign(i, i)}

  return(data)

}

tmp <- CheckData(dat, arg1 = 'foo', arg2 = 'bar')

给出了以下数据帧,这正是我想要的:

   foo bar arg3 arg4
1    1   a   NA   NA
2    2   b   NA   NA
3    3   c   NA   NA
4    4   d   NA   NA
5    5   e   NA   NA
6    6   f   NA   NA
7    7   g   NA   NA
8    8   h   NA   NA
9    9   i   NA   NA
10  10   j   NA   NA