Jessie
Jessie

Reputation: 313

R: Percentage stack bar chart in plotly

I have a dataset like below

City<-c("X","Y","Z","X","Z","X","Y")
House_Unit_Id<-c("H1","H2","H3","H4","H5","H6","H7")
Adult<-c(50,100,60,40,50,80,60)
Child<-c(40,0,40,20,50,20,30)
Baby<-c(10,0,0,40,0,0,10)
data<-data.frame(City,House_Unit_Id,Adult,Child,Baby)

 City House_Unit_Id Adult   Child   Baby
  X       H1         50      40     10
  Y       H2        100       0      0
  Z       H3         60      40      0
  X       H4         40      20     40
  Z       H5         50      50      0
  X       H6         80      20      0
  Y       H7         60      30     10 

I need a percentage column stack chart like below What I need

I tried the below code but the required output is not appearing as a percentage stack bar chart.

Chart <- plot_ly(data,x = ~City, y = ~Adult, type = 'bar',name= 'Adult') %>% 
  add_trace(y = ~Child, name = 'Child') %>% 
  add_trace(y = ~Baby, name = 'Baby') %>% 
  layout(yaxis = list(title = 'Percentage (%)'),barmode = "stack")

This is what I currently get What I currently get

I could not find any answers for this type of chart for plotly package in R. Can anyone please help me with this?

Upvotes: 3

Views: 16124

Answers (2)

Tbs
Tbs

Reputation: 136

The following code gives you the plot you describe, with the total number of type (Adult/Children/Baby) in each City in the hovertext (If you also want it on the plot itself you can try add_annotations)

  City<-c("X","Y","Z","X","Z","X","Y")
  House_Unit_Id<-c("H1","H2","H3","H4","H5","H6","H7")
  Adult<-c(50,100,60,40,50,80,60)
  Child<-c(40,0,40,20,50,20,30)
  Baby<-c(10,0,0,40,0,0,10)
  data<-data.frame(City,House_Unit_Id,Adult,Child,Baby)

  library(plyr)
  # Changing the data frame before plotting ... there is propably an easier way to do this!
  newdata <- ldply(3:5,function(n){tempdata <- data[,c(1,n)]
                               colnames(tempdata)[2] <- "Number"
                               tempdata$type <- colnames(data[n])
                               return(tempdata)})
  newdata <- ddply(newdata,.(City,type),summarize,Number=sum(Number))
  # Total for each city
  datatotal <- ddply(newdata,~City,summarize,n=sum(Number))
  # Merge the data frames together
  newdata <- merge(newdata,datatotal)
  # Calc the percentages
  newdata$perc <- newdata$Number/newdata$n

plot_ly(newdata,x = ~City, y = ~perc*100, type = 'bar',color = ~type,text=~Number,hoverinfo = 'text') %>% 
   layout(yaxis = list(title = 'Percentage (%)'),barmode = "stack") 

Upvotes: 4

acylam
acylam

Reputation: 18681

Since you want stacked percentage barplots across "City" not "House_Unit_Id", there are two things you can do. Either use the proportions you now have and create a combination of stacked and grouped barplot, where you are stacking by House_Unit_Id and grouping by City. Currently, I don't think the plotly package (correct me if I am wrong) is capable of doing this. You can use ggplot to do this.

However, if you really want to only compare percentages across City, you should aggregate the counts in Adult, Child and Baby with something like this:

newData = aggregate(. ~ City, data = data, FUN = sum)

Then calculate the proportions by City. After that, you can plot the percentages as stacked bars for each City.

Chart <- plot_ly(newData, x = ~City, y = ~Adult, type = 'bar', name= 'Adult') %>% 
  add_trace(y = ~Child, name = 'Child') %>% 
  add_trace(y = ~Baby, name = 'Baby') %>% 
  layout(yaxis = list(title = 'Percentage (%)'), barmode = "stack")

This will work if you aggregate your counts data by City and calculate the proportions for each City.

Upvotes: 1

Related Questions