Highchart stacked columns - r

I have the following graph:
highchart() %>%
hc_title(text = "Composition") %>%
hc_subtitle(text = "Subtitle") %>%
hc_chart(type = "column", polar = F) %>%
hc_xAxis(categories = c("A", "B", "C", "D", "E")) %>%
hc_add_series(name = "Type A", data = c(5, 3, 4, 7, 2), stack = "A") %>%
hc_add_series(name = "Type B", data = c(5, 3, 4, 7, 2), stack = "A") %>%
hc_add_series(name = "Type C", data = c(5, 3, 4, 7, 2), stack = "A") %>%
hc_add_series(name = "Type D", data = c(5, 3, 4, 7, 2), stack = "A") %>%
hc_add_series(name = "Type E", data = c(5, 3, 4, 7, 2), stack = "A") %>%
hc_add_series(name = "Type A", data = c(2, 2, 3, 2, 1), stack = "B") %>%
hc_add_series(name = "Type B", data = c(2, 2, 3, 2, 1), stack = "B") %>%
hc_add_series(name = "Type C", data = c(2, 2, 3, 2, 1), stack = "B") %>%
hc_add_series(name = "Type D", data = c(2, 2, 3, 2, 1), stack = "B") %>%
hc_add_series(name = "Type E", data = c(2, 2, 3, 2, 1), stack = "B") %>%
hc_plotOptions(column = list(
dataLabels = list(enabled = FALSE),
stacking = "normal"))
The graph is creating different variables and also duplicating the legend for each stack = "A" and stack = "B". Then, we have Type A in the legend two times, Type B in the legend two times, etc. How can I stack different groups and have only one variable for each group?
I add a picture:
EDIT: I add some data
df <- structure(list(TYPE = c("TYPE_A", "TYPE_A", "TYPE_A", "TYPE_A",
"TYPE_A", "TYPE_A", "TYPE_A", "TYPE_A", "TYPE_A", "TYPE_A", "TYPE_A",
"TYPE_A", "TYPE_A", "TYPE_A", "TYPE_A", "TYPE_B", "TYPE_B", "TYPE_B",
"TYPE_B", "TYPE_B", "TYPE_B", "TYPE_B", "TYPE_B", "TYPE_B", "TYPE_B",
"TYPE_B", "TYPE_B", "TYPE_B", "TYPE_B", "TYPE_B"), SUB_TYPE = c("Sub_A",
"Sub_A", "Sub_A", "Sub_A", "Sub_A", "Sub_B", "Sub_B", "Sub_B",
"Sub_B", "Sub_B", "Sub_C", "Sub_C", "Sub_C", "Sub_C", "Sub_C",
"Sub_A", "Sub_A", "Sub_A", "Sub_A", "Sub_A", "Sub_B", "Sub_B",
"Sub_B", "Sub_B", "Sub_B", "Sub_C", "Sub_C", "Sub_C", "Sub_C",
"Sub_C"), PERIOD = c("curr", "t0", "t1", "t2", "t3", "curr",
"t0", "t1", "t2", "t3", "curr", "t0", "t1", "t2", "t3", "curr",
"t0", "t1", "t2", "t3", "curr", "t0", "t1", "t2", "t3", "curr",
"t0", "t1", "t2", "t3"), VALUE = c(296.6954, 352.8885, 360.5875,
375.2185, 389.8869, 1409.0355, 1470.8772, 1537.3365, 1590.0784,
1650.0942, 115.7838, 117.8871, 122.5989, 133.0147, 140.5065,
296.6954, 352.8885, 360.5875, 437.319, 382.3504, 1409.0355, 1470.8772,
1440.1987, 1289.093, 1244.0955, 115.7838, 117.8871, 169.3969,
113.2784, 98.1415)), .Names = c("TYPE", "SUB_TYPE", "PERIOD",
"VALUE"), row.names = c(NA, -30L), class = "data.frame")
TYPE are the categories in the X, SUB_TYPE are the stacked vales ina column, and the PERIOD are the columns in each category (TYPE).

