Add values to rCharts hPlot tooltip - r

I would like to add some extra values to the standard Highcharts tooltip via rCharts. Example code:
require(rCharts)
df <- data.frame(x = c(1:5), y = c(5:1),
z = c("A", "B", "C", "D", "E"),
name = c("K", "L", "M", "N", "O"))
h1 <- hPlot(x = "x", y = "y", data = df, type = "scatter", group = "z")
This generates a tooltip with the x and y values. And the series name z as title. Now I also want the to add the name values to the tooltip. However I have no idea how this is done.

rCharts is a great package. But it still not well documented(Maybe I miss this point). I think you need to redefine new JS function for tooltip attribute.
Any JS literals need to be wrapped between #! and !# . Here a beginning but it doesn't work as I imagine ( I think is a good start):
h1$tooltip( formatter = "#! function() { return 'x: ' + this.point.x +
'y: ' + this.point.y +
'name: ' + this.point.group; } !#")

After several years, I have an answer.
It seems like these wrapper functions like hPlot() does not support additional tooltip variables even with a simple custom formatter function. See working example below based on the dataset from the question.
require(rCharts)
# create data frame
df <- data.frame(x = c(1:5), y = c(5:1),
z = c("A", "B", "C", "D", "E"),
name = c("K", "L", "M", "N", "O"))
# Plot using hPlot() approach
h1 <- hPlot(x = "x", y = "y", data = df, type = "scatter", group = "z")
h1$tooltip(borderWidth=0, followPointer=TRUE, followTouchMove=TRUE, shared = FALSE,
formatter = "#! function(){return 'X: ' + this.point.x + '<br>Y: ' + this.point.y + '<br>Z: ' + this.point.z + '<br>Name: ' + this.point.name;} !#")
h1
Tooltips do not work in the above example because the variables in the array are not named. See str(h1).
# Plot using manual build
h1 <- rCharts:::Highcharts$new()
dlev <- levels(factor(as.character(df$z)))
for(i in 1:length(dlev))
{
h1$series(data = toJSONArray2(df[df$z==dlev[i],,drop=F], json = F,names=T), name = dlev[i],type = c("scatter"), marker = list(radius = 3))
}
h1$tooltip(borderWidth=0, followPointer=TRUE, followTouchMove=TRUE, shared = FALSE,
formatter = "#! function(){return 'X: ' + this.point.x + '<br>Y: ' + this.point.y + '<br>Z: ' + this.point.z + '<br>Name: ' + this.point.name;} !#")
h1
This works because the array variables are named using names=T in the line starting h1$series.... See str(h1).
This sort of solves the tooltip issue, but there might be other problems with the named arrays. For example, it breaks things in a shiny-app environment. There must be a reason why hPlot() does not use the named arrays.

Related

R convert string into argument for a function

