我想绘制背对背的条形图,但是每侧都在一个独立的轴上。我可以通过取一组负值来将它们背对背绘制,但这使它们处于相同的访问方式,并且因为p值较小,所以它们的条形几乎无法表示。
library(ggplot2)
df <-structure(list(Description = c("a", "b", "c", "d", "e", "f",
"g", "h", "a", "b", "c", "d", "e", "f", "g", "h"), test = c("size",
"size", "size", "size", "size", "size", "size", "size", "p",
"p", "p", "p", "p", "p", "p", "p"), value = c(0.1, 0.1, 0.125,
0.1, 0.075, 0.1, 0.075, 0.125, 0.000230705311441713, 0.000314488619269942,
0.00106639822095382, 0.00108290238851994, 0.00114723539549198,
0.00160204850890075, 0.0019276388745184, 0.00320371567547557)), .Names = c("Description",
"test", "value"), row.names = c(NA, -16L), class = "data.frame")
df$value[df$test == 'p'] <- -(df$value[df$test == 'p'])
ggplot(df, aes(x=Description, y= value, group=test, fill=test)) + geom_col() +coord_flip()
理想情况下,我希望每个组都在独立的轴上,以使条形点在零点处(在绘图区域的中间)相交,但在本示例中,ylim的比例不同c(0,0.0035)
答案 0 :(得分:3)
您可以通过以下方式进行操作:调整切面以消除切面之间的间距:
ggplot(df, aes(x=Description, y= value, fill=test)) +
facet_wrap(~ test, scales = "free_x") +
geom_col() +
coord_flip() +
scale_y_continuous(expand = c(0, 0)) +
theme(panel.spacing.x = unit(0, "mm"))
这可能会导致轴标签出现一些问题,要解决这些问题有些棘手。在这种情况下,在小平面之间保留一些空间可能会更容易,但要以没有在中间相遇为代价。
输出:
PS:您还可以使用以下方法删除负轴标签:
scale_y_continuous(
expand = c(0, 0),
labels = function(x) signif(abs(x), 3)
)
答案 1 :(得分:1)
@Marius解决方案比此解决方案更容易,但这可以独立控制每个图形。
我必须删除p1右侧和p2左侧的绘图边距。由于某种原因,在左边距有填充,因此需要-3.5pt使其平齐,不确定在所有图上是否一致。另一个手动操作是更改一个轴上的中断,这样就不会在彼此的顶部绘制0。
我也不需要只使用<section class="container">
<form action="" class="form">
<div class="section-bio">
<div class="section-header section-header--nouvelle-section">
<button type="button" class="btn btn-nouvelle-section">Add</button>
</div>
</div>
</form>
</section>
scale_y_reverse
我也使用过p1 <- ggplot(df[df$test == 'p',], aes(x=Description, y= value)) + geom_col(fill='red') + theme_minimal()+
coord_flip() + scale_y_reverse(name= "axis1",expand = expand_scale(mult= c(c(0.05,0)))) +
theme(panel.spacing.x = unit(0, "mm")) +theme(plot.margin = unit(c(5.5, 0, 5.5, 5.5), "pt"))
p2 <- ggplot(df[df$test != 'p',], aes(x=Description, y= value)) + geom_col(fill='blue') +
scale_y_continuous(name = "axis2", breaks = seq(0.025, 0.125, 0.025) ,expand = expand_scale(mult= c(c(0,0.05)))) +
coord_flip() +
theme(panel.spacing.x = unit(0, "mm"))+ theme_minimal() +
theme(axis.title.y=element_blank(), axis.text.y=element_blank(),
axis.line.y = element_blank(), axis.ticks.y=element_blank(),
plot.margin = unit(c(5.5, 5.5, 5.5, -3.5), "pt"))
grid.newpage()
grid.draw(cbind(ggplotGrob(p1), ggplotGrob(p2), size = "last"))
,但这只是出于我的审美偏好。
答案 2 :(得分:1)
我已经根据我的需要调整了 this elegant solution。为张凌云点赞。
library(dplyr)
library(ggplot2)
set.seed(123)
ten_positive_rand_numbers <- abs(rnorm(10)) + 0.1
the_prob <- ten_positive_rand_numbers / sum(ten_positive_rand_numbers)
fk_data <- data.frame(job_type = sample(LETTERS[1:10], 1000,
replace = TRUE, prob = the_prob),
gender = sample(c("Male", "Female"), 1000,
replace = TRUE))
# prepare data for plotting
plotting_df <-
fk_data %>%
group_by(job_type, gender) %>%
summarise(Freq = n()) %>%
# a trick!
mutate(Freq = if_else(gender == "Male", -Freq, Freq))
## find the order
temp_df <-
plotting_df %>%
filter(gender == "Female") %>%
arrange(Freq)
the_order <- temp_df$job_type
# plot
p <-
plotting_df %>%
ggplot(aes(x = job_type, y = Freq, group = gender, fill = gender)) +
geom_bar(stat = "identity", width = 0.75) +
coord_flip() +
scale_x_discrete(limits = the_order) +
# another trick!
scale_y_continuous(breaks = seq(-150, 150, 50),
labels = abs(seq(-150, 150, 50))) +
labs(x = "Job type", y = "Count", title = "Back-to-back bar chart") +
theme(legend.position = "bottom",
legend.title = element_blank(),
plot.title = element_text(hjust = 0.5),
panel.background = element_rect(fill = "grey90")) +
# reverse the order of items in legend
# guides(fill = guide_legend(reverse = TRUE)) +
# change the default colors of bars
scale_fill_manual(values = c("red", "blue"),
name = "",
breaks = c("Male", "Female"),
labels = c("Male", "Female"))
print(p)
可以通过其他小细节进行改进,包括 geom_hline(yintercept = 0, colour = "black")
。