且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

geom_bar():叠加和闪避结合

更新时间:2023-01-28 13:07:40

好的,几天前有一个很好的问题有点类似于你面对的根问题,所以我要建立在该问题的接受答案中使用的方法,因为它工作,我不知道有任何其他方式有堆栈编辑和闪避 d条C> GGPLOT2 。实质上,解决方案是手动移动感兴趣的 geom_bar 的数据。在上面引用的问题中,这是比较直接的一点,因为横轴是数字,因此您可以快速确定需要转移多少。在这种情况下,你的水平轴是类 Date ,但是不需要花费更多的精力为你的类别== Z找到合适的移位值数据的子集。首先构建一个阴谋对象,就像你上面做的那样(我会调用这个 s2 );除非你知道你的两个 geom_bar s是重叠的,所以你将不得不使用这个宽度 - 我使用 width = 5 $

  s2  mydata.m,
aes(x = variable,fill = category))+
geom_bar(
data = subset(mydata.m,%c(A,B)中的类别%),
aes(y = value),
stat =identity,
position =stack,
width = 5)+
geom_bar(data =
子集(mydata.m,category ==Z),
aes(y = -value),
stat =identity,
position =dodge,
width = 5)+
geom_line(
data = subset(mydata.m,category ==R),
aes(y = value),
linetype =solid ,
size = 1)+
geom_line(
data = subset(mydata.m,category ==S),
aes(y = value),
linetype =solid,
size = 1)
##
s2

来看看情节对象的水平位置,

 > ggplot_build(s2)$ panel $ ranges [[1]] $ x.major 
Jan 01 Jan 15 Feb 01 Feb 15 Mar 01 Mar 15 Apr 01
0.06937799 0.20334928 0.36602871 0.50000000 0.63397129 0.76794258 0.93062201
$ c>

我想你可以通过查看 s2 ,但是当你想计算特定的位置/坐标时,这会给你详细信息。无论采用哪种方式,只需对要转移的数据进行一些调整即可,例如 category == Z 。我为此创建了一个新对象, s3 ,其中我将数据移动了7(即7天,因为 variable 是一个 Date ):

  s3  mydata.m,
aes(x = variable,fill = category))+
geom_bar(
data = subset(mydata.m,category%in%c(A, B)),
aes(y = value),
stat =identity,
position =stack,
width = 5)+
geom_bar(
subset(mydata.m,category ==Z),
aes(y = value,x = variable + 7),
stat =identity,
$ =




aes(y =值),
linetype =solid,
size = 1)+
geom_line(
data = subset(mydata.m,category ==S),
aes(y = value),
linetype =solid,
size = 1)
s3
##



编辑:另外,我不太确定为什么你的行为 R S 显示为黑色,尽管我怀疑它与您为他们使用不同的 geom 这一事实有关。无论如何,你可以通过这样做来解决这个问题。

  s5  subset(mydata.m ,
!(%c(R,S))),
aes(x = variable,fill = category))+
geom_bar(
data = subset(mydata.m,%c(A,B)中的类别%),
aes(y = value),
stat =identity,
position =stack,
width = 5)+
geom_bar(data =
subset(mydata.m,category ==Z),
aes(y = value, x $变量+ 7),
stat =identity,
position =dodge,
width = 5)+
geom_line(
data = subset
mydata.m,
%c(R,S)),
aes(y = value,color = category),
linetype = b
geom_line(
data = subset(
mydata.m,
category%in%c(R,S,
size = 1) )),
aes(y = value,color = category),
linetype =solid,
size = 1)
s5


这仍然显示 R S (很可能是因为它们是因子类别的因子水平),但您至少可以得到另一个区分它们的传奇。


I seek advice on ggplot2::geom_bar().

My data contains the categories "A", "B", "Z". I want A, B as stacked bar, and Z as dodged bar next to the A, B bar.

# sample data
A = c(3, 4, 3, 5)
B = c(2, 2, 1, 4)
Z = c(1, 2, 1, 2)
R = c(-2, -1, -3, 0)
S = c(7,7,7,9)
mydata = data.frame(cbind(A,B,Z,R,S))
dates = c("2014-01-01","2014-02-01","2014-03-01","2014-04-01")
mydata$date = as.Date(dates)
mydata.m = melt(mydata,id="date")
names(mydata.m) = c("variable", "category","value")



s = ggplot(mydata.m, aes(x=variable, fill=category)) +        
# bars for cat A, B, Z
geom_bar(data=subset(mydata.m, category %in% c("A","B")), aes(y=value), stat="identity", position="stack") +
geom_bar(subset=.(category=="Z"), aes(y=-value), stat="identity", position="dodge") +

