Why does the order of my tooltips change when using ggplotly? - r

When I add my own text into the tooltips for ggplotly the order of the text changes. In my example the order is Portuegese then German in my text, however on the plot the order is different.
How do I fix this?
Thanks
library(ggplot2);
library(plotly);
language <- c("de","es","hi","pt","sv","en")
averageRating <- c(6,4,3,9,10,30)
my_data <- data.frame(language, averageRating)
text <- c("Portuegese","German","Spanish","Hindi","Swedish","English")
p <- ggplot(data=my_data, aes(x=language, y=averageRating, text = text)) +
geom_bar(stat = "identity")
ggplotly(p, tooltip = c("text"))

Maybe you should try factor within aes when applying ggplot, e.g.,
ggplot(data = my_data, aes(x = factor(language, levels = language), y = averageRating, text = text))

To fix this I added a new column in my dataframe with the name I wanted displayed in the tooltip. I then set the "text" inside the aesthetic to that column name.
library(ggplot2);
library(plotly);
my_data <- read.csv("languageVsRating.csv")
p <- ggplot(data=my_data, aes(x=reorder(language,-averageRating), y=averageRating, text = fullName)) +
geom_bar(stat = "identity") +
labs(x="Film Language",y="Average Rating")+
geom_hline(aes(yintercept = 6.9,linetype="Mean"),colour='red',size=1)+
geom_hline(aes(yintercept = 6.7,linetype="Median"),colour='blue',size=1)+
scale_linetype_manual(name = "",values = c(2,2),guide = guide_legend(override.aes = list(color = c("red", "blue"))))
ggplotly(p, tooltip = c("text","y"))
There is another column inside languageVsRating.csv with the language full name

Related

R: How to customize plotly interactive hover window?

Here I have interactive barplot given by ggplotly. The only issue is that when I move mouse around bars, in the "model" category there is strange number instead of A or B (see the picture). Is it possible to customize plotly popup windows?
df <- data.frame (model = c("A", "A","B","B"),
year = c("2022","2021","2022","2021"),
sale = c(350,170,300,150),
change = c(180,NA,150,NA),
percent = c(105.8,NA,100,NA),
info = c("180, 105.8%",NA,"300,100%",NA)
)
#ggplot
plot <- ggplot(df, aes(fill=year, y=model, x=sale)) +
geom_bar(position="dodge", stat="identity") + geom_text(aes(label=info, x=1.11*max(sale),), fontface='bold')+ xlim(0, 1.2*max(df$sale)) +
theme(legend.position="bottom")+labs(fill = " ")+
scale_fill_brewer(palette = "Paired")
ggplotly(plot)
Personally, i avoid using ggplotly() as it more often than not formats the visuals in a way that i do not want.
A full plotly approach could look like this:
plot_ly(
data = df,
x = ~sale,
y = ~model,
color = ~year,
text = ~year,
type = "bar") %>%
add_trace(
x = ~max(df$sale) * 1.1,
y = ~model,
type = 'scatter',
mode = 'text',
text = ~info,
showlegend = FALSE
) %>%
style(hovertemplate = paste("Sale: %{x}",
"Model: %{y}",
"Year: %{text}",
sep = "<br>"))
You could also try to append the style() object to your ggplotly() object. I am not sure if this will work however.
For some reason, it works better if you use x=model and flip the axes:
plot <- ggplot(df, aes(fill=year, x=model, y=sale)) +
geom_bar(position="dodge", stat="identity") + geom_text(aes(label=info,y=1.11*max(sale),), fontface='bold')+
ylim(0, 1.2*max(df$sale)) +
theme(legend.position="bottom")+labs(fill = " ")+
scale_fill_brewer(palette = "Paired")+
coord_flip()
ggplotly(plot)

Box plot with multiple groups + Dots + Counts

