I working with plotly in R. I am trying to plot charts with the same colors. Below you can see data and charts.
library(plotly)
library(reshape2)
library(dplyr)
df<-data.frame(city=c("NYC","Seattle","Boston","LA","Seattle"),
value=c(100,200,300,400,500))
df <-melt(df)
Now I am plotting pie chart with colors shown below:
fig<-df %>%
plot_ly(labels = ~city, values = ~value)
fig <- fig %>% add_pie(hole = 0.6)
fig
Finally, I want to plot a bar chart with the same colors as the pie plot, shown above. In order to do this, I tried this command lines :
df <-melt(df)
fig <- plot_ly(df, x = ~city, y = ~value, type = 'bar')
fig
So can anybody help me with how to plot a barplot with the same colors as pie chart ?
Here's a somewhat hacky but effective solution:
fig <- ggplot(df, aes(city, value, fill = city)) +
geom_col() +
scale_fill_manual(values = c("#2ca02c", "#ff7f0e",
"#d62728", "#1f77b4")) +
theme_minimal() +
theme(panel.grid.major.x = element_blank())
ggplotly(fig)
You may use ggplot2 package for both charts and it shall give matching colours to the city in each chart:
#install.packages('ggplot2')
library(ggplot2)
library(dplyr)
#your data frame
df<-data.frame(city=c("NYC","Seattle","Boston","LA","Seattle"),
value=c(100,200,300,400,500))
df <-melt(df)
PieChart <- df %>% ggplot(aes(x="", y=value, fill=city)) +
geom_bar(stat = "identity", width=1) +
coord_polar("y",start=0) +
theme_void()
PieChart
The resulted plot:
BarChart <- df %>% ggplot(aes(x=city, y=value, fill=city)) +
geom_bar(stat = "identity") +
theme_void() +
xlab("City") + ylab("Value")
BarChart
The resulted plot:
You may find this helpful.
In addition, here's what you can do if you want to completely use plotly.
#install.packages('RColorBrewer')
library(RColorBrewer)
library(dplyr)
library(plotly)
df<-data.frame(city=c("NYC","Seattle","Boston","LA","Seattle"),
value=c(100,200,300,400,500))
df <-melt(df)
df
#define a vector with colour palette of four colours
cols <- brewer.pal(12, "Set3")[1:4]
cols
Bar Chart:
BarChart <- df %>% plot_ly(x = ~city, y = ~value, showlegend = TRUE,
type = 'bar', color = ~city, colors = cols)
BarChart
The resulting plot:
Pie Chart:
PieChart <- df %>% plot_ly(labels = ~city, values = ~value,
marker = list(colors = cols), showlegend = TRUE) %>%
add_pie(hole = 0.6)
PieChart
The resulting plot:
Note that this would still give you different colours for the cities, so another suggestion that I have besides the linked answer above is to try creating a new data frame that has the unique four cities i.e no repetition, the summation of the values for the repeated cities, and bind another column that has a unique colour per city.
Related
class_day <- c(1:10)
control_group <- c(67,72,69,81,73,66,71,72,77,71)
A_treatment_group <- c(NA,72,77,81,73,85,69,73,74,77)
B_treatment_group <- c(NA,66,68,69,67,72,73,75,79,77)
class.df<-data.frame(class_day, control_group, A_treatment_group, B_treatment_group)
I tried to convert vecotrs to a table but I am not sure how to include three categories in one plot.
How can I get a scatter plot with three different colors?
I would like to set x-axis as class_day above and y axis as scores.
First, A cleaner way to make a dataframe without the intermediate variables.
You can make this type of chart by pivoting the data into "long" form:
class.df<-data.frame(class_day = c(1:10),
control_group = c(67,72,69,81,73,66,71,72,77,71),
A_treatment_group = c(NA,72,77,81,73,85,69,73,74,77),
B_treatment_group = c(NA,66,68,69,67,72,73,75,79,77) )
library(tidyverse)
class.df %>%
pivot_longer(!class_day) %>%
ggplot(aes(x=class_day, y=value, color=name))+
geom_point()
Here is a version with ggscatter from ggpubr:
library(ggpubr)
library(tidyverse)
class.df %>%
pivot_longer(-class_day,
names_to= "group",
values_to = "score") %>%
ggscatter(x = "class_day", y = "score", color = "group",
palette = c("#00AFBB", "#E7B800", "#FC4E07"))
I need to create a proportional bar chart from a data set created by using the melt function from dplyr. By proportional, I mean that I would need a chart for which the height of each bar would be different, based on the proportion of the total. I would like to proportion to be for the value X generated by the following sample code, with fill based on "group". I have tried many online solutions, and I constantly run into not an error code, but solid bars, with no difference in proportions
See sample code:
library(ggplot2)
library(tidyr)
set.seed(1)
example_matrix <-matrix(rpois(90,7), nrow=6,ncol=15)
example_df <- data.frame(example_matrix)
rownames(example_df) <-c('group1','group2','group3','group4','group5','group6')
df <- reshape2::melt(as.matrix(example_df))```
library(data.table)
library(ggplot2)
set.seed(1)
example_matrix <-matrix(rpois(90,7), nrow=6,ncol=15)
example_df <- data.frame(example_matrix)
rownames(example_df) <-c('group1','group2','group3','group4','group5','group6')
df <- reshape2::melt(as.matrix(example_df))
df$fraction <- df$value/sum(df$value)
setDT(df)
p <-
ggplot(data = df, aes(x = Var2, y = fraction, fill = Var1)) +
geom_bar(stat = "identity", position = "dodge") +
scale_fill_manual(values = c("blue", "red", "black", "orange", "pink", "yellow"))
print(p)
I don't think this can be done with the plotting commands directly, you'll need to transform your data before. For example:
library(dplyr)
df <- df %>% group_by(Var2) %>% mutate(fraction = value/sum(value))
and then plot either with the ggplot solution from the other answer or here's a plotly version:
library(plotly)
plot_ly(data = df, x = ~Var2, y = ~fraction, color = ~Var1, type = 'bar')
I have multiple graphs that I am plotting with ggplot and then sending to plotly. I set the legend order based the most recent date, so that one can easily interpret the graphs. Everything works great in generating the ggplot, but once I send it through ggplotly() the legend order reverts to the original factor level. I tried resetting the factors but this creates a new problem - the colors are different in each graph.
Here's the code:
Data:
Country <- c("CHN","IND","INS","PAK","USA")
a <- data.frame("Country" = Country,"Pop" = c(1400,1300,267,233,330),Year=rep(2020,5))
b <- data.frame("Country" = Country,"Pop" = c(1270,1000,215,152,280),Year=rep(2000,5))
c <- data.frame("Country" = Country,"Pop" = c(1100,815,175,107,250),Year=rep(1990,5))
Data <- bind_rows(a,b,c)
Legend Ordering Vector - This uses 2020 as the year to determine order.
Legend_Order <- Data %>%
filter(Year==max(Year)) %>%
arrange(desc(Pop)) %>%
select(Country) %>%
unlist() %>%
as.vector()
Then I create my plot and use Legend Order as breaks
Graph <- Data %>%
ggplot() +
geom_line(aes(x = Year, y = Pop, group = Country, color = Country), size = 1.2) +
scale_color_discrete(name = 'Country', breaks = Legend_Order)
Graph
But then when I pass this on to:
ggplotly(Graph)
For some reason plotly ignores the breaks argument and uses the original factor levels.
If I set the factor levels beforehand, the color schemes changes (since the factors are in a different order).
How can I keep the color scheme from graph to graph, but change the legend order when using plotly?
Simply recode your Conutry var as factor with the levels set according to Legend_Order. Try this:
library(plotly)
library(dplyr)
Country <- c("CHN","IND","INS","PAK","USA")
a <- data.frame("Country" = Country,"Pop" = c(1400,1300,267,233,330),Year=rep(2020,5))
b <- data.frame("Country" = Country,"Pop" = c(1270,1000,215,152,280),Year=rep(2000,5))
c <- data.frame("Country" = Country,"Pop" = c(1100,815,175,107,250),Year=rep(1990,5))
Data <- bind_rows(a,b,c)
Legend_Order <- Data %>%
filter(Year==max(Year)) %>%
arrange(desc(Pop)) %>%
select(Country) %>%
unlist() %>%
as.vector()
Data$Country <- factor(Data$Country, levels = Legend_Order)
Graph <- Data %>%
ggplot() +
geom_line(aes(x = Year, y = Pop, group = Country, color = Country), size = 1.2)
ggplotly(Graph)
To "lock in" the color assignment you can make use of a named color vector like so (for short I only show the ggplots):
# Fix the color assignments using a named color vector which can be assigned via scale_color_manual
cols <- scales::hue_pal()(5) # Default ggplot2 colors
cols <- setNames(cols, Legend_Order) # Set names according to legend order
# Plot with unordered Countries but "ordered" color assignment
Data %>%
ggplot() +
geom_line(aes(x = Year, y = Pop, color = Country), size = 1.2) +
scale_color_manual(values = cols)
# Plot with ordered factor
Data$Country <- factor(Data$Country, levels = Legend_Order)
Data %>%
ggplot() +
geom_line(aes(x = Year, y = Pop, color = Country), size = 1.2) +
scale_color_manual(values = cols)
I need to convert into widget a simple ggplot, a stacked bar with uncertainty.
The data:
world.tot <- data.frame('country'='world', 'GHG'=c('CH4', 'CO2','N2O'),
'emi'=c(6e+6, 3e+6, 1+6),
'unc.min'=8561406, 'unc.max'=14027350)
and the ggplot:
p2 <- ggplot(world.tot) +
geom_bar(aes(x=country,y=emi,fill=GHG), stat='identity', position='stack' ) +
geom_errorbar(aes(x=country, ymin=unc.min, ymax=unc.max), width=0.2) +
theme(axis.title. x=element_blank(), axis.title. y=element_blank()) +
theme(legend.position='none')
When I try: ggplotly(p2) only the stacked bars are converted, not the error bar. Any advice?
Alternatively, I could use plot_ly to create the plot, but cannot manage to add the error bar:
plot_ly(world.tot, x=~country. y=~emi, color=~GHG,type=bar,
error_y=~list(array(c(unc.min, unc.max))) %>%
layout(barmode='stack')
This produces error bars to all shares of the stacked histogram, while I need only one error at the top of the stacked histogram.
Any help is appreciated
You can prepare a data.frame that has only one error size per group
library(dplyr)
world.err <- world.tot %>%
group_by(country) %>%
summarise(emi = sum(emi), unc.min = 8561406, unc.max = 14027350)
And plot the errors as a separate trace
plot_ly(world.tot) %>%
add_bars(x = ~country, y = ~emi, color = ~GHG, type='bar') %>%
add_trace(x = ~country, y = ~emi, data = world.err,
showlegend = F, mode='none', type='scatter',
error_y = ~list(array = c(unc.min, unc.max), color = '#000000')) %>%
layout(barmode='stack')
In the minimal example below, where the color scale is log-transformed, the z value displayed when hovering the mouse above the raster is also log-transformed.
This is very uninformative and I need it to be expressed in the same unit as the scale legend.
Is it possible to avoid plotly to automaticaly do this conversion?
library(plotly)
library(reshape2)
library(RColorBrewer)
myPalette <- colorRampPalette(brewer.pal(11, "Spectral"))
p <- volcano %>%
melt() %>%
ggplot(aes(Var1, Var2, fill = value)) + geom_tile() +
scale_fill_gradientn(colours = rev(myPalette(100)), trans="log")
ggplotly(p)
A workaround is this, I just added the text = paste("Value:", value) part (which doesn't get affected by the log):
p <- volcano %>%
melt() %>%
ggplot(aes(Var1, Var2, fill = value, text = paste("Value:", value))) + geom_tile() +
scale_fill_gradientn(colours = rev(myPalette(100)), trans="log")
ggplotly(p, tooltip = c("Var1", "Var2", "text"))
Also tooltip to control what to show on hover.