R中的可变范围

时间:2014-06-23 12:51:18

标签: r function scope

我有一个名为factor_nonagg的data.frame,有50行和3列。我用参数因子写了一个函数category()。我正在对函数中的因素进行更改。当我将data.frame传递给此函数时,data.frame中没有进行任何更改。 有人可以帮助我对我的data.frame进行永久性更改吗?

n=50
category=function(factors){
for(i in 1:n){
if(factors[i,1]>=90) factors[i,1]<-2*.45
else if(factors[i,1]>=65) factors[i,1]<-1*.45
else factors[i,1]<-0

if(factors[i,2]>=.190) factors[i,2]<-2*.25
else if(factors[i,2]>=.140) factors[i,2]<-1*.25
else factors[i,2]<-0

if(factors[i,3]>=.03) factors[i,3]<-2*.30
else if(factors[i,3]>=.015) factors[i,3]<-1*.30
else factors[i,3]<-0
}}
category(factor_nonagg)

4 个答案:

答案 0 :(得分:1)

R不容易支持函数的传递引用类型行为。当您对函数中的参数值进行更改时,将创建该对象的副本,并且只有在函数调用时,更改才会持续。

通常,您的函数会返回更改后的值(return(factor)),并将新值分配给原始变量:

factor_nonagg <- category(factor_nonagg)

答案 1 :(得分:1)

循环遍历数据帧行将会非常缓慢。这是一种矢量化方法,在没有数据的情况下通常未经测试,但不会与dardisco提供的其他测试数据产生错误:

category=function(factors){
factors[[1]] <- 0.45*(0:2)[ findInterval(factors[[1]], c(-Inf, 65, 90, Inf) )]
factors[[2]] <- 0.25*(0:2)[ findInterval(factors[[2]], c(-Inf, 0.140, 0.190, Inf) )]
factors[[3]] <- 0.30*(0:2)[ findInterval(factors[[3]], c(-Inf, 0.015, 0.03, Inf) )]
   return(factors) }

当然,与所有函数式语言一样,除了赋值命令外,不会修改factor_agg:

category(factor_agg)                # no effect
factor_agg <- category(factor_agg)  # replacement occurs.

findInterval是一个非常有用的面向向量的函数,可用于返回分组值或使用,如本例所示,作为从一组字符或数值中选择的索引

答案 2 :(得分:0)

您需要在函数中设置一个输出对象,该对象返回您对df所做的更改。这可以通过添加

来实现
return(factors)

就在函数定义中的最后一个大括号之前。

答案 3 :(得分:0)

你可以像这样接近它:

set.seed(1)
df1 <- data.frame(
    f1 = sample(seq(150), size=50, replace=TRUE),
    f2 = sample(seq(250) / 1000, size=50, replace=TRUE),
    f3 = sample(seq(50) / 1000, size=50, replace=TRUE)
    )
### vals1 = values
### mult1 = multiplier
fun1 <- function(x, vals1, mult1){
    if (x >= max(vals1)) return(mult1*2)
    if (x >= min(vals1) & x < max(vals1)) return(mult1)
    return(0)
    }
within(df1,
       f1 <- sapply(f1, fun1, vals1=c(90, 65), mult1=0.45),
       f2 <- sapply(f2, fun1, vals1=c(0.19, 0.14), mult1=0.25),
       f3 <- sapply(f3, fun1, vals1=c(0.03, 0.15), mult1=0.3)
       )

这避免了for(虽然短循环不一定是坏事),节省打字并且如果你想改变值或乘数,它可以更容易推广。我在return中使用fun1,因为它有多个退出点。