When you add series "Type A" the second time, it is considered as a different series even though it has the same name. What we can do here is link the second to the first to attach it to the same legend entry (see API reference) and manually set the same color.
library(highcharter)
default_colors <- c("#7cb5ec", "#434348", "#90ed7d", "#f7a35c", "#8085e9",
"#f15c80", "#e4d354", "#2b908f", "#f45b5b", "#91e8e1")
highchart() %>%
hc_title(text = "Composition") %>%
hc_subtitle(text = "Subtitle") %>%
hc_chart(type = "column", polar = F) %>%
hc_xAxis(categories = c("A", "B", "C", "D", "E")) %>%
hc_add_series(name = "Type A", data = c(5, 3, 4, 7, 2), stack = "A",
id = "AA", color = default_colors[[1]]) %>%
hc_add_series(name = "Type B", data = c(5, 3, 4, 7, 2), stack = "A",
id = "BA", color = default_colors[[2]]) %>%
hc_add_series(name = "Type C", data = c(5, 3, 4, 7, 2), stack = "A",
id = "CA", color = default_colors[[3]]) %>%
hc_add_series(name = "Type D", data = c(5, 3, 4, 7, 2), stack = "A",
id = "DA", color = default_colors[[4]]) %>%
hc_add_series(name = "Type E", data = c(5, 3, 4, 7, 2), stack = "A",
id = "EA", color = default_colors[[5]]) %>%
hc_add_series(name = "Type A", data = c(2, 2, 3, 2, 1), stack = "B",
linkedTo = "AA", color = default_colors[[1]]) %>%
hc_add_series(name = "Type B", data = c(2, 2, 3, 2, 1), stack = "B",
linkedTo = "BA", color = default_colors[[2]]) %>%
hc_add_series(name = "Type C", data = c(2, 2, 3, 2, 1), stack = "B",
linkedTo = "CA", color = default_colors[[3]]) %>%
hc_add_series(name = "Type D", data = c(2, 2, 3, 2, 1), stack = "B",
linkedTo = "DA", color = default_colors[[4]]) %>%
hc_add_series(name = "Type E", data = c(2, 2, 3, 2, 1), stack = "B",
linkedTo = "EA", color = default_colors[[5]]) %>%
hc_plotOptions(column = list(
dataLabels = list(enabled = FALSE),
stacking = "normal"))
UPD
If the number of series/categories is not known beforehand, we can still create the plot by defining the list of series with all the options and passing this list to hc_add_series_list. The purrr package comes in handy when we want to tranform a data.frame into a complex list.
library(dplyr)
library(purrr)
x_cats <- unique(df$TYPE)
default_colors <- c("#7cb5ec", "#434348", "#90ed7d", "#f7a35c", "#8085e9",
"#f15c80", "#e4d354", "#2b908f", "#f45b5b", "#91e8e1")
colors_df <- tibble(SUB_TYPE = unique(df$SUB_TYPE)) %>%
mutate(color = default_colors[1:n()])
series <- df %>%
left_join(colors_df, by = "SUB_TYPE") %>%
group_by(SUB_TYPE, color, PERIOD) %>%
group_split() %>%
map(~list(
name = .$SUB_TYPE[[1]],
stack = .$PERIOD[[1]],
color = .$color[[1]],
data = .$VALUE,
id = paste(.$SUB_TYPE[[1]], .$PERIOD[[1]], sep = "-"),
linkedTo = paste(.$SUB_TYPE[[1]], "curr", sep = "-")
)) %>%
# remove links of curr to itself
modify_if(~ .$stack == "curr", ~.[-6])
highchart() %>%
hc_chart(type = "column") %>%
hc_plotOptions(column = list(
dataLabels = list(enabled = FALSE),
stacking = "normal")
) %>%
hc_xAxis(categories = unique(df$TYPE)) %>%
hc_add_series_list(series)

Related

Using dplyr to create a ICCs table

