2014-10-07 87 views
10

我试图在facet-wrapped图中使用reorder,该图也在ggplot2中使用scales = free_x,但重新排序函数没有正确地重新排序x轴。以下是我正在运行的是什么:R:使用ggplot2中的free_x对facet_wrapped x轴重新排序

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)) 

运行从this tab-separated file读取数据帧上的代码产生在每个方位图的x轴仅部分有序的图。 Someone else on SO问了一个非常类似的问题,但唯一建议的解决方案是使用网格排列。因为我的数据集比那个问题中的数据集大得多,但是这不会是一个非常快速的操作,所以我想问一下:有没有办法重新排列每个分面图的x轴的顺序,以增加(或减少)大小顺序显示条形?我非常感谢他人在这个问题上提供的任何帮助。

+1

哇...'opts'已经废弃了,因为2012年我认为这是你更新你的'ggplot2'包的时间。你的第一个带标题的'opts()'然后可以用'labs()'替换(你的'xlab'和'ylab'可以进去),你的第二个'opts'将被'theme() '。格雷戈尔谢谢, – Gregor 2014-10-07 14:48:56

+0

谢谢!任何关于重新排序问题的想法? – duhaime 2014-10-07 14:51:56

+1

如果你想在不同方面有不同的订单,我认为'grid.arrange'是你最好的选择。 – Gregor 2014-10-07 15:26:20

回答

6

问题是,ggplotV2视为单因子;它不是每个方面的子集V2(值为V1),然后将其中的每一个视为独立因素(不幸)。由于某些角色(“信使1”等)出现在多个角色中,因此这些级别根据角色在遇到的第一个角色中的重要性排序。

有一个解决方法,但它有点瑕疵:你需要通过将播放名称连接到每个角色来使角色唯一,然后使用它作为x值。要恢复原始角色,请关闭轴文本,并使用geom_text(...)作为条形标签。这里有一个例子:

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()) 

这看起来在这样一个小规模的可怕的(不是那么糟糕,因为你原来的情节,虽然...)。但是如果你把它做得更大(因为你需要做38次,没有??),那么你可以看到标签和酒吧。如果你真的想下面条的标签,使用这样的:

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()) 

再次,看起来可怕在这个规模不大,但更好的扩大。无论哪种方式,您可能需要调整geom_text(...)中的size=...参数。

+1

聪明的黑客!热情+1 – Gregor 2014-10-07 18:46:46

+0

你是一位学者,@ jlhoward!非常感谢这个聪明的解决方法:) – duhaime 2014-10-07 20:45:59

9

使用稍有不同的方法,可以将标签保留在图表下面的区域中。此版本通过以类似于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)) 

enter image description here

+0

这真是太棒了@WaltS!多么简单的修复!谢谢:) – duhaime 2014-10-08 02:08:43

+2

很高兴帮助你。我注意到我需要对角色函数进行一些小修改,以正确处理V1的所有值。上面编辑的版本有这个修复程序。对于那个很抱歉。 – WaltS 2014-10-08 14:56:32

+0

我希望我可以两次对这个游戏赞不绝口。这只是为我节省了几个小时挣扎的事情。 – 2017-01-22 18:47:42