使用 ggplot 和空限对条形图中的条形进行分组,但要避免不一致 axis.ticks

Group bars in bar plot using ggplot and empty limits, but avoid inconsistent axis.ticks

我制作了这个精彩的条形图(见下文)。为了按地区快速对我的国家/地区进行分组,我添加了 scale_x_discrete(limits = ORDER ) 和一些空限制 ""(由 ORDER 指定)。它在图中添加了空条,这对我来说似乎工作正常,但 axis.ticks 不一致。我没有添加 axis.ticks(我更喜欢),但是对于最后一个空栏,它添加了。为什么?如何去掉这个单勾号?

ORDER <- c("Kiribati",  "Marshall Islands",  "Palau",  "States of Micronesia",
       "",
       "Micronesia g." ,
       "",
       "Fiji",  "Nauru",  "PNG",  "Solomon Islands",  "Vanuatu",
       "",
       "Melanesia g.",
       "",
       "Cook Islands",  "Niue",  "Samoa",  "Tonga",  "Tuvalu",
       "",
       "Polynesia g."
      )
ORDER

ggplot(ESA_coun_p ,aes(x=x, y=y))+
 geom_col(position="dodge", na.rm=TRUE)+
 scale_x_discrete(limits = ORDER )+
 coord_flip()  

thothal 和 Romain B. 对解决问题给出了一些很好的回答,包括正反两方面。

@thothal:您使用 labels 而不是 limits 的建议使绘图保持一致,因为它向所有空分隔条添加了轴刻度。但是,它可能需要对一些空的额外观察和重新排序因子进行硬编码。它也没有很好地区分不同的群体。

@Romain B.:您的建议非常有效,并且可以清楚地区分不同的群体。然而,我 运行 遇到了一些更复杂的图的困难,一个 "gap bar plot",它允许在异常值的情况下更好地比较值(见下面你的例子调整)。

set.seed(10)
test <- data.frame(country = LETTERS[1:12], 
                   region = c(1,1,1,1,2,2,3,4,4,4,5,5), 
                   value = rnorm(12, m = 10))%>%
 mutate(value=replace(value, country=='A', 100))

# I'm ordering by <value> here, so in the plot, they'll be ordered as such 
test$country <- factor(test$country, levels = test$country[order(test$value)])
######
trans_rate_surf <- 0.02   ##play around, defines cropping of the cut of values
white_space_min_surf <- 20 ##littel bit above the last fully displaied bar
white_space_max_surf<- 80 ##littel bit below the first cropped bar
#####  
trans_surf <- function(x){pmin(x,white_space_min_surf) + trans_rate_surf*pmax(x-white_space_min_surf,0)}
yticks_surf <- c(5, 10, 15, 20,  100) ## not within or too close to the white space
##
test$value_t <- trans_surf(test$value)

ggplot(test, aes(x = country, y = value_t)) + geom_bar(stat = 'identity') + coord_flip()+
 geom_rect(aes(xmin=0, xmax=nrow(test)+0.6, ymin=trans_surf(white_space_min_surf), ymax=trans_surf(white_space_max_surf)), fill="white")+
 scale_y_continuous(limits=c(0,NA), breaks=trans_surf(yticks_surf), labels=yticks_surf)

如果我现在添加 + facet_grid(rows = vars(region), scales = "free_y", space = "free_y") 一切都搞砸了,因为 xmax=nrow(test) 不再适合,但需要对区域敏感。

你可以有一个 region 变量并根据它对图进行分面。然后您可以玩小平面图间距。

你没有提供数据,所以我做了一个虚拟的 test 数据框。

set.seed(10)
test <- data.frame(country = LETTERS[1:12], 
                   region = c(1,1,1,1,2,2,3,4,4,4,5,5), 
                   value = rnorm(12, m = 10))

# I'm ordering by <value> here, so in the plot, they'll be ordered as such 
test$country <- factor(test$country, levels = test$country[order(test$value)])

ggplot(test, aes(x = country, y = value)) + geom_bar(stat = 'identity') + 
  facet_grid(rows = vars(region), scales = "free_y", space = "free_y") + coord_flip() +
  theme(panel.spacing = unit(1, "lines")) # play with this to spread more

这会产生

虽然我在这里按价值排序,但你可以根据你的因素水平给出你想要的顺序。

编辑:"gap"

我要在这里声明一下,我个人认为使用带有轴中断或间隙的图不是一个好主意。 This has been extensively discussed on this website before 并且有很多解决方法(例如 转换您的数据,使用对数刻度、构建索引等)。

既然你试图以你的方式强制它,我会给你另一个解决方法:使用宽度较大的线。

trans_rate_surf <- 0.02   ##play around, defines cropping of the cut of values
white_space_min_surf <- 20 ##littel bit above the last fully displaied bar
white_space_max_surf<- 80 ##littel bit below the first cropped bar
#####  
trans_surf <- function(x){pmin(x,white_space_min_surf) + trans_rate_surf*pmax(x-white_space_min_surf,0)}
yticks_surf <- c(5, 10, 15, 20,  100) ## not within or too close to the white space
##
test$value_t <- trans_surf(test$value)

ggplot(test, aes(x = country, y = value_t)) + geom_bar(stat = 'identity') + coord_flip() +
  scale_y_continuous(limits=c(0,NA), breaks=trans_surf(yticks_surf), labels=yticks_surf) +
  facet_grid(rows = vars(region), scales = "free_y", space = "free_y") + coord_flip() +
  theme(panel.spacing = unit(1, "lines")) + # play with this to spread more
  geom_hline(yintercept = trans_surf(50), size = 10, color = "white")

情节的最后一行是我对您的 post 代码所做的唯一更改。结果,我得到:

您应该使用 labels 而不是 limits。下面的玩具示例 b/c 您没有提供 regrex.

说明

使用 limits 可以设置 limits 的比例。由于它是离散量表,因此需要唯一的数据点。但是你的 labels 并不是独一无二的。你想要的是设置比例的 labels ,因此你应该使用参数 labels.

数据

library(tidyverse)
set.seed(1)
my_dat <- mtcars %>% 
    rownames_to_column() %>% 
    as_tibble() %>% 
    select(rowname, mpg) %>% 
    add_row(rowname = paste0("remove", 1:3), mpg = rep(0, 3)) %>% 
    slice(sample(NROW(.))) %>% 
    mutate(rowname = factor(rowname, rowname))

p <- ggplot(my_dat, aes(x=rowname, y = mpg)) + 
   geom_col(position = "dodge", na.rm=F) + 
   coord_flip()

rn <- gsub("^remove[0-9]+", "", my_dat$rowname)

使用方法错误 limits

p + scale_x_discrete(limits = rn)

使用labels

的正确方法
p + scale_x_discrete(labels = rn)