附加到函数中的数据框 - 是真的需要globalenv

时间:2018-06-16 14:23:57

标签: r

我使用以下代码,工作正常(非常欢迎改进建议):

WeeklySlopes <- function(Year, Week){

  DynamicQuery <- paste('select DayOfYear, Week, Year, Close from SourceData where year =', Year, 'and week =', Week, 'order by DayOfYear')
  SubData = sqldf(DynamicQuery)
  SubData$X <- as.numeric(rownames(SubData))
  lmfit <- lm(Close ~ X, data = SubData)
  lmfit <- tidy(lmfit)
  Slope <- as.numeric(sqldf("select estimate from lmfit where term = 'X'"))
  e <- globalenv()
  e$WeeklySlopesDf[nrow(e$WeeklySlopesDf) + 1,] = c(Year,Week, Slope)
}

WeeklySlopesDf <- data.frame(Year = integer(), Week = integer(), Slope = double())
WeeklySlopes(2017, 15)
WeeklySlopes(2017, 14)
head(WeeklySlopesDf)

是否真的没有其他方法可以向现有数据框添加行。我似乎需要访问globalenv。另一方面,为什么sqldf可以“看到”'全局'数据帧SourceData?

1 个答案:

答案 0 :(得分:1)

dfrm <- data.frame(a=1:10, b=letters[1:10])  # reproducible example

myfunc <- function(new_a=20){ g <- globalenv(); g$dfrm[3,1] <- new_a; cat(dfrm[3,1])}
myfunc()
20
dfrm
    a b
1   1 a
2   2 b
3  20 c  # so your strategy might work, although it's unconventional.

现在尝试在函数外部扩展数据框:

dfrm[11, ] <- c(a=20,b="c")

隐匿灾难(将数字列转换为字符):

str(dfrm)
'data.frame':   11 obs. of  2 variables:
 $ a: chr  "1" "2" "20" "4" ...
 $ b: Factor w/ 10 levels "a","b","c","d",..: 1 2 3 4 5 6 7 8 9 10 ...

所以使用列表来避免隐藏强制:

dfrm <- data.frame(a=1:10, b=letters[1:10]) # start over
dfrm[11, ] <- list(a=20,b="c")
str(dfrm)
'data.frame':   11 obs. of  2 variables:
 $ a: num  1 2 3 4 5 6 7 8 9 10 ...
 $ b: Factor w/ 10 levels "a","b","c","d",..: 1 2 3 4 5 6 7 8 9 10 ...

现在在一个函数中尝试:

myfunc <- function(new_a=20, new_b="ZZ"){ g <- globalenv(); g$dfrm[nrow(dfrm)+1, ] <- list(a=new_a,b=new_b)}
myfunc()
Warning message:
In `[<-.factor`(`*tmp*`, iseq, value = "ZZ") :
  invalid factor level, NA generated

str(dfrm)
'data.frame':   12 obs. of  2 variables:
 $ a: num  1 2 3 4 5 6 7 8 9 10 ...
 $ b: Factor w/ 10 levels "a","b","c","d",..: 1 2 3 4 5 6 7 8 9 10 ...

所以它成功了,但是如果有任何因子列,则不存在的级别将变为NA值(带有警告)。您在全局环境中使用对对象的命名访问的方法是非常规的,但是您可能需要检查一组经过测试的方法。看?R6。其他选项包括<<-assign,它们允许指定要进行分配的环境。