在函数调用中提供变量名,并在R中对现有数据帧进行cbinding

时间:2014-04-15 06:05:56

标签: r function arguments naming-conventions

目标是让函数调用的最后一个参数为要绑定到原始数​​据框的新列提供名称。

参考thisthis之前的问题,并以第一个问题的最小工作示例为基础。

GroupId <-          c(1,1,1,1,2,2,2,3,3)
IndId <-            c(1,1,2,2,3,4,4,5,5)
IndGroupProperty <- c(1,2,1,2,3,3,4,5,6)
PropertyType <-     c(1,2,1,2,2,2,1,2,2)

df <- data.frame(GroupId, IndId, IndGroupProperty, PropertyType)
df

ValidGroupC <-       c(1,1,1,1,0,0,0,0,0)
df <- data.frame(df, ValidGroupC)
df

library(dplyr)
grouptest <- function(object, group, ind, type, new){
groupvar <- deparse(substitute(group)) 
indvar <- deparse(substitute(ind)) 
typevar <- deparse(substitute(type)) 
eval(substitute(
tmp <- object[, c(groupvar, indvar, typevar)] %.%
  group_by(group, ind) %.%
  mutate(type1 = any(type == 1))  %.%
  group_by(group, add = FALSE) %.%
  mutate(tmp2 = all(type1) * 1) %.%
  select(-type1)
  ))
new <- tmp[, 4]                    # this is the relevant part
tmp <- cbind(object, new)          # this is the relevant part
}

df <- grouptest(df, GroupId, IndId, PropertyType, ValidGroup)
df

因此,大多数代码已经是引用问题的产物。这个问题的相关部分最后是我对tmp进行计算的第4列,并将其放在一个新对象中,其名称应取自new参数在函数调用中,然后我将其绑定到原始数​​据框。

我的问题:为什么最终df的最后一列未命名为ValidGroup? 我没有弄错 - new应该被ValidGroup取代,但事实并非如此?

我已尝试将这两行放在eval()内,结果为Error in cbind(df, ValidGroup) : object 'ValidGroup' not found

我尝试在两行周围放置另一个eval(substitute()),相同的错误。

我尝试了许多其他的线条放置方式,使用去除newvar,命名tmpnew ,. 。

3 个答案:

答案 0 :(得分:1)

您希望将函数中突出显示的最后两行更改为:

object[, new] <- tmp[, 4]
object

然后,当您调用该函数时,将new参数指定为字符串:

> df <- grouptest(df, GroupId, IndId, PropertyType, "ValidGroup")   
> df
  GroupId IndId IndGroupProperty PropertyType ValidGroupC ValidGroup
1       1     1                1            1           1          1
2       1     1                2            2           1          1
3       1     2                1            1           1          1
4       1     2                2            2           1          1
5       2     3                3            2           0          0
6       2     4                3            2           0          0
7       2     4                4            1           0          0
8       3     5                5            2           0          0
9       3     5                6            2           0          0

答案 1 :(得分:0)

如果对象始终是data.frame,为什么不做一个新对象?

tmp <- data.frame(object, new=tmp[,4])
names(tmp)[4] <- as.character(match.call()$new)
return(tmp)

修改:更改了代码以接受name而非character参数new。不过,我仍然认为这不是一个好主意。你应该至少有一个可选的参数来根据this线程中@hadley的推理将第二行切换到names(tmp)[4] <- new

答案 2 :(得分:0)

我怀疑您正在寻找assign功能:

assign(deparse(substitute(new)), tmp[,4])

显然我很想念这个问题。这是另一种方法。您可以只在现有对象中添加新列,而不是使用cbind

object[, deparse(substitute(new))] <- tmp[,4]
object