dynamical plot using plot_ly from R-plotly package - r

I am using shiny and plot_ly to plot a data frame.
The Goal: to implement a dynamical plot depending on the choice of users in GUI.
Consider the following data.table named pl.d
Group OS NP own.OS own.SCR HY9 WS8
A 34 54 27 76 56 82
B 15 45 0 84 89 48
C 0 36 7 92 91 22
in the server.R I used
plot_ly(pl.d, x = ~Group, y = ~OS, type = 'bar', name = "OS" ) %>%
layout(showlegend = TRUE)
The user should be able to expand the plot in the way that y could be an arbitrary choice of c(OS, NP, own.OS, own.SCR, HY9, WS8).
One not smart possible approach is to expand the plot_ly function with
if (input$choice of user =="NP"){
add_trace(y = ~NP, name = "NP")
}
and if conditionsand so on.
Is there any smart possibility to write an smart dynamical code to do that?
It has not to do with "NP". I mean plot_ly or add_trace should be in principle able to show one or many of c(OS, NP, own.OS, own.SCR,HY9,WS8).
I can write it as follows:
plot_ly(pl.d, x = ~Group, y = ~OS, type = 'bar', name = "OS" ) %>%
add_trace(y = ~NP, name = "NP") %>%
add_trace(y = ~own.OS, name = "own.OS") %>%
add_trace(y = ~own.SCR, name = "own.SCR") %>%
add_trace(y = ~HY9, name = "HY9") %>%
add_trace(y = ~WS8, name = "WS8")%>%
layout(showlegend = TRUE)
Problem: If you omit one of c(OS, NP, own.OS, own.SCR,HY9,WS8) you get an error!
One possible solution: to split the data frame into vectors! Using melt function makes it possible, however I do not get vectors just another shape of data table! Please take into account my outgoing point is pl.d and not data.frame(Group =c(...), ....)!
So, I tried the following
pl.d<-data.frame(Group =melt(setDT(d.plot), id.var = 'Group ')[,1],
model=melt(setDT(d.plot), id.var = 'Group ')[,2],
value=melt(setDT(d.plot), id.var = 'Group ')[,3])
and then,
plot_ly(pl.d, x = ~Group, y = ~value, type = 'bar', color= ~model ) %>%
add_trace(y = ~value, name = "NP")
However, I do not get for example the bars belonging to A close to each other.
Addendum: My mistake was, that I used color= ~model I had to use color=~Variable as mentioned in the answer! BUT why? I set it in my data frame asmodel`!!

Sounds like you are on the right track. You can use melt and filter to create a dataframe with the desired column names, like the following code.
data = data.frame(Group = c("a","b","c"),os = c(1,2,3),np = c(4,5,6), ws = c(7,8,9))
plot_cols = function(data, column_names = colnames(data)){
data%>%
melt()%>%
filter(variable %in% column_names) %>%
plot_ly(x = ~Group,y = ~value,color = ~variable,type = "bar")
}
You can plot all columns by calling plot_cols(data) or any select column like plot_cols(data,"os") or plot_cols(data,c("os","ws"))

Related

r plotly update button with line plot does not work with add_markers

I have a problem with the joined plot of an updatable line and static markers in R plotly. The line plot is updated via a drop down menu button, which works well on its own. The additional dots in the add_markers function are also correct when the plot is first initialized.
But after the first update, the markers are cut off (to the left side of the plot where the line starts) and remaining markers are modified (y values are different to initial ones).
For the example here the button function is simplified, but the result shows the same strange behavior.
`
sample_df <- tibble::tibble(quarter_date = rep(c("2022-06-30","2022-09-30","2022-12-31"),3),
forecast_value = runif(9,min = 10,max = 16),
forecast_date = c(rep("2022-07-23",3),rep("2022-08-26",3),rep("2022-09-15",3)))
marks = tibble::tibble(dates = c("2022-05-21","2022-06-15","2022-07-02","2022-07-26","2022-08-27"),
values = c(11,13,12,15,14))
create_buttons <- function(df, date_id) {
lapply(
date_id,
FUN = function(date_id,df) {
button <- list(
method = 'restyle',
args = list('y', list(df %>%
dplyr::filter(forecast_date == date_id) %>%
dplyr::pull(forecast_value))),
label = sprintf('Forecast # %s', date_id)
)
},
df
)
}
plotly::plot_ly(x = ~quarter_date) %>%
plotly::add_trace(data = sample_df %>%
dplyr::filter(forecast_date == max(forecast_date)),
#x = ~period_date,
y = ~forecast_value,
type = 'scatter',
mode = 'markers+lines',
name = 'forecasts') %>%
plotly::layout(
title = "Drop down menue",
yaxis = list(title = "y"),
updatemenus = list(
list(
y =1,
x = 0.9,
buttons = create_buttons(sample_df, unique(sample_df$forecast_date))
)
)) %>%
plotly::add_markers(data = marks,
x = ~dates,
y = ~values)
`
I have tried to set a wide xrange, used a second y2 axis and different approaches in the button calculation but nothing works as intended.
Does anyone have a clue why the add_markers is not working correctly after updating the line plot? Any ideas are highly appreciated!
Adding markers aren't the issue. The issue comes from the restyle. When you restyle the plot without designating that you only meant to change one trace, you changed all traces.
The solution is actually quite simple, you just need one more argument in your args call-- the trace number in a list: list(0) in this case. I've commented out your original args call, so you can see the change.
To make this repeatable, I added set.seed(46) before the creation of sample_df.
create_buttons <- function(df, date_id) {
lapply(
date_id,
FUN = function(date_id, df) {
button <- list(
method = 'restyle',
args = list('y', list(df %>% filter(forecast_date == date_id) %>%
pull(forecast_value)), list(0)),
# args = list('y', list(df %>%
# filter(forecast_date == date_id) %>%
# pull(forecast_value))),
label = sprintf('Forecast # %s', date_id)
)
},
df
)
}
Now when you run your plot, you will see that your marker data remains visible.

Is there a simple way to plot mutiples lines in R with plotly (Comparaison with plotly in python)

Hello everyone here is my issue:
In python, I can easily do a multiple-line plot from my raw data in one line using plotly:
import pandas as pd
import numpy as np
import plotly.express as px
#generating the data
I=np.linspace(0, 10, 100)
data={'0 min':np.cos(I)*0.5,
'10 min':np.cos(I)*1,
'20 min':np.cos(I)*2,
'30 min':np.cos(I)*4}
I=np.linspace(250, 349, 100)
df=pd.DataFrame(data,index=I)# df of my raw data
px.line(df, x=df.index, y=df.columns)
However, in R, with the same data :
library(plotly)
I<-seq(0, 10, length.out=100)
df = data.frame(t0min=cos(I)*0.5,
t10min=cos(I)*1,
t20min= cos(I)*2,
t30min=cos(I)*4)
I<-seq(250, 349, length.out=100)
rownames(df)<-I
this does not work:
plot_ly(df,
x = rownames(df),
y = colnames(df),
name = ~colnames(df),
type = 'scatter',
mode = 'lines')#does not work
The only solution that I found is to reshape my data frame entirely :
name=vector()
x=vector()
Y=vector()
for (i in colnames(df)){
name=c(name,rep(i,length(df[,i])) )
x=c(x, rownames(df[i]))
Y=c(Y, df[,i])
}
DF=data.frame(x, Y, name)
plot_ly(DF,
x = ~x,
y = ~Y,
color = ~name,
name = ~name,
type = 'scatter',
mode = 'lines')
Is there a simple solution to achieve the same result in R without reshaping the entire data frame?
AFAIK there isn't. But you could simplify the reshaping of your data considerably by using e.g. tidyr::pivot_longer. Also, instead of adding your I column as row names (which TBMK is different from the pandas concept of an index column) add it as a column to your dataset:
library(plotly)
I <- seq(0, 10, length.out = 100)
df <- data.frame(
t0min = cos(I) * 0.5,
t10min = cos(I) * 1,
t20min = cos(I) * 2,
t30min = cos(I) * 4
)
df$I <- I
df %>%
tidyr::pivot_longer(-I) %>%
plot_ly(
x = ~I,
y = ~value,
name = ~name,
type = "scatter",
mode = "lines"
)

geom_label() equivalent in {echarts4r}

Issue
I'm trying to produce a visualisation using {echarts4r} that involves plotting points with labels displayed on the chart itself, where the labels are unrelated to the position of the points. This sounds like it should be simple, but so far I haven't found any viable method of doing this and I'm beginning to wonder if it's even possible.
Desired output
Here is a minimal example. I will use {ggplot2} to demonstrate what I'd (roughly) like to reproduce:
data <- data.frame(
date_eaten = as.Date(c("2020-01-01", "2020-01-02", "2020-01-03")),
tastiness = c(5, 7, 10),
fruit = c("apple", "orange", "mango")
)
data
#> date_eaten tastiness fruit
#> 1 2020-01-01 5 apple
#> 2 2020-01-02 7 orange
#> 3 2020-01-03 10 mango
library(ggplot2)
ggplot(data, aes(x = date_eaten, y = tastiness, label = fruit)) +
geom_point() +
geom_text(nudge_y = 0.2)
Attempt using e_labels()
This method is visually exactly what I want, however, it seems that there is no option to specify which columns to take the labels from.
library(echarts4r)
data %>%
e_chart(date_eaten) %>%
e_scatter(tastiness, symbol_size = 10) %>%
e_labels()
Attempt using e_mark_point()
This option allows for more customisation, however this is not really a viable solution as it is very clunky and doesn't strictly 'link back' to the original data:
data %>%
e_chart(date_eaten) %>%
e_scatter(tastiness, symbol_size = 10) %>%
e_mark_point(data = list(
xAxis = as.Date("2020-01-01"),
yAxis = 5,
value = "apple"
)) %>%
e_mark_point(data = list(
xAxis = as.Date("2020-01-02"),
yAxis = 7,
value = "orange"
)) %>%
e_mark_point(data = list(
xAxis = as.Date("2020-01-03"),
yAxis = 10,
value = "mango"
))
I think this is the solution. Currently I'm not sure exactly how it works as documentation is a bit limited, but it seems to work:
data %>%
e_chart(date_eaten) %>%
e_scatter(tastiness, symbol_size = 10, bind = fruit) %>%
e_labels(formatter = htmlwidgets::JS("
function(params) {
return(params.name)
}
"))

How to plot multiple lines in radar chart using split in plotly

I have tried using split trace with scatterpolar and it seems to partly work but can't get it to plot the values for all 10 variables. So I want each row (identified by "ean") be plotted as its own line using the values from X1 to X10.
library(tidyverse)
library(vroom)
library(plotly)
types <- rep(times = 10, list(
col_integer(f = stats::runif,
min = 1,
max = 5)))
products = bind_cols(
tibble(ean = sample.int(1e9, 25)),
tibble(kategori = sample(c("kat1", "kat2", "kat3"), 25, replace = TRUE)),
gen_tbl(25, 10, col_types = types)
)
plot_ly(
products,
type = 'scatterpolar',
mode = "lines+markers",
r = ~X1,
theta = ~"X1",
split = ~ean
)
How can I get plotly to plot all variables in the radarchart (X1-X10)? Usually I would select the columns with X1:X10 but I can't do that here (I think it has to do with that ~ is used to select variable here).
So I want the result to look something like this (but I only show lines and not filled polygons and I would have more products). So in the end 25 products is a lot but I am connecting it so that the user can select the diagrams it wants to show.
In plotly it's convenient to use data in long format - see ?gather.
Please check the following:
library(dplyr)
library(tidyr)
library(vroom)
library(plotly)
types <- rep(times = 10, list(
col_integer(f = stats::runif,
min = 1,
max = 5)))
products = bind_cols(
tibble(ean = sample.int(1e9, 25)),
tibble(kategori = sample(c("kat1", "kat2", "kat3"), 25, replace = TRUE)),
gen_tbl(25, 10, col_types = types)
)
products_long <- gather(products, "key", "value", -ean, -kategori)
plot_ly(
products_long,
type = 'scatterpolar',
mode = "lines+markers",
r = ~value,
theta = ~key,
split = ~ean
)

Having trouble mapping highcharter aesthetics to reactive object elements

I have a large shiny app that allows users to filter through an API and spark table aggregate (dumped to an .Rdata) simultaneously using the same set of initially selectized parameters. Fitting all this into a reproducible example is going to be tough, but, this is the function that is grouping and summming my metric of interest (try to resist asking me to paste in partitionFiltered()):
df <- reactive({partitionFiltered() %>%
dplyr::group_by(updatedTimeHour, direction) %>%
dplyr::mutate(count_dir = sum(n_flows)) %>%
dplyr::ungroup() %>%
dplyr::select(updatedTimeHour, direction, count_dir) %>%
dplyr::arrange(updatedTimeHour) %>%
unique()})
(Eventually, updatedTimeHour and direction will be replaced by input$periodicity and input$dimension, respectively, but that is beyond the scope of this question.)
The df() object looks like:
updatedTimeHour direction count_dir
6 1 525071.00
6 2 3491.00
6 0 498816.00
6 3 5374.00
7 2 2432.00
7 0 303818.00
7 1 340768.00
7 3 4852.00
8 1 1969048.00
My highcharter calls do not seem to be grouping and coloring the aesthetics as I would expect:
hc <- highchart() %>%
hc_add_series(data = df()$count_dir,
type = input$plot_type,
name = factor(df()$direction)
showInLegend = TRUE,
# ??group = df()$direction,
# ??color = df()$direction,
# ??x = df()$updatedTimeHour, y = df()$count_dir, color = df()$direction,
# ??hcaes(x = df()$updatedTimeHour, y = df()$count_dir, color = df()$direction)
) %>%
hc_xAxis(type = 'datetime',
# ??group = factor(df()$direction),
categories = df()$updatedTimeHour,
tickmarkPlacement = "on",
opposite = FALSE) %>%
hc_title(text = "NetFlows, by Hour",
style = list(fontWeight = "bold")) %>%
hc_exporting(enabled = TRUE, filename = "threat_extract")
As you can probably tell, I'm very confused about where/how to map the x-grouping udpatedTimeHour, or color the different direction levels appropriately and make sure their group ends up mapped correctly to the labels in the legend and hover.
I have also attempted to map these aesthetics using the hcaes() call I see included as an argument to hc_add_series() in some of the documentation, but I get errors thrown saying that that argument is not (any longer?) named in that hc_ function...
Any help is appreciated, and a related question is here.
You are trying to add as one series multiple objects that's the reason why is not working. Just changing a little bit your code and using the "magic" function hchart it should work:
df = data_frame(updatedTimeHour = c(6,6,6,6,7,7,7,7,8), direction = c(1,2,0,3,2,0,1,3,1), count_dir = rnorm(9))
type = "line"
hchart(df, type, hcaes(x = updatedTimeHour, y = count_dir, group = as.factor(direction))) %>%
hc_title(text = "NetFlows, by Hour",
style = list(fontWeight = "bold")) %>%
hc_exporting(enabled = TRUE, filename = "threat_extract")

Resources