I am trying to create a table with ICCs for multiple raters and multiple variables, I am trying to use a function and dplyr, but it is not working as I expected.
This is the structure of the data frame and the expected ICCs table:
# Create data frame
ID <- c("r1", "r1", "r1", "r1", "r1", "r2", "r2", "r2", "r2", "r2", "r3", "r3", "r3", "r3", "r3")
V1.1 <- c(3, 3, 3, 3, 3, 3, 2, 3, 3, 1, 2, 2, 1, 1, 2)
V2.1 <- c(1, 1, 2, 1, 2, 1, 1, 1, 2, 1, 1, 2, 1, 1, 3)
V3.1 <- c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
V4.1 <- c(2, 2, 2, 1, 2, 2, 2, 2, 2, 1, 2, 2, 1, 1, 2)
V1.2 <- c(3, 3, 3, 3, 3, 3, 2, 3, 2, 2, 3, 2, 1, 2, 1)
V2.2 <- c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2)
V3.2 <- c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
V4.2 <- c(2, 4, 2, 1, 3, 2, 1, 3, 2, 2, 3, 2, 1, 2, 1)
df <- data.frame(ID, V1.1, V2.1, V3.1, V4.1, V1.2, V2.2, V3.2, V4.2)
# Empty data frame for ICCs
ids <- c("r1", "r2", "r3")
vars <- c("V1", "V2", "V3", "V4")
icc_table <- data.frame(ID = ids)
icc_table <- cbind(icc_table, matrix(NA, nrow = length(ids), ncol = length(vars)))
names(icc_table)[2:ncol(icc_table)] <- vars
Here is the attempt to create the ICCs table with a function and dplyr:
# ICC function
icc.fun <- function(data, x1, x2){
result <- irr::icc(subset(data, select = c(x1, x2)),
model = "twoway",
type = "agreement",
unit = "single")
result$value
}
# Table attempt
icc_table <- df %>%
pivot_longer(cols = -ID, names_to = c("criteria", ".value"), names_pattern = "(V\\d)\\.(\\d)") %>%
group_by(ID, criteria) %>%
rename("val1" = `1`, "val2" = `2`) %>%
summarise(icc = icc.fun(df, val1, val2), .groups = "drop") %>%
pivot_wider(id_cols = ID, names_from = criteria, values_from = icc)
However, it is not working and it returns a table with a lot of NAs. When I tried the function it seems to be working fine, so I guess it is a problem with the dplyr code. If you have any other solution apart from dplyr it is also welcomed!
Thanks!
I think the issue is between the subset() in your icc.fun and summarise(), try:
# ICC function
icc.fun <- function(x1, x2){
result <- irr::icc(data.frame(x1, x2)),
model = "twoway",
type = "agreement",
unit = "single")
result$value
}
# Table attempt
icc_table <- df %>%
pivot_longer(cols = -ID, names_to = c("criteria", ".value"), names_pattern = "(V\\d)\\.(\\d)") %>%
group_by(ID, criteria) %>%
rename("val1" = `1`, "val2" = `2`) %>%
summarise(icc = icc.fun(val1, val2), .groups = "drop") %>%
pivot_wider(id_cols = ID, names_from = criteria, values_from = icc)
In case it is useful for someone, here is the solution that I found:
I simplified the function by subsetting the data using R base
# ICC function
icc.fun <- function(data, x1, x2){
result <- icc(data[ ,c(x1, x2)],
model = "twoway",
type = "agreement",
unit = "single")
result$value
}
I used the group_modify() instead of summarise(), plus enframe()
# Create ICC table
icc_table <- df %>%
pivot_longer(cols = -ID, names_to = c("criteria", ".value"), names_pattern = "(V\\d)\\.(\\d)") %>%
group_by(ID, criteria) %>%
rename("val1" = `1`, "val2" = `2`) %>%
group_modify(~ {
icc.fun(.x, "val1", "val2") %>%
tibble::enframe(name = "variable", value = "icc")
}) %>%
pivot_wider(id_cols = ID, names_from = criteria, values_from = icc)

Why does plot_ly pie chart always turn 5th value text from white to black in R?

I'm making a pie chart using the plotly package in R, and whenever I have 5 choices to visualize, it always changes the 5th one to a brown/black color, despite me overriding the color to be white. In case it has something to do with the value being NA, how do I work around that? I have data that is labeled as NA, so I need to keep it named that. For what it's worth, I tried renaming to "NA ", but it still appeared the same.
Why is this happening and how do I fix it?
library(plotly)
library(dplyr)
data <- tibble(employee = c("Justin", "Corey","Sibley", "Justin", "Corey","Sibley", "Lisa", "NA"),
education = c("graudate", "student", "student", "graudate", "student", "student", "nurse", "doctor"),
fte_max_capacity = c(1, 2, 3, 1, 2, 3, 4, 5),
project = c("big", "medium", "small", "medium", "small", "small", "medium", "medium"),
aug_2021 = c(1, 1, 1, 1, 1, 1, 2, 5),
sep_2021 = c(1, 1, 1, 1, 1, 1, 2, 5),
oct_2021 = c(1, 1, 1, 1, 1, 1, 2, 5),
nov_2021 = c(1, 1, 1, 1, 1, 1, 2, 5))
data2 <- data %>%
dplyr::group_by(employee) %>%
mutate(sum = sum(rowSums(select(cur_data_all(), contains("_20"))))) %>%
dplyr::select(employee, sum) %>%
distinct()
my_colors <- c("#CA001B", "#1D28B0", "#D71DA4", "#00A3AD", "#FF8200", "#753BBD", "#00B5E2", "#008578", "#EB6FBD", "#FE5000", "#6CC24A", "#D9D9D6", "#AD0C27", "#950078")
fig <- plot_ly(type='pie', labels=data2$employee, values=data2$sum,
textinfo='label+percent', marker = list(colors = my_colors),
insidetextorientation='horizontal')
fig
t <- list(
family = "Arial",
size = 18,
color = 'white')
fig %>% layout(font=t, showlegend = FALSE)
Set color in insidetextfont -
library(plotly)
fig <- plot_ly(type='pie', labels=data2$employee, values=data2$sum,
textinfo='label+percent', insidetextfont = list(color = '#FFFFFF'),
marker = list(colors = my_colors),
insidetextorientation='horizontal')
fig