I have a boxplot with multiple groups in R.
When i add the dots within the boxplots, they are not in the center.
Since each week has a different number of boxplots, the dots are not centered within the box.
The problem is in the geom_point part.
I uploaded my data of df.m in a text file and a figure of what i get.
I am using ggplot, and here is my code:
setwd("/home/usuario")
dput("df.m")
df.m = read.table("df.m.txt")
df.m$variable <- as.factor(df.m$variable)
give.n = function(elita){
return(c(y = median(elita)*-0.1, label = length(elita)))
}
p = ggplot(data = df.m, aes(x=variable, y=value))
p = p + geom_boxplot(aes(fill = Label))
p = p + geom_point(aes(fill = Label), shape = 21,
position = position_jitterdodge(jitter.width = 0))
p = p + stat_summary(fun.data = give.n, geom = "text", fun.y = median)
p
Here is my data in a text file:
https://drive.google.com/file/d/1kpMx7Ao01bAol5eUC6BZUiulLBKV_rtH/view?usp=sharing
Only in variable 12 is in the center, because there are 3 groups (the maximum of possibilities!
I would also like to show the counting of observations. If I use the code shown, I can only get the number of observations for all the groups. I would like to add the counting for EACH GROUP.
Thank you in advance
enter image description here
Here's a solution using boxplot and dotplot and an example dataset:
library(tidyverse)
# example data
dt <- data.frame(week = c(1,1,1,1,1,1,1,1,1,
2,2,2,2,2,2,2,2,2),
value = c(6.40,6.75,6.11,6.33,5.50,5.40,5.83,4.57,5.80,
6.00,6.11,6.40,7.00,3,5.44,6.00,5,6.00),
donor_type = c("A","A","A","A","CB","CB","CB","CB","CB",
"CB","CB","CB","CB","CB","A","A","A","A"))
# create the plot
ggplot(dt, aes(x = factor(week), y = value, fill = donor_type)) +
geom_boxplot() +
geom_dotplot(binaxis='y', stackdir='center', position = position_dodge(0.75))
You should be able to adjust my code to your real dataset easily.
Edited answer with OP's dataset:
Using some generated data and geom_point():
library(tidyverse)
df.m <- df.m %>%
mutate(variable = as.factor(variable)) %>%
filter(!is.na(value))
ggplot(df.m, aes(x = variable, y = value, fill = Label)) +
geom_boxplot() +
geom_point(shape = 21, position = position_jitterdodge(jitter.width = 0)) +
scale_x_discrete("variable", drop = FALSE)

How do I include strikethrough text in geom_text_repel or geom_text labels for ggplot?

Is it possible to add strikethrough to some geom_text/geom_text_repel labels?
This question mentioned that you can italicise a label using the following:
library("ggplot2")
library("ggrepel")
df <- data.frame(
x = c(1,2),
y = c(2,4),
lab = c("italic('Italic Text')", "Normal"))
ggplot(df, aes(x, y, label = lab)) +
geom_point() +
geom_text_repel(parse = T)
However, I've been unable to use the same method to get strikethrough text.
df$lab = c("strike('Strikethrough Text')", "Normal")
ggplot(df, aes(x, y, label = lab)) +
geom_point() +
geom_text_repel(parse = T)
What about using a Unicode long strike overlay?
R Script
# Long strikethru test
# Unicode Character 'COMBINING LONG STROKE OVERLAY' (U+0336)
library("tidyverse")
# Keep 30 first rows in the mtcars natively available dataset
data <- head(mtcars, 30)
name <- "Strikethrough"
name_strk <- str_replace_all(name, "(?<=.)", "\u0336")
# Add one annotation
ggplot(data, aes(x=wt, y=mpg)) +
geom_point() + # Show dots
geom_label(
label= name_strk,
x=4.1,
y=20,
label.padding = unit(0.55, "lines"), # Rectangle size around label
label.size = 0.35,
color = "black",
size = 4,
fill="white"
)
As was mentioned in the comments, plotmath cannot handle strikethrough. However, we can do some tricks with phantom and underline.
library(tidyverse)
df <- data.frame(
y = c(1, 2),
lab = c("italic('Italic Text')", "Strikethrough"),
do_strike = c(FALSE, TRUE)
)
wrap_strike takes the text and wraps it in phantom which makes it invisible. For strikethrough text, it adds an underline.
wrap_strike <- function(text, do_strike) {
text <- glue::glue("phantom({text})")
ifelse(do_strike, glue::glue("underline({text})"), text)
}
If we nudge the y position of the new text, the underlines become strikethrough.
ggplot(df, aes(1, y, label = lab)) +
geom_point() +
geom_text(parse = TRUE, hjust = 0) +
geom_text(
data = mutate(df, lab = wrap_strike(lab, do_strike)),
parse = TRUE,
hjust = 0,
vjust = 0.1
)

R: placing a text with combination of variables over bars in ggplot

Lets draw a bar chart with ggplot2 from the following data (already in a long format). The values of the variable are then placed in the middle of the bars via geom_text() directive.
stuff.dat<-read.csv(text="continent,stuff,num
America,apples,13
America,bananas,13
Europe,apples,30
Europe,bananas,21
total,apples,43
total,bananas,34")
library(ggplot2)
ggplot(stuff.dat, aes(x=continent, y=num,fill=stuff))+geom_col() +
geom_text(position = position_stack(vjust=0.5),
aes(label=num))
Now it is necessary to add on top of the bars the "Apple-Bananas Index", which is defined as f=apples/bananas - just as manually added in the figure. How to program this in ggplot? How it would be possible to add it to the legend as a separate entry?
I think that the easiest way to achieve this is to prepare the data before you create the plot. I define a function abi() that computes the apple-banana-index from stuff.dat given a continent:
abi <- function(cont) {
with(stuff.dat,
num[continent == cont & stuff == "apples"] / num[continent == cont & stuff == "bananas"]
)
}
And then I create a data frame with all the necessary data:
conts <- levels(stuff.dat$continent)
abi_df <- data.frame(continent = conts,
yf = aggregate(num ~ continent, sum, data = stuff.dat)$num + 5,
abi = round(sapply(conts, abi), 1))
Now, I can add that information to the plot:
library(ggplot2)
ggplot(stuff.dat, aes(x = continent, y = num, fill = stuff)) +
geom_col() +
geom_text(position = position_stack(vjust = 0.5), aes(label = num)) +
geom_text(data = abi_df, aes(y = yf, label = paste0("f = ", abi), fill = NA))
Adding fill = NA to the geom_text() is a bit of a hack and leads to a warning. But if fill is not set, plotting will fail with a message that stuff was not found. I also tried to move fill = stuff from ggplot() to geom_col() but this breaks the y⁻coordinate of the text labels inside the bars. There might be a cleaner solution to this, but I haven't found it yet.
Adding the additional legend is, unfortunately, not trivial, because one cannot easily add text outside the plot area. This actually needs two steps: first one adds text using annotation_custom(). Then, you need to turn clipping off to make the text visible (see, e.g., here). This is a possible solution:
p <- ggplot(stuff.dat, aes(x = continent, y = num, fill = stuff)) +
geom_col() +
geom_text(position = position_stack(vjust = 0.5), aes(label = num)) +
geom_text(data = abi_df, aes(y = yf, label = paste0("f = ", abi), fill = NA)) +
guides(size = guide_legend(title = "f: ABI", override.aes = list(fill = 1))) +
annotation_custom(grob = textGrob("f: ABI\n(Apple-\nBanana-\nIndex",
gp = gpar(cex = .8), just = "left"),
xmin = 3.8, xmax = 3.8, ymin = 17, ymax = 17)
# turn off clipping
library(grid)
gt <- ggplot_gtable(ggplot_build(p))
gt$layout$clip[gt$layout$name == "panel"] <- "off"
grid.draw(gt)

Adding specific labels to legend

Goal: add numeric labels(number of bar on the plot) to legend, e.g 1.Company X
2.Company Y
3.Company Z
library(ggplot2)
require(scales)
companies = c('Company X','Company Y','Company Z')
profits = c(100,200,300)
data1 = data.frame(companies,profits)
CP <- ggplot(data1, aes(x = data1$companies,y = data1$profits,fill =data1$companies )) +
geom_bar(stat = 'identity') +
scale_x_discrete(name = "Companies",labels = 1:length(data1$companies))
Currently I have
What you might be looking for is paste:
newcompanies <- paste(1:50,companies,sep=".")
Personal (style) suggestion:
Search how you can change the colours to one colour-range. For fifty companies this colour-range will be confusing.
You can use seq_along and paste to make the plot you want as follow:
ggplot(data1, aes(x=seq_along(companies), weight=profits,
fill=paste(seq_along(companies), companies))) +
geom_bar() +
scale_fill_discrete("Companies") +
labs(x="Company Labels", y="Count")

Resources