Related
I have a dataframe like this:
library(tidyverse)
data <- tibble(Question_num = rep(c("Question_1", "Question_2"),each= 5),
Answer = rep(c('Strongly disagree',
'Disagree',
'Neutral',
'Agree',
'Strongly agree'), 2),
n = c(792, 79, 69, 46, 24, 34, 34, 111, 229, 602),
prop = c(78.4, 7.82, 6.83, 4.55, 2.38, 3.37, 3.37, 11.0, 22.7, 59.6))
where:
Question_num is the label of a question;
Answer is the response mode;
n is a simple count for each response mode;
prop is proportion, in percentage;
I would like to represent it graphically through a dynamic bar graph with divergent colours. Perhaps, this would be a starting point:
library(plotly)
library(RcolorBrewer)
data %>%
plot_ly(x = ~prop,
y = ~Question_num,
color = ~Answer) %>%
add_bars(colors = "RdYlBu") %>%
layout(barmode = "stack")
Is it possible, with Plotly in R, to obtain an ordered plot, which has the neutral category clearly delineated (in the center) and the percentages summarised by grouping the extreme categories together (even if they are in their plotted in different colours)? What I would like to obtain is a plot similar to this one:
The plot in the picture is obtained from a dataset in a different format (wide, not long) and with the likert package, which computes everything automatically. Could such a result be achieved with plotly (both for percentages and for counts)? If so, how?
I could not find any documentation to answer this challenging question.
Thank you very much to those who can help me.
The following isn't addressing all of the issues your post is raising (It might be better to split this into multiple questions).
However, I'd like to share what I was able to get so far.
(Sorry for switching from tidyverse to data.table - I'm not familar with the tidyverse and I'm not planning to familiarize any time soon).
To get the desired plot we can switch to barmode = 'relative'
Run schema() and navigate:
object ► traces ► bar ► layoutAttributes ► barmode
Determines how bars at the same location coordinate are displayed on
the graph. With stack, the bars are stacked on top of one another.
With
relative, the bars are stacked on top of one another, with negative values below the axis, positive values above
library(data.table)
library(plotly)
DF <- data.frame(Question_num = rep(c("Question_1", "Question_2"),each= 5),
Answer = rep(c('E - Strongly disagree',
'D - Disagree',
'A - Neutral',
'B - Agree',
'C - Strongly agree'), 2),
n = c(792, 79, 69, 46, 24, 34, 34, 111, 229, 602),
prop = c(78.4, 7.82, 6.83, 4.55, 2.38, 3.37, 3.37, 11.0, 22.7, 59.6))
DT <- as.data.table(DF)
DT[, order := .GRP, by = Answer]
DT[Answer == "A - Neutral", c("n", "prop") := .(n/2, prop/2)][Answer %in% c("E - Strongly disagree", "D - Disagree"), prop := -prop]
DT <- rbindlist(list(DT, DT[Answer == "A - Neutral", .(Question_num = Question_num, Answer = Answer, n = n, prop = -prop, order = order-0.5)]))
setorder(DT, -Question_num, order)
# setorder(DT, order)
fig <- plot_ly(
data = DT,
type = "bar",
x = ~ prop,
y = ~ Question_num,
color = ~ Answer,
colors = c("E - Strongly disagree" = "#a6611a",
"D - Disagree" = "#d2b08c",
"A - Neutral" = "#b3b3b3",
"B - Agree" = "#80c2b8",
"C - Strongly agree" = "#018571"),
text = ~ paste0(prop, "%"),
textfont = list(
size = 12,
color = 'black')
)
fig <- layout(
fig,
barmode = "relative",
xaxis = list(title ="Percentage"),
yaxis = list(
categoryorder = "array",
categoryarray = sort(unique(DT$Question_num), decreasing = TRUE),
title = ""
),
legend = list(orientation = "h")
)
print(fig)
Here a related question can be found.
I came across this website which show how to generate an interactive barplot using highchart. The frequency is called 'len' and I would like to know if there are len1, len2, len3 and len4, how do we include all len1–4 in highchart barplot?
I'm copying the R code they provide below:
# Load required R packages
library(highcharter)
# Set highcharter options
options(highcharter.theme = hc_theme_smpl(tooltip = list(valueDecimals = 2)))
df <- data.frame(dose=c("D0.5", "D1", "D2"),
len=c(4.2, 10, 29.5))
df2 <- data.frame(supp=rep(c("VC", "OJ"), each=3),
dose=rep(c("D0.5", "D1", "D2"),2),
len=c(6.8, 15, 33, 4.2, 10, 29.5))
hc <- df2 %>%
hchart('column', hcaes(x = 'dose', y = 'len', group = 'supp')) %>%
hc_colors(c("#0073C2FF", "#EFC000FF"))
hc
Can someone gives some guidance? I hand drawn the plot that I mean. Thanks.
Trying to make interactive plotly barchart with filter_select() and no-shiny work. I am working with data for a lot of airports (> 100). A barchart is typically too crowded to support the user to compare the performance observed (value VAL) at one airport (APT_x) to a subset of peers. The idea is to use a filter to have the user select the subset of airports.
# create a dummy table with data for year, airport, and oberved value
yr <- c(2017, 2018, 2019)
ap <- c("APT_1", "APT_2", "APT_3", "APT_N")
df <- expand.grid(YEAR = yr, APT = ap)
df$VAL <- c(10, 11, 12, 14, 9, 8, 7, 6, 2, 10, 12, 13)
library(plotly)
# shared data
df_sh <- highlight_key(df, key=~APT)
# filters
ap_filter <- filter_select(id="airport",label="filter airport", sharedData=df_sh, group=~APT)
# stacked bar chart
bc <- df_sh %>% plot_ly(x=~APT, y=~VAL, color=~factor(YEAR)) %>%
group_by(APT) %>%
add_bars() %>%
layout(barmode = "stack")
# arrange plot
bscols(widths = c(3, 9)
, ap_filter
, bc
)
Whenever more than one airport APT is selected, the x-axis shows all the entity-ticks between the bars.
How can this be removed/surpressed? Obviously, in the following example, APT_2 should not be shown. Thanks for any pointers.
I got an answer to the same issue here.
All that is needed is to set categoryorder = "trace" in the layout of the axis you are interested in.
In your example, it is (only difference is in the layout call of the bc definition):
library(crosstalk)
library(plotly)
# create a dummy table with data for year, airport, and oberved value
yr <- c(2017, 2018, 2019)
ap <- c("APT_1", "APT_2", "APT_3", "APT_N")
df <- expand.grid(YEAR = yr, APT = ap)
df$VAL <- c(10, 11, 12, 14, 9, 8, 7, 6, 2, 10, 12, 13)
# shared data
df_sh <- highlight_key(df, key = ~APT)
# filters
ap_filter <- filter_select(id = "airport", label = "filter airport", sharedData = df_sh, group = ~APT)
# stacked bar chart
bc <- df_sh %>% plot_ly(x = ~APT, y = ~VAL, color = ~factor(YEAR)) %>%
group_by(APT) %>%
add_bars() %>%
layout(barmode = "stack",
xaxis = list(categoryorder = "trace"))
# arrange plot
bscols(widths = c(3, 9), ap_filter, bc)
I am trying to plot a soil profile in R using the package aqp: algorithms for quantitative pedology. The profile should represent matrix colour, plus mottling colour and percentage. For that purpose, I am using the function addVolumeFraction, which works well to some extent: it plots points on the profile that correspond to the right mottling percentage for each horizon, but it doesn't assign the corresponding colours. Here an example:
#Variables for the soil profile
id <- rep(1, 4)
hor <- c("H1", "H2", "H3", "H4")
tops <- c(0,15,35,60)
bottoms <- c(15, 35, 60, 95)
mx_Hex <- c("#695F59FF", "#A59181FF", "#9E9388FF", "#A59181FF")
mot_Hex <- c("#EEB422","#EEB422", "#CD4F39", "#CD4F39")
mot_perc <- c(5, 10, 40, 8)
#Soil profile df
soildf <- data.frame(id,hor,tops,bottoms, mx_Hex, mot_Hex, mot_perc)
soildf$mx_Hex <- as.character(mx_Hex) #the class "SoilProfileCollection" needs colors as characters
soildf$mot_Hex <- as.character(mot_Hex)
# Transform df to "SoilProfileCollection"
depths(soildf) <- id ~ tops + bottoms
#Plot
plot(soildf, name = "hor", color = "mx_Hex", divide.hz = TRUE)
addVolumeFraction(soildf, "mot_perc",pch = 19, cex.min = 0.4, cex.max = 0.5, col = soildf$mot_Hex)
Soil profile plot
As you can see on the plot, the mottles' colours are mixed along the profile. I would like to have mottles of a given colour for their corresponding horizon instead. Can anybody help me to solve this problem?
Thanks!!
This works as expected in the current version of aqp available on CRAN (v1.19 released in January 2020).
I modified your example below to use alternating black and white mottles in each horizon.
library(aqp)
#Variables for the soil profile
id <- rep(1, 4)
hor <- c("H1", "H2", "H3", "H4")
tops <- c(0,15,35,60)
bottoms <- c(15, 35, 60, 95)
mx_Hex <- c("#695F59FF", "#A59181FF", "#9E9388FF", "#A59181FF")
# change mottle colors to something obviously different in each horizon
mot_Hex <- c("#FFFFFF", "#000000", "#FFFFFF","#000000")
mot_perc <- c(5, 10, 40, 8)
#Soil profile df
soildf <- data.frame(id, hor, tops, bottoms, mx_Hex, mot_Hex, mot_perc)
#the class "SoilProfileCollection" needs colors as characters
soildf$mx_Hex <- as.character(mx_Hex)
soildf$mot_Hex <- as.character(mot_Hex)
# Transform df to "SoilProfileCollection"
depths(soildf) <- id ~ tops + bottoms
#Plot
plot(soildf,
name = "hor",
color = "mx_Hex",
divide.hz = TRUE)
addVolumeFraction(
soildf,
"mot_perc",
pch = 19,
cex.min = 0.4,
cex.max = 0.5,
col = soildf$mot_Hex
)
alternating mottles
As the title says, a single ColorRamp palette when used in two different scetterplots built by plotly, gives two slightly differently looking (note the middle part) colorbars even though the upper and the lower bounds of corresponding data sets are manually set to be identical in both plots.
I'd like to make the plots visually comparable, and for that I'd obviously have to have identical colorbars. Is there a way to do that?
Here's the code:
myxaxis <- list(range = c(16, 44), dtick=2, gridwidth = 1, title = "Length of carbon chain") #setting the visible area of x axis
myyaxis <- list(range = c(0, 8), gridwidth = 1, title = "No. of double bonds") #setting the visible area of y axis
mycolors <- colorRampPalette(c('green', 'red', 'black'))(n = 100) #creating an RColorBrewer palette
ch_new1 <- cbind.data.frame(c('PA', 'PA', 'PA', 'PA', 'PA', 'PA', 'PA', 'PA', 'PA', 'upper bound', 'lower bound'), c(4.571087, 6.522441, 6.522441, 5.081869, 4.471815, 5.744834, 7.329796, 5.472866, 5.744834, 1, 1), c(10.52337, 16.75454, 16.0976, 16.47356, 18.94973, 17.46351, 10.97607, 18.11186, 11.64033, 0.2085327, 71.18021), c(32, 34, 34, 36, 36, 36, 38, 38, 38, 100, 100), c(1, 1, 2, 2, 3, 4, 4, 5, 6, 100, 100), c(0.4128963, 16.68394, 26.52718, 23.50851, 16.02339, 3.971546, 6.854153, 3.24342, 2.774968, 1, 1)) #the first dataset
colnames(ch_new1) <- c('Species', 'log_inversed_pval','fold_difference', 'N_of_carbons','N_of_double_bonds', 'rel_abund')
d <- plot_ly(ch_new1, x=~N_of_carbons, y=~N_of_double_bonds, text = ~paste('Percent of total', Species, '=', round(rel_abund, 0)), size=~rel_abund, color=~fold_difference, colors = mycolors)%>% #producing the scatter plot
layout(
xaxis = myxaxis,
yaxis = myyaxis,
title = paste('PA', '2b')
)%>%
colorbar(title="Fold difference", ypad=20)
export(d)
ch_new2 <- cbind.data.frame(c('LPC', 'LPC', 'LPC', 'lower limit', 'upper limit'), c(7.329796, 7.329796, 5.081869, 1, 1), c(2.952345, 5.042931, 3.700331, 0.2085327, 71.18021), c(18, 20, 22, 100, 100), c(0, 3, 5, 100, 100), c(82.87528, 13.56943, 3.555281, 1, 1)) #the second dataset
colnames(ch_new2) <- c('Species', 'log_inversed_pval','fold_difference', 'N_of_carbons','N_of_double_bonds', 'rel_abund')
d <- plot_ly(ch_new2, x=~N_of_carbons, y=~N_of_double_bonds, text = ~paste('Percent of total', Species, '=', round(rel_abund, 0)), size=~rel_abund, color=~fold_difference, colors = mycolors)%>% #creating the second scatterplot
layout(
xaxis = myxaxis,
yaxis = myyaxis,
title = paste(unique(ch$Species)[i], fraction)
)%>%
colorbar(title="Fold difference", ypad=20)
export(d)
chart #1 with bright red middle
chart #2 with dim red middle
I've solved the problem on my own.
Turns out that by adding one or several "anchoring" dummy points placed beyond the margins of the plot (so they are not shown) helps to make the plot colorbars almost identical.
The initial dataset
ch_new1 <- cbind.data.frame(c(...)) #the first dataset
should be appended with anchoring dummy points:
ch_new1 <- cbind.data.frame(c(...)) #the first dataset
ch_new1 <- rbind(ch_new, list('middle anchor point', 1, 50, 100, 100, 1))
ch_new1 <- rbind(ch_new, list('quarter anchor point', 1, 25, 100, 100, 1))
tl;dr anchor the variable responsible for colorbar to multiple reference points (10, 20, 30, 40, 50, ...)