生成data.frames(特别是对于不可重现的SO问题)的一种非常罕见的情况是当一列依赖于另一列的(通常是随机的)值时。例如,如果想要一个data.frame来测试回归,那么有一些噪声线性依赖会很好:
n <- 100
x <- runif(n)
dat <- data.frame( x=x, y=x+runif(n) )
plot(y~x,data=dat)
但是,我想在一行中完成(上面将计为两行,第一行创建x,第二行使用data.frame赋值中的x),理想情况下不会在全局环境中存放任何内容。
答案 0 :(得分:5)
这是within
within(data.frame(x = runif(n)), y <- x + runif(n))
此命令不将y
分配给全局环境(或父框架)。
答案 1 :(得分:3)
这是一种不会破坏很多程序员喜欢的“按行分配”规则的方法:
within(data.frame(row.names = 1:n), {x = runif(n); y = x + runif(n)})
其中data.frame(row.names = 1:n)
用于创建具有正确行数的空data.frame,否则within
会抱怨。
答案 2 :(得分:3)
这是一个解决方案,既不会出现ID'd的两个缺点。
library(data.table)
n <- 100
dat <- data.table(x = runif(n))[, y := x + runif(n)]
它自身的缺点是:
data.frame(data.table(......))
如果你想要一个“普通的”data.frame
返回。答案 3 :(得分: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
答案 4 :(得分: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)
答案 5 :(得分:1)
这是我提出的最好的。它使用的东西是初学者R的常见错误,作为编写更紧凑代码的技巧。
dat <- data.frame( x<-runif(n), y=x+runif(n) )
这与@Tommy's tip on CodeGolf.SE的精神相似。
缺点是:
x
,可能会覆盖其他一些变量。修改强>
@ WojciechSobala在评论中的解决方案值得在此处突出显示。只需将上述表达式包装在local
:
dat <- local( data.frame( x<-runif(n), y=x+runif(n) ) )
由于local
的工作方式与evalq
类似(例如,它评估给定环境中的表达式),但默认情况下它通过new.env()
,x
在新环境中进行评估。在这个新环境中创建,而不是在全球环境中创建。