plot multiple datasets and compare categories with barplots

I have three datasets with the same variables and I want to compare one variables over 29 different categories between the three datasets. The example below should work as a reproducible example. I tried already to plot it but the out put was not as expected. I would like to have the three bars next to each other and a small plot in the plot for every category.
number_trackers = c(1, 2, 3, 4, 5, 6),
category = c("Ads", "Analytics", "Ads", "Analytics", "Ads", "Ads"),
c4 = c("url1.com","ur2.com","url3.com","url4.com","url5.com","url6.com"))
List_short_after=data.frame = c("Tracker1", "Tracker2", "Tracker3", "Tracker4","Tracker5","Tracker6"),
number_trackers = c(1, 2, 3, 4, 5, 6),
category = c("Ads", "Analytics", "Ads", "Analytics", "Ads", "Ads"),
c4 = c("url1.com","ur2.com","url3.com","url4.com","url5.com","url6.com"))
List_after=data.frame = c("Tracker1", "Tracker2", "Tracker3", "Tracker4","Tracker5","Tracker6"),
number_trackers = c(1, 2, 3, 4, 5, 6),
category = c("Ads", "Analytics", "Ads", "Analytics", "Ads", "Ads"),
c4 = c("url1.com","ur2.com","url3.com","url4.com","url5.com","url6.com"))
ggplot(data = NULL,
mapping = aes(y = number_trackers,x=category)) +
geom_col(data = List_before,fill= "#ca93ef", colour="#ca93ef") +
geom_col(data = List_short_after,fill= "#5034c4", colour="#5034c4") +
geom_col(data = List_after,fill= "#795fc6", colour="#795fc6") +
facet_wrap(facets = vars(category))+
theme_minimal() +
theme(text = element_text(color = "#795fc6",size=12,face="bold"),
axis.text = element_text(color = "#795fc6",size=14,face="bold"))+
labs( y = "Number Trackers", x = "Categories")
[![This is how the plot shut look like just with 3 bars instead of 2][1]][1]
[1]: https://i.stack.imgur.com/nDq36.png
Here's code that may help you reach your goal. Note that I took some liberties with your input data because it seems to be incomplete in your question.
library(ggplot2)
List_before <- data.frame(
list_id = "list_before",
name = c("Tracker1", "Tracker2", "Tracker3", "Tracker4","Tracker5","Tracker6"),
number_trackers = sample(c(1, 2, 3, 4, 5, 6)),
category = c("Ads", "Analytics", "Other 1", "Other 2", "Other 3", "Other 4"),
c4 = c("url1.com","ur2.com","url3.com","url4.com","url5.com","url6.com"))
List_short_after <- data.frame(
list_id = "list_short_after",
name = c("Tracker1", "Tracker2", "Tracker3", "Tracker4","Tracker5","Tracker6"),
number_trackers = sample(c(1, 2, 3, 4, 5, 6)),
category = c("Ads", "Analytics", "Other 1", "Other 2", "Other 3", "Other 4"),
c4 = c("url1.com","ur2.com","url3.com","url4.com","url5.com","url6.com"))
List_after <- data.frame(
list_id = "list_after",
name = c("Tracker1", "Tracker2", "Tracker3", "Tracker4","Tracker5","Tracker6"),
number_trackers = sample(c(1, 2, 3, 4, 5, 6)),
category = c("Ads", "Analytics", "Other 1", "Other 2", "Other 3", "Other 4"),
c4 = c("url1.com","ur2.com","url3.com","url4.com","url5.com","url6.com"))
df <- rbind(List_before, List_short_after, List_after)
df$list_id <- as.factor(df$list_id)
df$category <- as.factor(df$category)
ggplot(df, aes(y = number_trackers, x = list_id)) +
geom_bar(aes(fill = list_id), stat = "identity", position = position_dodge()) +
theme(axis.text.x = element_blank(),
axis.ticks.x = element_blank()) +
facet_grid(~category) +
labs(y = "Number of Trackers", x = NULL)