I am trying to make plots using a function in which arguments are values of dataframes.
seniorPlot <- function(validityDate, seniorTotal, color){
par(new = T)
plot(validityDate,seniorTotal,
type = "l",
lwd = 2.5,
xlim = c(date_debut$validityDate,date_fin$validityDate),
ylim = c(1,nmax$seniorTotal),
col = color,
xlab = "",
ylab = "",
xaxt = "n",
yaxt = "n",
bty = "n",
)
}
For the purpose, the threee arguments of the function are results several dataframes 'seniorList' and the seniors df named with the senior initials ('AM', 'FB', 'GM'…)
To describe, you can see the senior dataframes below:
seniorList <- data.frame(seniorValidation=c('AM', 'FB', 'GM'),seniorTotal=c(72, 154, 137))
AM <- data.frame(validationDate=c('2022-01-25', '2022-01-26'), color=c('brown','brown')
FB <- data.frame(validationDate=c('2022-01-20', '2022-01-30'), color=c('green','green')
GM <- data.frame(validationDate=c('2022-01-24', '2022-01-28'), color=c('blue','blue')
Obviously, there is more than 3 lines in the seniorList, so I want to do a loop, using the value of the first column of seniorList (ie. the senior name) to call the write dataframe.
And, here is the issue : how can I convert the result of noquote(paste(noquote(seniorList[i,1]),'$validityDate', sep = '')) to the result '2022-01-25' (if i = 1)
for (i in 1:nrow(seniorList)) {
seniorPlot(validityDate = noquote(paste(noquote(seniorList[i,1]),'$validityDate', sep = '')),
seniorTotal = noquote(paste(noquote(seniorList[i,1]),'$seniorTotal', sep = '')),
color = noquote(paste(noquote(seniorList[i,1]),'$color', sep = '')))
}
Thank you for your help, I hope my english is easy to understand.
noquote(paste(noquote(seniorList[i,1]),'$validityDate', sep = '')) give AM$validityDate and not its result
It's unclear what exactly the plot should look like but this shows how use "tidy" data easily with ggplot2.
DF <- rbind(cbind(AM, data.frame(seniorTotal = 72, seniorValidation = "AM")),
cbind(FB, data.frame(seniorTotal = 154, seniorValidation = "GB")),
cbind(GM, data.frame(seniorTotal = 137, seniorValidation = "GM")))
DF$validationDate <- as.Date(DF$validationDate)
#this is how your data should look like:
print(DF)
library(ggplot2)
ggplot(data = DF, aes(x = validationDate, y = seniorTotal, color = seniorValidation)) +
geom_line()

Create an R function that normalizes data based on input values

I don't make to many complicated functions and typically stick with very basic ones. I have a question, how do I create a function that takes a dataset and normalizes based on desired normalization method and boxplots the output? Currently norm_method is different between the norm methods, was wondering if there is a way to call this in the start of function to pull through the correct method? Below is the code I created, but am stuck how to proceed.
library(reshape2) # for melt
library(cowplot)
demoData;
# target_deoData will need to be changed at some point
TestFunc <- function(demoData) {
# Q3 norm (75th percentile)
target_demoData <- normalize(demoData ,
norm_method = "quant",
desiredQuantile = .75,
toElt = "q_norm")
# Background normalization without spike
target_demoData <- normalize(demoData ,
norm_method = "neg",
fromElt = "exprs",
toElt = "neg_norm")
boxplot(assayDataElement(demoData[,1:10], elt = "q_norm"),
col = "red", main = "Q3",
log = "y", names = 1:10, xlab = "Segment",
ylab = "Counts, Q3 Normalized")
boxplot(assayDataElement(demoData[,1:10], elt = "neg_norm"),
col = "blue", main = "Neg",
log = "y", names = 1:10, xlab = "Segment",
ylab = "Counts, Neg. Normalized")
}
You might want to consider designing your normalize() and assayDataElement() functions to take ..., which provides more flexibility.
In lieu of that, given the examples above, you could make a simple configuration list, and elements of that configuration are passed to your normalize() and assayDataElement() functions, like this:
TestFunc <- function(demoData, method=c("quant", "neg")) {
method = match.arg(method)
method_config = list(
"quant" = list("norm_args" = list("norm_method" = "quant", desired_quantile = 0.75, "toElt" = "q_norm"),
"plot_args" = list("col"="red", main="Q3", ylab = "Counts, Q3 Normalized")),
"neg" = list("norm_args" = list("fromElt" = "exprs", "toElt" = "neg_norm"),
"plot_args" = list("col"="blue", main="Neg", ylab = "Counts, Neg Normalized"))
)
mcn = method_config[[method]][["norm_args"]]
mcp = method_config[[method]][["plot_args"]]
# normalize the data
target_demoData = do.call(normalize, c(list(data = demoData[1:10]), mcn))
# get the plot
boxplot(assayDataElement(
demoData[1:10], elt=mcp[["toElt"]],col = mcp[["col"],main = mcp[["main"]],
log = "y", names = 1:10, xlab = "Segment",ylab = mcp[["ylab"]]
)
}
Again, using this approach is not as flexible as ... (and consider splitting into two functions.. one that returns normalized data, and a second function that generates the plot..

How to edit the labels of a facet_wrap/grid if there are two variables?

In ggplot I have faceted by two variables (tau and z) but can only change the label of the first:
df<-data.frame(x=runif(1e3),y=runif(1e3),tau=rep(c("A","aBc"),each=500),z=rep(c("DDD","EEE"),each=500))
tauNames <- c(
`A` = "10% load",
`aBc` = "40% load"
)
df%>%
ggplot(aes(x=x,y=y))+
geom_point(alpha=0.4)+
xlab(label = "Time[s]")+
ylab(label = "Dose")+
facet_grid(tau~z,labeller = as_labeller(tauNames))+
ggpubr::theme_pubclean()
As you can see I can change one of the labels but not both. Any thoughts are much appreciated
In the documentation of ?as_labeller you can find in the examples how you get the labels for multiple faceting variables.
library(tidyverse)
df<-data.frame(x=runif(1e3),y=runif(1e3),tau=rep(c("A","aBc"),each=500),z=rep(c("DDD","EEE"),each=500))
tauNames <- c(
`A` = "10% load",
`aBc` = "40% load"
)
df%>%
ggplot(aes(x=x,y=y))+
geom_point(alpha=0.4)+
xlab(label = "Time[s]")+
ylab(label = "Dose")+
facet_grid(tau~z,labeller = labeller(tau = tauNames,
z = c("DDD" = "D", "EEE" = "E")))+
ggpubr::theme_pubclean()

Plotting function gives data must be of vector type, was 'NULL'

So I use the following functions for plotting most of the data I have to plot. I created it thanks to different chunks of code that I have found online. So far I have never encountered any issue with it.
Here is the plotting function first.
library(ggplot2)
library(reshape2)
#' Plot a given mean with error bars
#' #param resultTable The table with all the result to plot
#' #param techniques The name of the techniques in the form of a list/vector
#' #param nbTechs The number of given techniques
#' #param ymin The minimum value for y
#' #param ymax The maximum value for y
#' #param xAxisLabel The label for the x (vertical) axis
#' #param yAxisLable The label for the y (horizontal) axis
#' #return
#'
barChartTime <- function(resultTable, techniques, nbTechs = -1, ymin, ymax, xAxisLabel = "I am the X axis", yAxisLabel = "I am the Y Label"){
#tr <- t(resultTable)
if(nbTechs <= 0){
stop('Please give a positive number of Techniques, nbTechs');
}
tr <- as.data.frame(resultTable)
nbTechs <- nbTechs - 1 ; # seq will generate nb+1
#now need to calculate one number for the width of the interval
tr$CI2 <- tr$upperBound_CI - tr$mean_time
tr$CI1 <- tr$mean_time - tr$lowerBound_CI
#add a technique column
tr$technique <- factor(seq.int(0, nbTechs, 1));
breaks <- c(as.character(tr$technique));
print(tr)
g <- ggplot(tr, aes(x=technique, y=mean_time)) +
geom_bar(stat="identity",fill = I("#CCCCCC")) +
geom_errorbar(aes(ymin=mean_time-CI1, ymax=mean_time+CI2),
width=0, # Width of the error bars
size = 1.1
) +
#labs(title="Overall time per technique") +
labs(x = xAxisLabel, y = yAxisLabel) +
scale_y_continuous(limits = c(ymin,ymax)) +
scale_x_discrete(name="",breaks,techniques)+
coord_flip() +
theme(panel.background = element_rect(fill = 'white', colour = 'white'),axis.title=element_text(size = rel(1.2), colour = "black"),axis.text=element_text(size = rel(1.2), colour = "black"),panel.grid.major = element_line(colour = "#DDDDDD"),panel.grid.major.y = element_blank(), panel.grid.minor.y = element_blank())+
geom_point(size=4, colour="black") # dots
print(g)
}
Now, here is (a simplified version of the data) data that I am using (and that reproduces the error):
EucliP,AngularP,EucliR,AngularR,EucliSp,AngularSp,EucliSl,AngularSl
31.6536,30.9863,64.394,92.7838,223.478,117.555,44.7374,25.4852
12.3592,40.7639,70.2508,176.55,10.3927,145.909,143.025,126.667
14.572,8.98445,113.599,150.551,47.1545,54.3019,10.7038,47.7004
41.7957,20.9542,55.1732,67.1647,52.364,41.3655,62.7036,75.65
135.868,83.7135,14.0262,69.7183,44.987,35.9599,19.5183,66.0365
33.5359,17.2129,6.95909,47.518,224.561,91.4999,67.1279,31.4079
25.7285,33.6705,17.4725,58.45,43.1709,113.847,28.9496,20.0574
48.4742,127.588,75.0804,89.1176,31.4494,27.9548,38.4563,126.248
31.9831,80.0161,19.9592,145.891,55.2789,142.738,94.5126,136.099
17.4044,52.3866,49.9976,150.891,104.936,77.2849,232.23,35.6963
153.359,151.897,41.8876,46.3893,79.5218,75.2011,68.9786,91.8972
And here is the code that I am using:
data = read.table("*Path_to_file*.csv", header=T, sep=",")
data$EucliPLog = (data$EucliP) #Before here I used to use a log transform that I tried to remove for some testing
data$EucliRLog = (data$EucliR) #Same thing
data$EucliSpLog = (data$EucliSp) #Same thing
data$EucliSlLog = (data$EucliSl) #Same thing
a1 = t.test(data$EucliPLog)$conf.int[1]
a2 = t.test(data$EucliPLog)$conf.int[2]
b1 = t.test(data$EucliRLog)$conf.int[1]
b2 = t.test(data$EucliRLog)$conf.int[2]
c1 = t.test(data$EucliSpLog)$conf.int[1]
c2 = t.test(data$EucliSpLog)$conf.int[2]
d1 = t.test(data$EucliSlLog)$conf.int[1]
d2 = t.test(data$EucliSlLog)$conf.int[2]
analysisData = c()
analysisData$ratio = c("Sl","Sp","R","P")
analysisData$pointEstimate = c(exp(mean(data$EucliSlLog)),exp(mean(data$EucliSpLog)),exp(mean(data$EucliRLog)),exp(mean(data$EucliPLog)))
analysisData$ci.max = c(exp(d2), exp(c2),exp(b2), exp(a2))
analysisData$ci.min = c(exp(d1), exp(c1),exp(b1), exp(a1))
datatoprint <- data.frame(factor(analysisData$ratio),analysisData$pointEstimate, analysisData$ci.max, analysisData$ci.min)
colnames(datatoprint) <- c("technique", "mean_time", "lowerBound_CI", "upperBound_CI ")
barChartTime(datatoprint,analysisData$ratio ,nbTechs = 4, ymin = 0, ymax = 90, "", "Title")
So If I do use the log() that I mention in the comments of the last piece of code, everything works fine and I get my plots displayed. However, I tried removing the log and I get the famous
Error in matrix(value, n, p) :
'data' must be of a vector type, was 'NULL'
I have tried looking for null values in my data but there are none and I do not know where to look at next. Would love to get some help with that.
Thanks in advance
Edit: Here is the result of dput on datatoprint:
structure(list(technique = structure(c(3L, 4L, 2L, 1L), .Label = c("P",
"R", "Sl", "Sp"), class = "factor"), mean_time = c(1.04016257618464e+32,
1.64430609815788e+36, 7.5457775364611e+20, 3.85267453902928e+21
), lowerBound_CI = c(6.64977706609883e+50, 5.00358136618364e+57,
2.03872433045407e+30, 4.93863589006376e+35), `upperBound_CI ` = c(16270292584857.9,
540361462434140, 279286207454.44, 30055062.6409769)), .Names = c("technique",
"mean_time", "lowerBound_CI", "upperBound_CI "), row.names = c(NA,
-4L), class = "data.frame")
And the dput on analysisData:
structure(list(ratio = c("Sl", "Sp", "R", "P"), pointEstimate = c(1.04016257618464e+32,
1.64430609815788e+36, 7.5457775364611e+20, 3.85267453902928e+21
), ci.max = c(6.64977706609883e+50, 5.00358136618364e+57, 2.03872433045407e+30,
4.93863589006376e+35), ci.min = c(16270292584857.9, 540361462434140,
279286207454.44, 30055062.6409769)), .Names = c("ratio", "pointEstimate",
"ci.max", "ci.min"))
Without the log I don't have anything on display because the value are above 10^40++ whereas with the log it's below the upper limit (90).
I don' get the error you get though.

rChart nPlot - update yAxis label

I am currently using nPlot from rCharts package and how do I add $ signs to the y Axis?
I am thinking I need something like n1$yAxis(labels = ...) but I don't think nPlot supports this?
test <- data.frame(object = c("A", "B"), price = c(111333, 876176))
test$Test <- "TEST"
n1 <- nPlot(price~Test, group = "object", data = test, type = "multiBarChart")
Also, it looks like nPlot is rounding to 5 significant figures (initially thought it was rounding to the nearest 10), is there a way of displaying the full value?
Thanks,
I am posting my comment as a full solution so that it is easier for others looking for it.
require(rCharts) # install the latest from the dev branch
test <- data.frame(object = c("A", "B"), price = c(111333, 876176))
test$Test <- "TEST"
n1 <- nPlot(price~Test, group = "object", data = test, type = "multiBarChart")
n1$yAxis(tickFormat = "#! function(d) {return '$' + d} !#")

Resources