【发布时间】:2015-08-16 09:06:18
【问题描述】:
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”。可以重写它来避免这个问题。
也可以减小字体大小,但这是对可读性的折衷,而且通常没有必要减小字体大小。
处理这种标签重叠的最佳方法是什么?
【问题讨论】:
-
我通常通过旋转它们来处理重叠标签:
+ theme(axis.text.x = element_text(angle = 60, hjust = 1))(但如果它们很长则不理想,因为它会产生很大的边距)
标签: r plot ggplot2 axis-labels