Plotly R: Hovertext for values which have 0 y-axis values

Problem: In plotly, is there a possibility to get the hoverinfo also for values which have zero y-value? So, in the example below, I want to have hovertext for xaxis value a, d and e.
Any suggestions?
library(data.table)
library(plotly)
dt <- data.table(
x = c("a", "b", "c", "d", "e"),
y = c(0 , 5, 2, 0, 0),
z = c(12, 14, 19, 23, 0)
)
plot_ly(dt,
x = ~x) %>%
add_bars(y = ~y,
text = ~paste("y-Values:", y, " z-Values:", z),
hoverinfo = "text")
I found the solution (add in layout hovermode = 'x'):
library(data.table)
library(plotly)
dt <- data.table(
x = c("a", "b", "c", "d", "e"),
y = c(0 , 5, 2, 0, 0),
z = c(12, 14, 19, 23, 0)
)
plot_ly(dt,
x = ~x) %>%
add_bars(y = ~y,
text = ~paste("y-Values:", y, " z-Values:", z),
hoverinfo = "text") %>%
layout(hovermode = 'x')

R Highcharter specify continuous x and y axis

I am a bit confused with use of highcharter hc_add_series function.
I am trying to create a plot where I need to specify both x and y axis, where x axis are continuous. I have a data-frame, for example:
df_plot <- cbind(
seq(0, 1, by = 0.1),
sample(seq(from = 100, to = 300, by = 10), size = 11, replace = TRUE),
sample(seq(from = 1, to = 100, by = 9), size = 11, replace = TRUE),
sample(seq(from = 50, to = 60, by = 2), size = 11, replace = TRUE),
sample(seq(from = 100, to = 130, by = 1), size = 1, replace = TRUE)
) %>%
as.data.frame()
names(df_plot) <- c("x", "a", "b", "c", "d")
I saw this example that works
highchart() %>%
hc_add_series(data = purrr::map(4:8, function(x) list(x, x)), color = "blue")
So i tried:
df_plot1 <- Map(cbind, split.default(df_plot[-1], names(df_plot)[-1]), x=df_plot[1])
highchart() %>%
hc_add_series(data = df_plot1[[1]]) %>%
hc_add_series(data = df_plot1[[2]], yAxis = 1) %>%
hc_yAxis_multiples(
list(lineWidth = 3, lineColor='#7cb5ec', title=list(text="First y-axis")),
list(lineWidth = 3, lineColor="#434348", title=list(text="Second y-axis")))
However, I am getting "No data to display" on the plot, so I obviously went wrong somewhere.
Also, I cannot use hchart function, as I need have multiple y axis
After reading docs about split.default it Divide into Groups and Reassemble, however you need to access the variable you want to plot, e.g. df_plot1[[1]$a, like so:
library(highcharter)
df_plot <- cbind(
seq(0, 1, by = 0.1),
sample(seq(from = 100, to = 300, by = 10), size = 11, replace = TRUE),
sample(seq(from = 1, to = 100, by = 9), size = 11, replace = TRUE),
sample(seq(from = 50, to = 60, by = 2), size = 11, replace = TRUE),
sample(seq(from = 100, to = 130, by = 1), size = 1, replace = TRUE)
) %>% as.data.frame()
names(df_plot) <- c("x", "a", "b", "c", "d")
df_plot1 <- Map(cbind, split.default(df_plot[-1], names(df_plot)[-1]), x=df_plot[1])
highchart() %>%
hc_xAxis(categories = df_plot1[[1]]$x) %>%
hc_add_series(data = df_plot1[[1]]$a) %>%
hc_add_series(data = df_plot1[[2]]$b, yAxis = 1) %>%
hc_yAxis_multiples(
list(lineWidth = 3, lineColor='#7cb5ec', title=list(text="First y-axis")),
list(lineWidth = 3, lineColor="#434348", title=list(text="Second y-axis")))
not sure if this can help you,
library(tidyr)
df_plot2 <- gather(df_plot, group, y, -x)
hchart(df_plot2, "line", hcaes(x, y, group = group))
hchart(df_plot2, "line", hcaes(x, y, group = group), yAxis = 0:3) %>%
hc_yAxis_multiples(
list(lineWidth = 3, title=list(text="First y-axis")),
list(lineWidth = 3, title=list(text="Second y-axis")),
list(lineWidth = 3, title=list(text="3rd y-axis")),
list(lineWidth = 3, title=list(text="4th y-axis"))
)

Resources