在 R 中使用循环的多个绘图

Posted

技术标签:

【中文标题】在 R 中使用循环的多个绘图【英文标题】:Multiple plots using loops in R 【发布时间】:2014-01-20 10:49:24 【问题描述】:

我仍在尝试使用循环在 R 中绘图。我想根据中的不同名称在下面的数据框中绘制(任何可视化数据的绘图都可以)列 z_1 与 z_2 x_1 列。

x_1 <- c("A1", "A1","A1", "B10", "B10", "B10","B10", "C100", "C100", "C100")


z_1 <- rnorm(10, 70) 

z_2 <- rnorm(10, 1.7)

A <- data.frame(x_1, z_1, z_2)

因此,我想以三个不同的情节结束;一个用于 A1 类,一个用于 B10,另一个用于 C100。我可以使用三个不同的代码来做到这一点,但我希望能够使用循环或任何其他单个代码在同一页面上执行所有三个绘图。实际上,我有一个大型数据集(4,000 行),并且想在一页上绘制几个 ID(比如一页上 5 个)。

我希望这是有道理的。谢谢你的帮助。

这是我单独绘制它们的尝试:

对于 A1:

data_A1 <- A[which(A$x_1 == "A1"), ]
plot(data_A1$z_2, data_A1$z_1)

我也尝试过类似的方法,但收到错误消息

for ( i in A$x_1[[i]])

plot(A[which(A$x_1==A$x_1[[i]]), ], aspect = 1)

【问题讨论】:

如果你展示了你迄今为止所做的实际尝试,并解释它是如何不起作用的,我可能会想帮忙。 @joran,我将编辑我的帖子以包含我迄今为止的尝试。谢谢。 小事,但你犯了过度使用which的常见错误。尝试运行x &lt;- runif(10),然后比较x[x &lt; 0.5]x[which(x &lt; 0.5)]。与上面的代码一样,您可以省略 which 以获得相同的结果。 @shujaa,感谢您的提示,非常感谢。 @Shujaa,你有没有机会帮助重写我的原始代码以使其工作? 【参考方案1】:

一个简单的循环方法是

for (cat in unique(x_1))
  d <- subset(A, x_1 == cat)
  plot(d$z_1, d$z_2)

unique(x_1) 为您提供x_1 的所有唯一值。然后,为这些值中的每一个获取一个对应的子集,并使用该子集进行绘图。

【讨论】:

@Mark Heckmann,非常感谢您提供的代码,它运行良好。我正在尝试对其进行编辑,使其使用布局功能在一个页面上绘制所有三个 - 还没有。 @Mark Heckmann,我刚刚再次查看了代码。我不太清楚为什么在上面的代码中我只得到 C100 类别作为 d 的输出。为什么它给出 C100 类别而不是 A1 或 B10? @John 我无法重现您的问题,请详细说明。对我来说效果很好。 真的很抱歉打扰你。为了确定,我刚刚再次执行了代码。我对d &lt;- subset(A, x_1==cat) 的输出为我提供了 ff 3 行:8 C100 71.08877 1.892950、9 C100 71.29257 1.144764、10 C100 71.28251 1.974991。这不是你得到的吗? @John for 循环的要点是d 每次都会被覆盖,x_1 的每个唯一值都会覆盖一次。因为C100 是最后一个值,所以当for 循环结束时d 将处于它的最终状态。【参考方案2】:

只是为了了解为什么您的原始代码不起作用:

设置数据工作正常

x_1 <- c("A1", "A1", "A1", "B10", "B10", "B10","B10", "C100", "C100", "C100")
z_1 <- rnorm(10, 70) 
z_2 <- rnorm(10, 1.7)
A <- data.frame(x_1, z_1, z_2)

个别情节运作良好,但正如我在评论中所说,which 是不必要的

data_A1 <- A[which(A$x_1 == "A1"), ] # your way
plot(data_A1$z_2, data_A1$z_1)

data_A1 <- A[A$x_1 == "A1", ]    # deleting which() makes it cleaner
with(data_A1, plot(z_2, z_1))    # you can also use with() to save typing

现在是 for 循环。让我们回顾一下 R 中的一个简单 for 循环(非常接近 ?"for" 中的示例):

for (i in 1:5) 
   print(1:i)

很简单,1:5c(1, 2, 3, 4, 5),所以首先 i1,然后是 2,等等。你的 for 循环在第一行有问题:

for (i in A$x_1[[i]])  ## already a problem

