我想为每个ggplot2
构建一个堆积条形图(或箭头图),最好使用d
,下面的示例数据id
。
特点是,我希望堆栈首先遵循v0
列,z1
秒,z2
第三列(数据为宽格式)。但请注意,z2
有一些负值。所以它应该以某种方式用箭头或其他东西表示,从堆栈的顶部向下(或向上,取决于z3
的值)。
有办法做到这一点吗?
d <- data.frame(
id=c('AAA','BBB','CCC','DDD','EEE','FFF'),
v0 =c( 50 , 60 , 40 , 50 , 70 ,40),
z1 =c( 20 , 15 , 5 , 40 , 5 , 40),
z2 =c(-10 , 5 , 10 ,-20 , 15 ,-15)
)
#normaly people transform the data to long format:
d %>% gather(ef_type, value,v0:d2) %>%
ggplot(aes(...) + geom_bar(...)
OBS:请注意,这与this related question的答案不同,其中列的顺序无关紧要,负值表示在y轴的负部分。
EDIT1:根据@fanli回答,我试过以下代码:
d %>% select(id,v0,z1) %>% gather(ef_type, value,v0:z1) -> df
d %>% mutate(z2_start=v0+z1,z2_end=v0+z1+z2) %>% select(id,z2_start,z2_end) -> df2
ggplot(df, aes(x=id,y=value,fill=ef_type))+ geom_bar(stat = "identity") +
+ geom_segment(data=df2, aes(x=id, xend=id, y=z2_start, yend=z2_end), arrow = arrow(length = unit(0.02, "npc")))
#which results in the error:
Error: ggplot2 doesn't know how to deal with data of class uneval
答案 0 :(得分:4)
你在找这样的东西吗?
df <- melt(d)
df$absvalue <- abs(df$value)
df <- ddply(df, .(id), transform, pos =
ifelse(value<0, cumsum(absvalue)-(0.4 * absvalue),
cumsum(absvalue)-(0.6 * absvalue)))
df <- ddply(df, .(id), transform, pos2 =
ifelse(value>0, cumsum(absvalue)-(0.4 * absvalue),
cumsum(absvalue)-(0.6 * absvalue)))
ggplot(df, aes(x=id,y=absvalue,group=variable,fill=variable))
+ geom_bar(stat="identity", position="stack")
+ geom_segment(aes(x=id, xend=id, y=pos, yend=pos2), arrow = arrow(length = unit(0.02, "npc")))
您可以使用箭头的位置/数量/大小,但geom_segment
似乎是您喜欢的一种可能性。
编辑:根据所需输出的说明:
df&lt; - melt(d)
ggplot(subset(df, variable!="z2"), aes(x=id,y=value,group=variable,fill=variable))
+ geom_bar(stat="identity", position="stack") + geom_segment(data=d,
aes(x=id, xend=id, y=v0+z1, yend=v0+z1+z2), arrow = arrow(length = unit(0.02, "npc")), inherit.aes=F)
编辑2:使用scale_fill_manual
和scale_color_manual
自定义图例键:
d <- data.frame(
id=c('AAA','BBB','CCC','DDD','EEE','FFF'),
v0 =c( 50 , 60 , 40 , 50 , 70 ,40),
z1 =c( 20 , 15 , 5 , 40 , 5 , 40),
z2 =c(-10 , 5 , 10 ,-20 , 15 ,-15)
)
d$cc <- "effect B"
df <- melt(d)
ggplot(subset(df, variable!="z2"), aes(x=id,y=value,group=variable,fill=variable)) + geom_bar(stat="identity", position="stack") + geom_segment(data=d, aes(x=id, xend=id, y=v0+z1, yend=v0+z1+z2, color=cc), arrow = arrow(length = unit(0.02, "npc")), inherit.aes=F) + scale_color_manual(values="black") + scale_fill_manual(values=c("skyblue", "red"), labels=c("base level", "effect A"))