# lines for cat R, S
geom_line(subset=.(category=="R"), aes(y=value), linetype="solid", size=1) + 
geom_line(subset=.(category=="S"), aes(y=value), linetype="solid", size=1) ;

The above does not put Z bar next to AB bar, but overlaying the AB bar. Which problem is solved with aes(y=-value) or with facet_wrap to make separate plot for "Z". But I prefer it next to to AB bar, not below. Any suggestions? Thanks!

Side question: the fill legend has colors for R, S but in the plot the lines are just black, i don't see why?

Okay, so a couple of days ago there was a good question somewhat similar to the root issue you are facing, so I'm going to build off the method used in that question's accepted answer because it works and I'm not aware of any other way to have stacked and dodged bars in ggplot2. Essentially, the solution is to manually shift the data for the geom_bar of interest. This was a bit more straight forward in the cited question above because the horizontal axis was numeric, so you could quickly determine how much to shift by. In this situation your horizontal axis is of class Date, but it does not require much more effort to find an appropriate shift value for your category==Z subset of data. First build a plot object, like you did above (I'll call this s2); except you know your two geom_bars are overlapping, so you will have to play around with the width a bit - I used width = 5 after some trial and error:

s2 <- ggplot(
        mydata.m, 
        aes(x=variable, fill=category))+
      geom_bar(
        data=subset(mydata.m, category %in% c("A","B")), 
        aes(y=value), 
        stat="identity", 
        position="stack",
        width=5) +
     geom_bar(data = 
        subset(mydata.m, category=="Z"), 
        aes(y=-value), 
        stat="identity", 
        position="dodge",
        width=5)+ 
     geom_line(
        data = subset(mydata.m,category=="R"), 
        aes(y=value), 
        linetype="solid", 
        size=1) + 
     geom_line(
        data = subset(mydata.m,category=="S"), 
        aes(y=value), 
        linetype="solid", 
        size=1)
     ##
     s2

Then, we can look at the horizontal positions of the plot object by doing

> ggplot_build(s2)$panel$ranges[[1]]$x.major
    Jan 01     Jan 15     Feb 01     Feb 15     Mar 01     Mar 15     Apr 01 
0.06937799 0.20334928 0.36602871 0.50000000 0.63397129 0.76794258 0.93062201

I suppose you can eyeball this one by looking at the x-axis labels on the plot of s2, but incase you want to calculate specific positions / coordinates, this will give you the details. Either way, you just need to make some adjustments to the data you want to shift, in this case category == Z. I made a new object for this, s3, where I shifted the data by 7 (i.e. 7 days, since variable is a Date):

s3 <- ggplot(
  mydata.m, 
  aes(x=variable, fill=category))+
  geom_bar(
    data=subset(mydata.m, category %in% c("A","B")), 
    aes(y=value), 
    stat="identity", 
    position="stack",
    width=5) +
  geom_bar(
    subset(mydata.m, category=="Z"), 
    aes(y=value,x=variable+7), 
    stat="identity", 
    position="dodge",
    width=5)+ 
  geom_line(
    data = subset(mydata.m, category=="R"), 
    aes(y=value), 
    linetype="solid", 
    size=1) + 
  geom_line(
    data = subset(mydata.m, category=="S"), 
    aes(y=value), 
    linetype="solid", 
    size=1)
s3
##

EDIT: Also, I'm not quite sure why your lines for R and S were coming out black, although I suspect it had something to do with the fact that you are using a different geom for them. Anyways, you can sort of get around this by doing

s5 <- ggplot(
  subset(mydata.m,
         !(category %in% c("R","S"))), 
  aes(x=variable, fill=category))+
  geom_bar(
    data=subset(mydata.m, category %in% c("A","B")), 
    aes(y=value), 
    stat="identity", 
    position="stack",
    width=5) +
  geom_bar(data = 
    subset(mydata.m, category=="Z"), 
    aes(y=value,x=variable+7), 
    stat="identity", 
    position="dodge",
    width=5)+ 
  geom_line(
    data=subset(
      mydata.m,
      category %in% c("R","S")), 
    aes(y=value,color=category), 
    linetype="solid", 
    size=1) + 
  geom_line(
    data=subset(
      mydata.m,
      category %in% c("R","S")), 
    aes(y=value,color=category), 
    linetype="solid", 
    size=1)
s5

This still shows R and S in the original legend box (most likely because they are factor levels of your factor category), but you can at least get another legend distinguishing them.