假设我想创建一个带有数字列和字符列的数据框:
df<-data.frame()
for(i in 1:26) {
df<-rbind(df, cbind(x=i, y=toString(i)))
}
str(df)
'data.frame': 26 obs. of 2 variables:
$ x: Factor w/ 26 levels "1","2","3","4",..: 1 2 3 4 5 6 7 8 9 10 ...
..- attr(*, "names")= chr "x" "x" "x" "x" ...
$ y: Factor w/ 26 levels "1","2","3","4",..: 1 2 3 4 5 6 7 8 9 10 ...
..- attr(*, "names")= chr "y" "y" "y" "y" ...
哎呀,我不想要因素。
df2<-data.frame()
for(i in 1:26) {
df2<-rbind(df2, cbind(x=i, y=toString(i)), stringsAsFactors=FALSE)
}
str(df2)
'data.frame': 26 obs. of 2 variables:
$ x: chr "1" "2" "3" "4" ...
$ y: chr "1" "2" "3" "4" ...
现在一切都是一个角色。我可以想出避免这种情况的唯一方法是构造单独的向量,然后在最后形成数据帧:
x<-NULL
y<-NULL
for(i in 1:26) {
x<-c(x, i)
y<-c(y, toString(i))
}
df3<-data.frame(x, y, stringsAsFactors=FALSE)
str(df3)
'data.frame': 26 obs. of 2 variables:
$ x: int 1 2 3 4 5 6 7 8 9 10 ...
$ y: chr "1" "2" "3" "4" ...
但正如您所看到的,这需要额外的代码。如果你有一个包含20列的数据框,你需要在循环之前有20个初始化语句,在循环中需要20个语句来添加到向量。
有没有更简洁的方法来实现这个目标?
答案 0 :(得分:3)
不要这样做。由于内存管理,在循环中增长对象的速度非常慢。正如评论告诉你的那样,你根本不需要循环遍历行。但是,如果需要执行此操作,则应预先分配向量,将其分配到它们中并在循环之后将它们组合到data.frame中。在循环中使用单独的向量(或者你可以使用向量列表)的原因是data.frame子集分配也很慢。
x <- integer(26)
y <- character(26)
for(i in 1:26) {
x[i] <- i
y[i] <- toString(i)
}
df <- data.frame(x, y, stringsAsFactors = FALSE)
str(df)
#'data.frame': 26 obs. of 2 variables:
# $ x: int 1 2 3 4 5 6 7 8 9 10 ...
# $ y: chr "1" "2" "3" "4" ...
如果你有很多专栏,你至少应该知道他们的课程。然后你可以这样做:
colclasses <- c("integer", "character")
l <- lapply(colclasses, vector, length = 26)
for(i in 1:26) {
l[[1]][i] <- i
l[[2]][i] <- toString(i)
}
names(l) <- c("x", "y")
df <- as.data.frame(l, stringsAsFactors = FALSE)
修改强>
由于您需要简明扼要的内容,请考虑使用lapply
。
l <- lapply(1:26, function(i) list(x = i, y = toString(i)))
df <- do.call(rbind.data.frame, l)
答案 1 :(得分:-5)
我知道这将被遗忘,但这是我的同事提出的解决方案:
df<-data.frame()
for(i in 1:26) {
df<-rbind(df, data.frame(x=i, y=toString(i), stringsAsFactors=FALSE))
}
str(df)
'data.frame': 26 obs. of 2 variables:
$ x: int 1 2 3 4 5 6 7 8 9 10 ...
$ y: chr "1" "2" "3" "4" ...
性能可能很差,但这是我正在寻找的那种简洁的解决方案。