I'd like to make a new geom geom_spine() : This geom is similar with geom_bar() but the barwidth varies depending on the count.
Here is what I tried.
require(ggplot2)
"%||%" <- function(a, b) {
if (!is.null(a)) a else b
}
geom_spine <- function(mapping = NULL, data = NULL,
stat = "count", position = "fill",
color="black",size=0.2,
...,
width = NULL,
binwidth = NULL,
na.rm = FALSE,
show.legend = NA,
inherit.aes = TRUE) {
layer(
data = data,
mapping = mapping,
stat = stat,
geom = GeomSpine,
position = position,
show.legend = show.legend,
inherit.aes = inherit.aes,
params = list(
width = width,
na.rm = na.rm,
color=color,
size=size,
...
)
)
}
colcount=function(data){
result=c()
myx=unique(data$x)
for(i in 1:length(myx)) result=c(result,sum(data[data$x==myx[i],"count"]))
result
}
GeomSpine <- ggproto("GeomSpine", GeomRect,
required_aes = c("x", "y"),
setup_data = function(data, params) {
data$width <- data$width %||%
params$width %||% (resolution(data$x, FALSE) * 0.9)
sumc<-c(0,colcount(data))
sumc<-cumsum(sumc)
total<-sum(data$y)/(length(unique(data$x))+1)
data1<-transform(data,
ymin = pmin(y, 0), ymax = pmax(y, 0),
xmin=sumc[x]+(sumc[x+1]-sumc[x])*(1- width)/2,xmax=sumc[x+1]-sumc[x+1]*(1-width)/2)
data<-transform(data1,
xmin=xmin/total,xmax=xmax/total,
x=(xmin+xmax)/(2*total), width=xmax-xmin
)
data
},
draw_panel = function(self, data, panel_scales, coord, width = NULL) {
ggproto_parent(GeomRect,self)$draw_panel(data, panel_scales, coord)
}
)
With this code, I am able to draw this plot. But I am not able to position the x labels in the middle of bar.
ggplot(data=mpg,aes(x=drv,fill=factor(cyl)))+geom_spine() +
scale_fill_brewer(palette="Blues")
How to change to continuous scale with this geom?