r - 如何使用条件标签在循环中制作多个ggplots

标签 r for-loop ggplot2

  Name      Value1     Value2     Value3
1   A1 -0.05970872 -1.1651404  1.3516952
2   A2  0.44143488 -0.7270722 -1.9870423
3   A3  0.34616897 -0.3891095  0.9123736
4   A4  0.49289331  1.3957877 -0.2689896
5   A5 -1.39354557  0.9429327  1.0719274

我有上面的数据框,我想在 ggplot2 中为其生成四个图表,每个图表的 x 轴作为“名称”列,y 轴作为其他列的值。虽然 x 轴不需要有“刻度线”,但如果 y 轴低于截止值(例如 0),我确实想有条件地使用相应“名称”列值的名称来标记这些点。下面是我的代码使用 R 中的基本绘图函数通过循环函数自动生成图形。我附上了一张示例图。

cutoff = 0
df = read.csv("Book4.csv", header = TRUE)
list = rownames(df)
for(i in names(df)){
  png(filename = paste(i,".png"))
  plot(df[,i],
       main = i, 
       ylab = "Values",
       xlab = "Names",
       col = ifelse(df[,i]<cutoff, 'red', 'gray'),
       pch = ifelse(df[,i] < cutoff, 10, 1)
  )
  abline(cutoff, 0, col= "blue", lty=2)
  outlier = which(df[,i]<=cutoff)
  if (length(outlier)>0){
    text(outlier, df[outlier,i], list[outlier], cex=0.7, pos=2)
  }
  dev.off()
  
}

Sample Graph generated

问题是这些图形标签通常是隐藏的,或者当我使用较大的数据集时重叠,因此我无法读取它们。因此,我想使用 ggplot2 和函数 geom_text_repel 重现这一点。我尝试使用 for 循环来执行此操作,但在使用 geom_text_repel 点标记的实现中陷入困境,因为我不确定如何有条件地使用它进行标记。我将生成超过 200 个 png,因此如果它可以自动化并以“Value1.png”、“Value2.png”等文件名输出,我将不胜感激。

这是我在下面的 ggplot 中的尝试

cutoff = 0
df = read.csv("Book4.csv", header = TRUE, row.names = 1)    
for(i in colnames(df)){
      png(filename = paste(i,".png"))
      outlier = which(df[,i]<=cutoff)
      print(ggplot(df, aes(x = rownames(df), y = df[,i])) +
              geom_point() + 
              geom_text_repel(data = df, label=outlier))
      dev.off()
    }

我不断收到错误“错误:美学必须是长度 1 或与数据 (5): 标签相同”,并且不确定如何解决该问题。

最佳答案

你可以像这样达到你想要的结果:

  1. 使用df[,i]时在大多数情况下会起作用,但不推荐,并且确实在某些情况下它不起作用。相反,如果您想通过字符串引用变量,您可以使用所谓的 .data代词,即使用.data[[i]] .

  2. 要获取条件标签,您可以映射 ifelse(.data[[i]] <= cutoff, Name, "")关于label内在美学aes() (!!)。

library(ggplot2)
library(ggrepel)

cutoff <- 0

for (i in colnames(df)) {
  png(filename = paste(i, ".png"))
  gg <- ggplot(df, aes(x = rownames(df), y = .data[[i]])) +
    geom_point() +
    geom_text_repel(aes(label = ifelse(.data[[i]] <= cutoff, Name, "")))
  print(gg)
  dev.off()
}

enter image description here

编辑首先。如果您想使用过滤器,最好将行名作为新变量添加到数据集中,例如使用df$x <- rownames(x) ,可以映射到 x (我猜这就是您收到错误消息的原因)。之后您可以使用data = dplyr::filter(df, .data[[i]] <= cutoff)作为数据集。

注意 不过,有一点需要注意。如果您想添加另一个geom_point,这种方法就很好。仅包含您的数据的子集。如果是geom_text_repel但是不建议这样做(这就是我使用 ifelse 的原因)。原因是,geom_text_repel只有了解全部数据才能做好工作。如果仅传递一个子集,则标签通常会与子集数据中缺失的点重叠,如 geom_text_repel不知道这些在那里。

df$x <- row.names(df)
for (i in colnames(df)) {
  png(filename = paste(i, ".png"))
  gg <- ggplot(df, aes(x = x, y = .data[[i]])) +
    geom_point() +
    geom_text_repel(data = dplyr::filter(df, .data[[i]] <= cutoff), aes(x = x, y = .data[[i]], label = Name))
  print(gg)
  dev.off()
}

数据

df <- structure(list(Name = c("A1", "A2", "A3", "A4", "A5"), Value1 = c(
      -0.05970872,
      0.44143488, 0.34616897, 0.49289331, -1.39354557
    ), Value2 = c(
      -1.1651404,
      -0.7270722, -0.3891095, 1.3957877, 0.9429327
    ), Value3 = c(
      1.3516952,
      -1.9870423, 0.9123736, -0.2689896, 1.0719274
    )), class = "data.frame", row.names = c(
      "1",
      "2", "3", "4", "5"
    ))

关于r - 如何使用条件标签在循环中制作多个ggplots,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64343500/

相关文章:

r - ggplot2 中的嵌套 facet_wrap()

r - 如何展平从 jsonlite 返回的嵌套数据帧

Python 在嵌套 for 循环中编写嵌套 if-else 的有效方法

r - 如何在 ggplot2 中以对数刻度显示 stat_binhex

r - 如何在 ggplot 之后使用 %T>% 管道?

r - 时间序列和 MA 模型在 R 中看起来相同

java - 将循环结果添加到数组中?

php - 检查数组元素是否在不同的数组中

r - 使用相同 glm 的 glm 预测和 geom_smooth() 之间的差异

r - 如何使用 geom_bar (ggplot2) 垂直居中标签