简体   繁体   English

R:在ggplot2中使用free_x重新排序facet_wrapped x轴

[英]R: Reorder facet_wrapped x-axis with free_x in ggplot2

I'm trying to use reorder in a facet-wrapped plot that also uses scales = free_x in ggplot2, but the reorder function isn't reordering the x-axis properly. 我正在尝试在小面包裹的绘图中使用reorder ,该绘图也在scales = free_x中使用scales = free_x free_x,但是重新排序功能没有正确地重新排序x轴。 Here's what I'm running: 这是我正在运行的:

library(ggplot2)

df <- read.table("speaking_distribution_by_play.txt",
                 header = F,
                 sep = "\t")

ggplot(df, aes(x=reorder(V2, V3), y=V3)) + 
  geom_bar(stat = "identity") +
  facet_wrap(~V1, ncol = 4, scales = "free_x") + 
  opts(title = "Distribution of Speakers in Shakespearean Drama") + 
  xlab("Speaking Role") + 
  ylab("Words Spoken") +
  opts(axis.text.x=theme_text(angle=90, hjust=1))

Running that code on the data frame read from this tab-separated file yields a plot in which the x-axis of each faceted plot is only partially ordered. 在从此制表符分隔文件中读取的数据框上运行该代码会生成一个图,其中每个分面图的x轴仅部分排序。 Someone else on SO asked a very similar question, but the only proposed solution was to use grid arrange. SO上的其他人提出了一个非常相似的问题,但唯一提出的解决方案是使用网格排列。 Because my data set is quite a bit larger than the data set in that question, though, this won't be a terribly swift operation, so I wanted to ask: Is there a way to reorder the x axis of each faceted plot so as to show the bars in increasing (or decreasing) order of size? 因为我的数据集比那个问题中的数据集要大得多,所以这不会是一个非常迅速的操作,所以我想问:有没有办法重新排序每个刻面图的x轴,以便显示尺寸增加(或减少)的条形? I would be very grateful for any help others can offer on this question. 我非常感谢其他人可以在这个问题上提供任何帮助。

With a slightly different approach, you can keep the labels in the area under the charts. 使用稍微不同的方法,您可以将标签保留在图表下方的区域中。 This version creates unique x breaks by concatenating V1 and V2 in a way similar to jlhoward's method but then restores V2 as the x labels using the function roles in the code below in the scale_x_discrete statement. 此版本通过以类似于jlhoward方法的方式连接V1和V2来创建唯一的x中断,但随后使用scale_x_discrete语句中下面的代码中的函数角色将V2恢复为x标签。

library(ggplot2)
df <- read.table("speaking_distribution_by_play.txt",
             header = F,
             sep = "\t")

# Creates a small test subset; remove for complete set 
df <- df[df$V1 %in% c("Mac.xml","MM.xml","MND.xml","MV.xml"),]

# used to create x-axis label restoring original name of role
roles <- function(x) sub("[^_]*_","",x )   

ggplot(cbind(df, V4=paste(df$V1,df$V2,sep="_")), aes(x=reorder(V4,V3), y=V3) ) + 
geom_bar(stat = "identity") +
facet_wrap(~ V1,  ncol=4, scales = "free_x") +
labs(title = "Distribution of Speakers in Shakespearean Drama") + 
xlab("Speaking Role") + 
ylab("Words Spoken") +
scale_x_discrete(labels=roles) +
theme(axis.text.x=element_text(angle=90, hjust=1)) 

在此输入图像描述

The problem is that ggplot treats V2 as a single factor ; 问题是ggplotV2视为单一因素 ; it does not subset V2 for each facet (value of V1 ) and then treat each of those as independent factors (unfortunately). 它没有为每个方面( V1值)子集V2 ,然后将每个方面视为独立因素(不幸的是)。 Since some of the roles ("Messenger 1", and so on), appear in more than one play, those levels are ordered based on their importance in the first play in which they are encountered. 由于某些角色(“Messenger 1”等)出现在多个游戏中,因此这些级别会根据它们在遇到它们的第一个游戏中的重要性进行排序。

There is a workaround, but it's a bit of a hack: you need to make the roles unique by concatenating the name of the play to each, then use that as the x-value. 有一种解决方法,但这有点像黑客攻击:你需要通过将播放的名称连接到每个角色来使角色唯一,然后将其用作x值。 To get the original roles back, turn off the axis text and instead use geom_text(...) for the bar labels. 要恢复原始角色,请关闭轴文本,而使用geom_text(...)作为条形标签。 Here is an example: 这是一个例子:

gg     <- df[order(df$V1,-df$V3),]   # reorder by play and lines
gg$lvl <- with(df,paste(V2,V1,sep="."))

ggplot(gg[gg$V1 %in% unique(df$V1)[1:4],], 
       aes(x=factor(lvl,levels=unique(lvl)), y=V3)) + 
  geom_text(aes(y=5,label=V2),angle=90,size=3,hjust=-0)+
  geom_bar(stat = "identity", fill="blue",alpha=0.2) +
  facet_wrap(~V1, ncol = 2, scales="free_x") + 
  labs(title="Distribution of Speakers in Shakespearean Drama", 
       x="Speaking Role", y="Words Spoken") +
  theme(axis.text.x=element_blank(),axis.ticks.x=element_blank())

This looks awful at such a small scale (not as bad as your original plot, though...). 这看起来很糟糕(虽然......不像原来的情节那么糟糕)。 But if you make it larger (as you will have to do with 38 plays, no??), then you can see the labels and the bars. 但是如果你把它做得更大(因为你将要做38场比赛,没有??),那么你可以看到标签和条形图。 If you really want the labels below the bars, use something like this: 如果你真的想要条形图下方的标签,请使用以下内容:

ggplot(gg[gg$V1 %in% unique(df$V1)[1:4],], 
       aes(x=factor(lvl,levels=unique(lvl)), y=V3)) + 
  geom_text(aes(y=-5,label=V2),angle=90,size=3,hjust=1)+
  ylim(-500,NA)+
  geom_bar(stat = "identity", fill="lightblue") +
  facet_wrap(~V1, ncol = 2, scales="free_x") + 
  labs(title="Distribution of Speakers in Shakespearean Drama", 
       x="Speaking Role", y="Words Spoken") +
  theme(axis.text.x=element_blank(),axis.ticks.x=element_blank())

Again, looks awful at this small scale, but better enlarged. 再次,这个小规模看起来很糟糕,但扩大得更好。 Either way you are likely to need to tweak the size=... parameter in geom_text(...) . 无论哪种方式,您都可能需要调整geom_text(...)size=...参数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM