2015-10-05 150 views
0

我正在尝试编写一个函数,当我调用它时,它将向数据框中添加一个新列,而不进行任何明确的赋值。 即我只是想调用带参数的功能,并把它修改数据帧:从R中的函数内修改全局数据

input_data: 
x y 
1 2 
2 6 


column_creator<-function(data,column_name,...){ 
data$column_name <- newdata ...} 

column_creator(input_data,new_col,...) 

x y new_col 
1 2 5 
2 6 9 

至于反对:

input_data$new_col <- column_creator(input_data,new_col,...) 

但是这样做在函数内部分配不修改全局变量。

我正在通过让函数返回一个赋值语句(下面的函数中的temp)来解决这个问题,但是有没有另外一种方法来做到这一点?

这里是我的函数供参考,它应该在名称为dummy_name的情况下在提供的开始日期和结束日期之间创建一个1的列。

dummy_creator<-function(data,date,dummy_name,start,end){ 

    temp<-paste(data,"['",dummy_name,"'] <- ifelse(",data,"['",date,"'] > as.Date (","'" , start,"'" , ", format= '%Y-%m-%d') & ",data,"['",date,"'] < as.Date(", "'", end,"'" ,",format='%Y-%m-%d') ,1,0)",sep="") 
    print(temp) 
    return() 
} 

感谢

我也试过:

dummy_creator<-function(data,date,dummy_name,start,end){ 

    data[dummy_name] <<- ifelse(data[,date] > as.Date (start, format= "%Y-%m-%d") & data[,date] < as.Date(end,format="%Y-%m-%d") ,1,0) 

    } 

但是,尝试给了我错误object of type closure is not subsettable

+4

你可以用超赋值运算符'<<尝试 - '。 – RHertel

+0

@RHertel没有没有工作,它给了我类型闭包的错误对象不是子集表单,当不存在东西时就会出现。 – user124123

回答

2

修改传递给函数的全局数据或数据通常是一个糟糕的主意:R对象是不可变的,在函数中使用技巧修改它们会打破用户的期望,并且使得更难推理程序的状态。

这是很好的形式返回,而不是修改的对象:

input_data = column_creator(input_data, new_col, …) 

这就是说,你有几种选择。一般来说,R有几个机制允许修改对象。我建议你看看这个R6 classes

您也可以使用non-standard evaluation来捕获传递的对象并在来电者的站点修改它。但是,这是不可取的。我在这里发布一个这样的例子,因为这个机制很有趣,值得了解,但我会重申,你不应该在这里使用它。

function (df, new_col, new_data) { 
    # Get the unevaluated expression representing the data frame 
    df_obj = substitute(df) 
    new_col = substitute(new_col) 
    # Ensure that the input is valid 
    stopifnot(is.name(df_obj)) 
    stopifnot(is.name(new_col)) 
    stopifnot(is.data.frame(df)) 

    # Add new column to data frame 
    df[[deparse(new_col)]] = new_data 
    # Assign back to object in caller scope 
    assign(deparse(df_obj), df, parent.frame()) 
    invisible(df) 
} 
test = data.frame(A = 1 : 5, B = 1 : 5) 
column_creator(test, C, 6 : 10) 
test 
# A B C 
# 1 1 1 6 
# 2 2 2 7 
# 3 3 3 8 
# 4 4 4 9 
# 5 5 5 10