gpt4 book ai didi

r - 如何处理ggplot2和离散轴上的重叠标签

转载 作者:行者123 更新时间:2023-12-04 04:25:15 25 4
gpt4 key购买 nike

ggplot2似乎没有内置的方法来处理scatter plots上的文本的过度绘图。但是,在另一种情况下,标签是离散轴上的标签,我想知道这里的人是否有比我以前做的更好的解决方案。

一些示例代码:

library(ggplot2)

#some example data
test.data = data.frame(text = c("A full commitment's what I'm thinking of",
"History quickly crashing through your veins",
"And I take A deep breath and I get real high",
"And again, the Internet is not something that you just dump something on. It's not a big truck."),
mean = c(3.5, 3, 5, 4),
CI.lower = c(4, 3.5, 5.5, 4.5),
CI.upper = c(3, 2.5, 4.5, 3.5))

#plot
ggplot(test.data, aes_string(x = "text", y = "mean")) +
geom_point(stat="identity") +
geom_errorbar(aes(ymax = CI.upper, ymin = CI.lower), width = .1) +
scale_x_discrete(labels = test.data$text, name = "")

因此,我们看到x轴标签彼此重叠。有两种解决方案:1)缩写标签,以及2)在标签上添加换行符。在许多情况下(1)可以,但在某些情况下则无法做到。因此,我编写了一个函数,用于在字符串中每第n个字符添加换行符( \n),以避免名称重叠:
library(ggplot2)

#Inserts newlines into strings every N interval
new_lines_adder = function(test.string, interval){
#length of str
string.length = nchar(test.string)
#split by N char intervals
split.starts = seq(1,string.length,interval)
split.ends = c(split.starts[-1]-1,nchar(test.string))
#split it
test.string = substring(test.string, split.starts, split.ends)
#put it back together with newlines
test.string = paste0(test.string,collapse = "\n")
return(test.string)
}

#a user-level wrapper that also works on character vectors, data.frames, matrices and factors
add_newlines = function(x, interval) {
if (class(x) == "data.frame" | class(x) == "matrix" | class(x) == "factor") {
x = as.vector(x)
}

if (length(x) == 1) {
return(new_lines_adder(x, interval))
} else {
t = sapply(x, FUN = new_lines_adder, interval = interval) #apply splitter to each
names(t) = NULL #remove names
return(t)
}
}

#plot again
ggplot(test.data, aes_string(x = "text", y = "mean")) +
geom_point(stat="identity") +
geom_errorbar(aes(ymax = CI.upper, ymin = CI.lower), width = .1) +
scale_x_discrete(labels = add_newlines(test.data$text, 20), name = "")

输出为:

这样一来,您就可以花一些时间来处理间隔大小,以避免标签之间的空白过多。

如果标签的数量不同,则这种解决方案就不太理想,因为最佳间隔大小会发生变化。另外,由于普通字体不是等宽字体,因此标签文本也会对宽度产生影响,因此在选择合适的间隔时必须格外小心(可以通过使用等宽字体来避免这种情况) ,但它们特别宽)。最后, new_lines_adder()函数很愚蠢,它将以人类无法做到的愚蠢方式将单词分为两部分。例如。在上面,它将“呼吸”分为“br\nreath”。可以重新编写它以避免此问题。

也可以减小字体大小,但这是在可读性上的一种折衷,通常不必减小字体大小。

处理此类标签过度绘图的最佳方法是什么?

最佳答案

我试图将不同版本的new_lines_adder放在一起:

new_lines_adder = function(test.string, interval) {
#split at spaces
string.split = strsplit(test.string," ")[[1]]
# get length of snippets, add one for space
lens <- nchar(string.split) + 1
# now the trick: split the text into lines with
# length of at most interval + 1 (including the spaces)
lines <- cumsum(lens) %/% (interval + 1)
# construct the lines
test.lines <- tapply(string.split,lines,function(line)
paste0(paste(line,collapse=" "),"\n"),simplify = TRUE)
# put everything into a single string
result <- paste(test.lines,collapse="")
return(result)
}

它仅在空格处分割行,并确保这些行最多包含 interval给定的字符数。这样,您的情节如下所示:

我不会声称这是最好的方法。它仍然忽略并非所有字符都具有相同的宽度。也许可以使用 strwidth达到更好的效果。

顺便说一句:您可以将 add_newlines简化为以下内容:
add_newlines = function(x, interval) {

# make sure, x is a character array
x = as.character(x)
# apply splitter to each
t = sapply(x, FUN = new_lines_adder, interval = interval,USE.NAMES=FALSE)
return(t)
}

首先, as.character确保您具有一个字符串。如果您已经有一个字符串,那么这样做也没有什么害处,因此不需要 if子句。

同样,下一个 if子句也是不必要的:如果x仅包含一个元素,则sapply可以完美地工作。而且,您可以通过设置 USE.NAMES=FALSE来隐藏名称,这样您就无需在其他行中删除名称。

关于r - 如何处理ggplot2和离散轴上的重叠标签,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30598347/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com