【发布时间】:2021-04-09 15:51:55
【问题描述】:
我想将ggplot2 可视化编码为函数,然后在数据帧的每一行上使用apply 函数(我想使用apply 来避免for 循环,建议here .)
数据:
library(ggplot2)
point1 <- c(1,2)
point2 <- c(2,2)
points <-as.data.frame(rbind(point1,point2))
我将points 保存为数据框,它在ggplot2 中运行良好:
ggplot(data = points) +
geom_point(aes(x = points[, 1], y = points[, 2])) +
xlim(-3, 3) +
ylim(-3, 3) +
theme_bw()
但这并不是我真正想要的情节:我想要两个情节,每个情节都有一个点。
现在我构建了一个循环遍历数据框行的函数:
plot_data <- function(data) {
ggplot(data) +
geom_point(aes(x = data[, 1], y = data[, 2])) +
xlim(-3, 3) +
ylim(-3, 3) +
theme_bw()
}
我创建了一个列表来存储图:
myplots <- list()
这是对apply 的调用,在this suggestion 之后:
myplots <- apply(points, 1, plot_data)
但我收到以下错误:
#> Error: `data` must be a data frame, or other object coercible by `fortify()`,
not a numeric vector
但我的数据是一个数据框。
这是因为:“apply() 将尝试将 data.frame 转换为矩阵(请参阅帮助文档)。如果由于混合数据类型而无法正常转换,我不太确定会产生什么结果" 正如我提到的对the answer 的评论中所指出的那样?
不过,如果我在调用 apply 后检查数据类,数据仍然是一个数据框:
class(points)
#> [1] "data.frame"
由reprex package (v0.3.0) 于 2021-04-09 创建
【问题讨论】:
-
apply在这里是一个糟糕的选择。apply是为处理矩阵而构建的,当你给apply一个数据框时,它所做的第一件事就是将它转换为矩阵——正如你所说的。此转换在apply函数内。你的原始数据仍然是一个数据框并且仍然没有改变(除非你给它分配了一些东西,points <- apply(...)。所以,如果你真的想使用apply,你可以转换apply使用的矩阵返回到数据帧,但这非常低效。 -
感谢您的解释。您会推荐什么来替代
apply? -
如果您对 for 循环过敏并且对其他
*apply系列函数持开放态度,则可以在行索引中使用lapply,例如myplots <- lapply(1:nrow(points), function(i) plot_data(points[i, ]))。或者一个 for 循环,for(i in 1:nrow(points)) {myplots[[i]] <- plot_data(points[i, ])}。 -
我真的不知道有关该构造的信息的良好来源...更多的是熟悉
*apply系列函数和R 数据结构。我真的很喜欢 this FAQ 来理解 *apply 系列功能。当然,R for Data Science chapter on iteration 也不错,其中包括对purrr的这些函数变体的介绍。 -
无论
X是什么lapply都会迭代,因为数据框是作为列列表构建的,如果你lapply(some_data_frame, foo)迭代将在列之上。例如,lapply(mtcars,mean)、lapply(iris, class)。