第一个iA$x_1[[i]]?那行不通,i 尚未定义。此外,A$x_1 是一个向量,而不是一个列表,因此您不应该使用 [[ 对其进行子集化。但是我们还不需要一个子集,我们想要一个包含i 应该采用的值的向量。在这种情况下,我们想要的是for (i in c("A1", "B10", "C100")),但我们也希望以编程方式完成,而不是输入所有不同的可能性。有几种常见的方法可以做到这一点:

unique(A$x_1) # as in Mark's solution
levels(A$x_1) # works because A$x_1 is a factor

我们可以将这些表达式中的任何一个放在in 之后。我在情节调用中将您的[[ 更改为[[[ 仅用于列表。我也去掉了不必要的which()

for (i in unique(A$x_1))    # this line is good
    plot(A[A$x_1==A$x_1[i], ], aspect = 1)  # still a problem

让我们提醒自己i 的价值观是:"A1""B10""C100"A$x_1 == A$x_1["A1"] 会给什么?没什么用。

for (i in unique(A$x_1))   
    plot(A[A$x_1 == i, ], aspect = 1)  # getting there

上面的代码绘制了一些东西,它很整洁,但这不是你想要的。有一堆警告,它们都告诉我们aspect 不是一个有效的参数,所以我们将其删除。查看绘图,您会看到它绘制了 3 个变量,因为我们还没有告诉它在 x 和 y 轴上放置什么。

for (i in unique(A$x_1))    
    plot(A[A$x_1==i, "z_2"], A[A$x_1==i, "z_1"])  # z_2 on x, z_1 on y 
   # Works!!!

请注意,这与马克的回答几乎相同。你不必在 for 循环中使用 ij,他使用了 cat。使用更具描述性的名称是一种很好的做法。 现在让我们把它想象一下:

for (i in unique(A$x_1))    
    plot(A[A$x_1==i, "z_2"], A[A$x_1==i, "z_1"],
         xlim = range(A$z_2), ylim = range(A$z_1), # base the axes on full data range
         main = paste("Plot of", i))  # Give each a title

下一次:不要忘记您可以运行一小段代码来查看它们是什么。如果您有类似for (i in A$x_1[[i]]) 的行不确定是否正确,请在控制台输入A$x_1[[i]],希望这能帮助您确定您尚未定义i,因此您将对其进行更改到

for (i in A$x_1)

然后你运行 A$x_1 并意识到它的长度是 10。你想要 3 个图,而不是 10 个,所以你需要 i 获取 3 个值,它们都不同,等等。

【讨论】:

太棒了!这可能是我从这个论坛收到的最好的答案。现在我更好地理解了循环。谢谢shujaa。【参考方案3】:

也许您不需要循环。尝试使用 ggplots facet_grid()。 这是documentation,充满了例子。

library(ggplot2)
library(reshape2)

melted_a <- melt(A)


ggplot(melted_a, aes(variable, value)) +
  geom_jitter() +
  facet_grid(. ~ x_1)

ggplot(melted_a, aes(variable, value)) +
  geom_jitter() +
  facet_grid(variable ~ x_1)

编辑 也许这可以解决这个问题。但是,如果您需要绘制许多具有相似结构的绘图,您可以创建一个函数并使用aes_string() 而不是aes()。 注意:我不是编写函数的专家,所以可能有人可以编辑和改进它。 (未测试)

ggplot_fun <- function(data, x, y, rowfacet, colfacet, ...)
  p <- ggplot(data, aes_string(x, y))
  p <- p + geom_jitter()
  p <- p + facet_grid(as.formula(sprintf("%s ~ %s", rowfacet, colfacet))


ggplot_fun(melted_a, variable, value, variable, x_1)

来自question的想法。

【讨论】:

@Martin Bel,非常感谢您提供有用的参考资料和代码,我会花时间通读一遍。【参考方案4】:

您还可以调整数据,例如我在这里所做的......

如果我想要按日期绘制的图和 xlab、ylab 和图的标题具有特定的详细信息...

 for ( i in 1:length(unique(wheeldata$Date)) )
     d <- subset( wheeldata, Date == unique ( wheeldata$Date )[i] )
     plot(d$X, d$Y, xlab = "X", ylab = "Y", main = paste0("Date: ",  unique(d$Date)) )
 

【讨论】:

以上是关于在 R 中使用循环的多个绘图的主要内容,如果未能解决你的问题,请参考以下文章

Rmarkdown(knitr chunk)文档中生成的多个(R)绘图图形

R:保存绘图 - 仍在 RStudio 中时无法打开图像

在 matplotlib 中使用 for 循环定义要动画的多个绘图

有没有办法用 char 变量创建一个 for 循环来创建多个绘图?

绘图覆盖,所以在 R 循环结束时,都从列表的最后一个元素中拉出。我究竟做错了啥?

在 for 循环中以 pdf 格式保存 2-plot 图形