Round stacks in R

I came across this amazing and relatively simple package that can be seen here , which can create beautiful normalized stacked line art in polar form like this . I hope to create a similar plot, but this does not normalize and may instead have initial values ​​as input.

On his blog, he points out that someone made an unnormalized version of their code that can create such graphics: enter image description here

This is almost what I need, but I can’t figure out how to add columns to create such a graph (sorry for the quality): enter image description here

Here are some toy data that is a subset of the real data that I will use and that follow its input format:

family item score value Group 1 Disease 1 Genetics 1 Group 1 Disease 1 EMR 8 Group 1 Disease 1 Pubmed 10 Group 1 Disease 2 Genetics 1 Group 1 Disease 2 EMR 21 Group 1 Disease 2 Pubmed 4 Group 1 Disease 3 Genetics 0 Group 1 Disease 3 EMR 2 Group 1 Disease 3 Pubmed 0 Group 2 Disease 4 Genetics 4 Group 2 Disease 4 EMR 72 Group 2 Disease 4 Pubmed 16 Group 3 Disease 5 Genetics 2 Group 3 Disease 5 EMR 19 Group 3 Disease 5 Pubmed 7 Group 3 Disease 6 Genetics 2 Group 3 Disease 6 EMR 12 Group 3 Disease 6 Pubmed 6 Group 4 Disease 7 Genetics 0 Group 4 Disease 7 EMR 11 Group 4 Disease 7 Pubmed 4 

A direct link to the package code that it openly provides can be found here .

Thanks a lot Ben

edit: Here is what I tried -

I entered the code and replaced:

 # histograms p<-ggplot(df)+geom_rect( aes( xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, fill=score) ) 

with:

 # histograms p<-ggplot(df)+ geom_bar(stat="identity", position="stack", aes(x=item, y=value,fill=score)) 

I did this because, as far as I was able to understand, there is no easy way to create a stacked bar using geom_rect, and when I try the above code with the polarBarChart script context, it will build graphs broken down by lines, but starting from the center generating instead to come from the entrance. Also, when I use this piece of code in a polarBarChart script, I get the following error:

 "Error: Discrete value supplied to continuous scale" 

and do not output

+6
source share
1 answer

To do this, you need to use geom_rect (). Modifying geom_bar () is not possible to do what you need, as polar geometry () creates a pink graph. Therefore, in order to have data plotted inward and not outward, geom_rect () is the only option (which I know of for ggplot2).

I will talk about the changes that I made first, show the graph, and then at the end I will turn on the entire function as changed.

I modified a block of code that computes xmin, xmax, ymin and ymax as follows:

xmin:

xmin <- (indexScore - 1) * (binSize + spaceBar) + (indexItem - 1) * (spaceItem + M * (binSize + spaceBar)) + (indexFamily - 1) * (spaceFamily - spaceItem)

xmin now:

xmin <- (binSize + spaceBar) + (indexItem - 1) * (spaceItem + (binSize + spaceBar)) + (indexFamily - 1) * (spaceFamily - spaceItem)

I deleted (indexScore-1) * and M * , because it is that the position of the bars for each point is next to each other. In each element, we want them to be in the same place x.

ymin:

ymin <- affine(1)

ymin now:

df<-df[with(df, order(family,item,value)), ] df<-ddply(df,.(item),mutate,ymin=c(1,ymax[1:(length(ymax)-1)]))

We want the ymin for each bar in each element to start with the ymax panel in front of it. To do this, I first ordered a data frame so that in each element the order of values ​​is from lowest to highest. Then for each element, I set ymin to 1 for the lowest value, and then to ymax of the previous bar for all other values.

I also made some ascetic changes. In the family shortcuts section, I changed y=1.2 to y=1.7 because your item labels are long, so the family labels were therefore on top of them. I also added hjust=0.5 to the center of them and vjust=0 so that they are not so close to the element labels. As a result, this line:

p<-p+ylim(0,outerRadius+0.2)

Now:

p<-p+ylim(0,outerRadius+0.7)

Thus, labels are placed in the chart area.

Finally, this line:

familyLabelsDF<-aggregate(xmin~family,data=df,FUN=function(s) mean(s+binSize))

Now:

familyLabelsDF<-aggregate(xmin~family,data=df,FUN=function(s) mean(s+binSize/2))

This makes the family labels centered in each group.

Here's what it looks like:

enter image description here

