2

生成 data.frames(特别是对于不可重现的 SO 问题)的一种不常见的情况是,当一列依赖于另一列的(通常是随机的)值时。例如,如果想要一个 data.frame 来测试回归,最好有一些嘈杂的线性依赖:

n <- 100
x <- runif(n)
dat <- data.frame( x=x, y=x+runif(n) )
plot(y~x,data=dat)

y 与 x

但是,我想在一行中完成(上面将算作两行,第一行创建 x,第二行在 data.frame 分配中使用 x),理想情况下不在全局环境中存放任何东西。

4

6 回答 6

5

这是一个简单的解决方案within

within(data.frame(x = runif(n)), y <- x + runif(n))

此命令不分配y全局环境(或父框架)。

于 2012-12-02T13:15:17.583 回答
3

这是一种不违反许多程序员喜欢坚持的“每行一个分配”规则的方法:

within(data.frame(row.names = 1:n), {x = runif(n); y = x + runif(n)})

wheredata.frame(row.names = 1:n)用于创建具有正确行数的空 data.frame,否则within会抱怨。

于 2012-12-02T13:00:16.607 回答
3

这是一个解决方案,它没有您识别出的两个缺点。

library(data.table)
n <- 100

dat <- data.table(x = runif(n))[, y := x + runif(n)]

它本身的缺点是:

  1. 需要加载整个包。
  2. 变得有点丑陋(即data.frame(data.table(......)),如果你想要一个“普通的”data.frame返回。
于 2012-12-02T13:04:18.260 回答
3

set.seed将需要使随机数在任何情况下都可重现,但尝试此模数:

set.seed(123)
dat <- transform(data.frame(x = runif(10)), y = x + runif(10))

这给出了:

> dat
           x         y
1  0.2875775 1.2444109
2  0.7883051 1.2416393
3  0.4089769 1.0865476
4  0.8830174 1.4556508
5  0.9404673 1.0433920
6  0.0455565 0.9453815
7  0.5281055 0.7741932
8  0.8924190 0.9344786
9  0.5514350 0.8793557
10 0.4566147 1.4111184
于 2012-12-02T15:59:03.523 回答
2

这是一个自定义函数,其工作方式类似于transform(或plyr::mutate),但不需要初始数据框。(显然这对 OP 的问题并没有真正的帮助,因为没有人会拥有这个功能,但我认为其他人可能会感兴趣)

create <- function(...) {
  .data <- list()

  cols <- as.list(substitute(list(...))[-1])
  cols <- cols[names(cols) != ""] # Silently drop unnamed columns

  for(col in names(cols)) {
    .data[[col]] <- eval(cols[[col]], .data, parent.frame())
  }
  as.data.frame(.data)
}
create(x = runif(1:10), y = x + 1)
于 2012-12-02T15:07:58.020 回答
1

这是我想出的最好的。它使用 R 初学者的常见错误作为编写更紧凑代码的技巧。

dat <- data.frame( x<-runif(n), y=x+runif(n) )

这与@Tommy 在 CodeGolf.SE 上的提示在精神上相似

缺点是:

  1. 潜在的混乱。尤其是因为这是一个常见的错误,在这种情况下,专家代码审查员可能会将其与错误混淆。
  2. 存放x在父(全局,在大多数用例中)环境中,它可能会覆盖其他一些变量。

编辑

@WojciechSobala 在评论中的解决方案值得在这里强调。只需将上面的表达式包装在local

dat <- local( data.frame( x<-runif(n), y=x+runif(n) ) )

由于它的local工作原理与evalq(例如,它在给定环境中评估表达式)一样,除了它默认在新环境中通过 评估,因此new.env()x这个新环境中而不是在全局环境中创建。

于 2012-12-02T12:40:34.263 回答