使用 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)
我制作了这个精彩的条形图(见下文)。为了按地区快速对我的国家/地区进行分组,我添加了 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:您使用 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)