Reputation: 423
I want to make an interactive bar chart of one variable where the bars are filled in by a second variable and faceted by a third variable. I would like to embed it in a slidify deck. I am guessing rCharts is the right tool for this (or would another package be better?).
Here is my data:
df <- data.frame(numbers = rep(1:3, 30),
letter = sample(c("A", "B", "C", "D"), 90, replace = TRUE),
status = sample(c("good", "bad", "ugly"), 90, replace = TRUE))
I can do this in ggplot2, but I can't make it interactive. I can make this graph (sorry, can't embed):
ggplot(df, aes(letter, fill = status)) + geom_bar() + facet_wrap(.~numbers)
Ideally I would be able to select and deselect "status" and see the bars change. I've played with the bar chart code on this page but can't make it work. Is this functionality possible?
Upvotes: 1
Views: 223
Reputation: 1660
I was a heavy rCharts
user, but nowadays, in my opinion, plotly
is a better supported option (rCharts
is not in CRAN anymore).
Furthermoreplotly
has an automatic way to make ggplot2
charts interactive. For your example:
library(ggplot2)
library(plotly)
df <- data.frame(
numbers = rep(1:3, 30),
letter = sample(c("A", "B", "C", "D"), 90, replace = TRUE),
status = sample(c("good", "bad", "ugly"), 90, replace = TRUE)
)
p <-
ggplot(df, aes(letter, fill = status)) + geom_bar() + facet_wrap(. ~ numbers)
ggplotly(p)
EDIT 1
This edit is made to suit the needs of the comment.
The changes you requested cannot be made directly from ggplot2
so you need to use plotly
. There may be a more elegant way to do the chart than my for loops but they seem to work:
library(data.table)
library(ggplot2)
library(plotly)
# make data.table
df <- data.table(
numbers = rep(1:3, 30),
letter = sample(c("A", "B", "C", "D"), 90, replace = TRUE),
status = sample(c("good", "bad", "ugly"), 90, replace = TRUE)
)
# keep unique status values for bars and numbers for facets
traces <- df[,unique(status)]
facets <- df[,unique(numbers)]
# cast df
casted_df <- dcast(df,letter + numbers ~ status )
# initialise list to keep charts
facetplots <- list()
for(i in 1:length(facets)){
# initialise chart
facetplots[[i]] <- plot_ly(type = "bar")
facet_df <- casted_df[numbers == facets[i]]
for(j in traces){
if(i == 1){
facetplots[[i]] <- add_trace(facetplots[[i]], x = facet_df[,letter], y = facet_df[,get(j)],legendgroup = j , color = j, name = j )
}else{
facetplots[[i]] <- add_trace(facetplots[[i]], x = facet_df[,letter], y = facet_df[,get(j)],legendgroup = j, color = j , name = j , showlegend = F)
}
}
facetplots[[i]] <- layout( facetplots[[i]], barmode = "stack")
}
q <- subplot(facetplots, shareX = TRUE)
q
Upvotes: 0
Reputation: 922
Maybe this is what you're after in ggplot? I couldn't tell if you wanted a ggplots solution or rCharts solution. So this is ggplot.
Add position = "dodge" to your geom_bar argument will mimic the other graph you linked to
ggplot(df, aes(letter, fill = status)) +
geom_bar(position = "dodge") +
facet_wrap(.~numbers)
Alternatively, you could "unselect" status, and fill by number -- note, had to make this a factor in this example:
ggplot(df, aes(letter, fill = as.factor(numbers))) +
geom_bar(position = "dodge") +
facet_wrap(.~numbers)
Or omit and keep grayscale
ggplot(df, aes(letter)) +
geom_bar(position = "dodge") +
facet_wrap(.~numbers)
Upvotes: 0