ggplot2:为条形图的构面布局中的行指定不同的比例

时间:2017-08-15 00:03:31

标签: r ggplot2 facet facet-wrap facet-grid

我的数据在包ggplot2中通过带有几个(~10)面的条形图可视化。我想首先将这些方面分成几行。我可以使用函数facet_grid()facet_wrap()。在这里的最小示例数据中,我在两行(4x2)中构建了8个面。但是我需要调整不同方面的比例,即:第一行包含小规模数据,第二行数值更大。所以我需要为第一行中的所有数据设置相同的比例,以便沿着行比较它们,并为第二行比较另一个比例。

这是最小的例子和可能的解决方案。

#loading necessary libraries and example data
library(dplyr)
library(tidyr)
library(ggplot2)

trial.facets<-read.csv(text="period,xx,yy
A,2,3
B,1.5,2.5
C,3.2,0.5
D,2.5,1.5
E,11,13
F,16,14
G,8,5
H,5,4")

#arranging data to long format with omission of the "period" variable
trial.facets.tidied<-trial.facets %>% gather(key=newvar,value=newvalue,-period)

现在正在策划自己:

#First variant
ggplot(trial.facets.tidied,aes(x=newvar,y=newvalue,position="dodge"))+geom_bar(stat ="identity") +facet_grid(.~period)

#Second variant:
ggplot(trial.facets.tidied,aes(x=newvar,y=newvalue,position="dodge"))+geom_bar(stat ="identity") +facet_wrap(~period,nrow=2,scales="free")

第一个和第二个变体的结果如下:

enter image description here

在这两个例子中,我们有所有图形的自由尺度,或者所有图形都是固定的。同时第一行(前4个方面)需要稍微缩放到5,第二行需要缩放到15。

作为使用facet_grid()函数的解决方案,我可以添加一个假变量&#34; row&#34;它指定相应字母属于哪一行。新数据集trial.facets.row(仅显示三行)如下所示:

period,xx,yy,row
C,3.2,0.5,1
D,2.5,1.5,1
E,11,13,2

然后我可以对长格式执行相同的重新排列,省略变量&#34; period&#34;和&#34;行&#34;:

trial.facets.tidied.2<-trial.facets.row %>% gather(key=newvar,value=newvalue,-period,-row)

然后我按照变量排列方面&#34; row&#34;和&#34;期间&#34;希望使用选项scales="free_y"仅针对行调整比例:

ggplot(trial.facets.tidied.2,aes(x=newvar,y=newvalue,position="dodge"))+geom_bar(stat ="identity") +facet_grid(row~period,scales="free_y")

和 - 惊讶:解决了尺度问题,然而,我得到两组空条,并且整个数据再次在长条带上拉伸:

enter image description here

所有发现的手册页和手册(通常使用mpg和mtcars数据集)都没有考虑这种不需要的或虚假数据的情况

3 个答案:

答案 0 :(得分:3)

我使用了第一种方法(facet_wrap)和&amp;的组合。第二种方法(利用不同行的虚拟变量):

# create fake variable "row"
trial.facets.row <- trial.facets %>% mutate(row = ifelse(period %in% c("A", "B", "C", "D"), 1, 2))
# rearrange to long format
trial.facets.tidied.2<-trial.facets.row %>% gather(key=newvar,value=newvalue,-period,-row)
# specify the maximum height for each row
trial.facets.tidied.3<-trial.facets.tidied.2 %>%
  group_by(row) %>%
  mutate(max.height = max(newvalue)) %>%
  ungroup()

ggplot(trial.facets.tidied.3,
       aes(x=newvar, y=newvalue,position="dodge"))+
  geom_bar(stat = "identity") +
  geom_blank(aes(y=max.height)) + # add blank geom to force facets on the same row to the same height
  facet_wrap(~period,nrow=2,scales="free")

resulting plot

注意:基于这个可重复的例子,我假设你的所有图已经在0处共享一个共同的ymin。如果不是这样的话,只需为min.height&amp;创建另一个虚拟变量。在你的ggplot中添加另一个geom_blank

答案 1 :(得分:2)

仔细观察我遇到了一个可能有点棘手的解决方案 - from here

我们的想法是创建第二个假数据集,该数据集将在每个方面绘制单个点。该点将绘制在该位置,对应于每种情况下y刻度的最高期望值。因此,可以针对每个方面手动调整比例的高度。以下是相关数据集的解决方案。我们希望第一行的y比例(最大y值)为5,第二行为17。所以创建

df3=data.frame(newvar=rep("xx",8),period=c("A","B","C","D","E","F","G","H"),newvalue=c(5,5,5,5,17,17,17,17))

现在使用geom_point()将新数据叠加到我们的图表上。

ggplot(trial.facets.tidied,aes(x=newvar,y=newvalue,position="dodge"))+geom_bar(stat ="identity") +facet_wrap(~period,nrow=2,scales="free_y") +geom_point(data=df3,aes(x=newvar,y=newvalue),alpha=1)

我们得到的是:

barplot with fake points, fixing the scale

在这里,我故意画出这个额外的观点,以便清楚地表达出来。接下来我们需要使它不可见,这可以通过在最后一个命令中设置alpha=0而不是1来实现。

答案 2 :(得分:2)

此方法为每行绘制一条最大值的隐形线

#loading necessary libraries and example data
library(dplyr)
library(tidyr)
library(ggplot2)

trial.facets<-read.csv(text="period,xx,yy
                       A,2,3
                       B,1.5,2.5
                       C,3.2,0.5
                       D,2.5,1.5
                       E,11,13
                       F,16,14
                       G,8,5
                       H,5,4")

# define desired number of columns
n_col <- 4

#assign a row number - mmnsodulo number of colu
trial.facets$row <- seq(0, nrow(trial.facets)-1)  %/% n_col

# determine the max by row, and round up to nearest multiple of 5
# join back to original
trial.facets.max <- trial.facets %>% 
  group_by(row) %>% 
  summarize(maxvalue = (1 + max(xx, yy) %/% 5) * 5 )
trial.facets <- trial.facets %>% inner_join(trial.facets.max)

# make long format carrying period, row and maxvalue
trial.facets.tidied<-trial.facets %>% gather(key=newvar,value=newvalue,-period,-row,-maxvalue)

# plot an invisible line at the max
ggplot(trial.facets.tidied,aes(x=newvar,y=newvalue,position="dodge"))+
  geom_bar(stat ="identity") +
  geom_hline(aes(yintercept=maxvalue), alpha = 0) +
  facet_wrap(~period,ncol=n_col,scales="free")

enter image description here