![](/img/trans.png)
[英]How to assign unique title and text labels to ggplots created in lapply loop?
[英]How to make multiple ggplots in a loop with conditional labels
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()
}
問題是這些圖形標簽通常是隱藏的,或者當我使用較大的數據集時,我無法讀取它們。 因此,我想使用 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) 相同:標簽”,並且不確定如何解決該問題。
你可以像這樣達到你想要的結果:
雖然在大多數情況下使用df[,i]
會起作用,但不推薦使用,並且確實存在不起作用的情況。 相反,如果您想通過字符串引用變量,您可以使用所謂的.data
代詞,即使用.data[[i]]
。
要獲得條件標簽,您可以將ifelse(.data[[i]] <= cutoff, Name, "")
映射到aes()
(!!) 內的label
美學上。
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()
}
首先編輯。 如果您想使用過濾器,最好將行名作為新變量添加到您的數據集中,例如使用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"
))
另一種方法是創建一個繪圖函數,然后將該函數應用於每個“值”,例如
library(tidyverse)
library(ggrepel)
plot_data <- function(ValueX) {
ValueX <- ensym(ValueX)
ggplot(df, aes(y = !!ValueX,
x = Name)) +
geom_text_repel(aes(label = ifelse(!!ValueX < 0,
Name, NA))) +
geom_point() +
theme_bw(base_family = "Helvetica", base_size = 14) +
ggtitle(ValueX) +
theme(axis.ticks.x = element_blank(),
legend.position = "none")
ggsave(filename = paste(ValueX,
"plot.png",
sep = "_"),
device = "png")
}
df <- readr::read_table(" 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") %>%
select(-c(X1))
## Collate unaltered colnames into a vector
vector_of_colnames <- colnames(df)[-1]
## Plot
lapply(vector_of_colnames, plot_data)
這種方法是否對您有用取決於您的用例。 在我自己的工作中,我必須一次生成多達 35,000 個圖,這種方法比使用循環有優勢,例如,我通常將圖像整理成單個 pdf,而不是生成大量單獨的文件(例如,一個 3 頁的文件,每頁一個圖):
library(tidyverse)
library(ggrepel)
plot_data <- function(ValueX) {
ValueX <- ensym(ValueX)
ggplot(df, aes(y = !!ValueX,
x = Name)) +
geom_text_repel(aes(label = ifelse(!!ValueX < 0,
Name, NA))) +
geom_point() +
theme_bw(base_family = "Helvetica", base_size = 14) +
ggtitle(ValueX) +
theme(axis.ticks.x = element_blank(),
legend.position = "none")
}
df <- readr::read_table(" 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") %>%
select(-c(X1))
## Collate unaltered colnames into a vector
vector_of_colnames <- colnames(df)[-1]
pdf(file=paste0("All_plots.pdf"))
lapply(vector_of_colnames, plot_data)
dev.off()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.