And here is the whole function (latest version see GitHub ):

 ## ============================================================================= ## Polar BarChart ## Original Polar Histogram by Christophe Ladroue ## Source: http://chrisladroue.com/2012/02/polar-histogram-pretty-and-useful/ ## Modified from original by Christos Hatzis 3.22.2012 (CH) ## Modified from modified by Christie Haskell 7.25.2014 (CHR) ## ============================================================================= polarBarChart <- function( df, binSize=1, spaceBar=0.05, spaceItem=0.2, spaceFamily=1.2, innerRadius=0.3, outerRadius=1, nguides=3, guides=pretty(range(c(0, df$value)), n=nguides, min.n=2), alphaStart=-0.3, circleProportion=0.8, direction="inwards", familyLabels=TRUE, itemSize=3, legLabels=NULL, legTitle="Source"){ require(ggplot2) require(plyr) # ordering df<-arrange(df,family,item,score) # family and item indices df$indexFamily <- as.integer(factor(df$family)) df$indexItem <- with(df, as.integer(factor(item, levels=item[!duplicated(item)]))) df$indexScore <- as.integer(factor(df$score)) df<-arrange(df,family,item,score) # define the bins vMax <- max(df$value) guides <- guides[guides < vMax] df$value <- df$value/vMax # linear projection affine<-switch(direction, 'inwards'= function(y) (outerRadius-innerRadius)*y+innerRadius, 'outwards'=function(y) (outerRadius-innerRadius)*(1-y)+innerRadius, stop(paste("Unknown direction"))) df<-within(df, { xmin <- (binSize + spaceBar) + (indexItem - 1) * (spaceItem + (binSize + spaceBar)) + (indexFamily - 1) * (spaceFamily - spaceItem) xmax <- xmin + binSize ymax <- affine(1 - value) } ) df<-df[with(df, order(family,item,value)), ] df<-ddply(df,.(item),mutate,ymin=c(1,ymax[1:(length(ymax)-1)])) # build the guides guidesDF<-data.frame( xmin=rep(df$xmin,length(guides)), y=rep(guides/vMax,1,each=nrow(df))) guidesDF<-within(guidesDF,{ xend<-xmin+binSize+spaceBar y<-affine(1-y) }) # Building the ggplot object totalLength<-tail(df$xmin+binSize+spaceBar+spaceFamily,1)/circleProportion-0 # histograms p<-ggplot(df)+geom_rect( aes( xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, fill=score) ) # guides p<-p+geom_segment( aes( x=xmin, xend=xend, y=y, yend=y), colour="white", data=guidesDF) # label for guides guideLabels<-data.frame( x=0, y=affine(1-guides/vMax), label=guides ) p<-p+geom_text( aes(x=x,y=y,label=label), data=guideLabels, angle=-alphaStart*180/pi, hjust=1, size=4) # item labels readableAngle<-function(x){ angle<-x*(-360/totalLength)-alphaStart*180/pi+90 angle+ifelse(sign(cos(angle*pi/180))+sign(sin(angle*pi/180))==-2,180,0) } readableJustification<-function(x){ angle<-x*(-360/totalLength)-alphaStart*180/pi+90 ifelse(sign(cos(angle*pi/180))+sign(sin(angle*pi/180))==-2,1,0) } dfItemLabels<-ddply(df,.(item),summarize,xmin=xmin[1]) dfItemLabels<-within(dfItemLabels,{ x <- xmin + (binSize + spaceBar)/2 angle <- readableAngle(xmin + (binSize + spaceBar)/2) hjust <- readableJustification(xmin + (binSize + spaceBar)/2) }) p<-p+geom_text( aes( x=x, label=item, angle=angle, hjust=hjust), y=1.02, size=itemSize, vjust=0.5, data=dfItemLabels) # family labels if(familyLabels){ # familyLabelsDF<-ddply(df,.(family),summarise,x=mean(xmin+binSize),angle=mean(xmin+binSize)*(-360/totalLength)-alphaStart*180/pi) familyLabelsDF<-aggregate(xmin~family,data=df,FUN=function(s) mean(s+binSize/2)) familyLabelsDF<-within(familyLabelsDF,{ x<-xmin angle<-xmin*(-360/totalLength)-alphaStart*180/pi }) p<-p+geom_text( aes( x=x, label=family, angle=angle), data=familyLabelsDF, hjust=0.5, vjust=0, y=1.7) } # empty background and remove guide lines, ticks and labels p<-p+opts( panel.background=theme_blank(), axis.title.x=theme_blank(), axis.title.y=theme_blank(), panel.grid.major=theme_blank(), panel.grid.minor=theme_blank(), axis.text.x=theme_blank(), axis.text.y=theme_blank(), axis.ticks=theme_blank() ) # x and y limits p<-p+xlim(0,tail(df$xmin+binSize+spaceFamily,1)/circleProportion) p<-p+ylim(0,outerRadius+0.7) # project to polar coordinates p<-p+coord_polar(start=alphaStart) # nice colour scale if(is.null(legLabels)) legLabels <- levels(df$score) names(legLabels) <- levels(df$score) p<-p+scale_fill_brewer(name=legTitle, palette='Set1',type='qual', labels=legLabels) p } 
+7
source

Source: https://habr.com/ru/post/972599/


All Articles