【问题标题】:How to apply ggplot2 to each row in a data frame如何将ggplot2应用于数据框中的每一行
【发布时间】: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 &lt;- apply(...)。所以,如果你真的想使用apply,你可以转换apply 使用的矩阵返回到数据帧,但这非常低效。
  • 感谢您的解释。您会推荐什么来替代apply?
  • 如果您对 for 循环过敏并且对其他 *apply 系列函数持开放态度,则可以在行索引中使用 lapply,例如 myplots &lt;- lapply(1:nrow(points), function(i) plot_data(points[i, ]))。或者一个 for 循环,for(i in 1:nrow(points)) {myplots[[i]] &lt;- 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)。

标签: r ggplot2 apply


【解决方案1】:

正如评论中Gregor Thomas 所建议的那样:

library(ggplot2)
point1 <- c(1, 2)
point2 <- c(2, 2)

points <- as.data.frame(rbind(point1, point2))

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()
myplots <- lapply(1:nrow(points), function(i) plot_data(points[i, ]))
myplots
#> [[1]]

#> 
#> [[2]]

由reprex package (v0.3.0) 于 2021-04-09 创建

【讨论】:

  • 使用 lapply 时不需要myplots &lt;- list()。如果您有按行分隔的数据,为什么不首先将其排列在列表中?然后,您可以使用所有应用函数和 purrr 等更轻松地遍历列表。我会通过按行拆分数据框来创建一个列表,然后遍历每个数据框。
猜你喜欢
  • 2020-02-02
  • 2021-10-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-22
  • 2011-11-02
  • 1970-01-01
相关资源
最近更新 更多