我正在尝试编写一个函数,当我调用它时,它会向数据框添加一个新列,而不进行任何显式赋值。 即我只想用参数调用函数并修改数据框:
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)来解决这个问题,但是还有另一种方法吗?
这是我的参考函数,它应该在提供的开始日期和结束日期之间创建一个1s的列,名称为dummy_name。
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
。
答案 0 :(得分: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