I am attempting to pass an expression with subscript to a single geom_text() label in ggplot. Here is my code right now:
my_exp <- expression('my_exp'[s][u][b])
my_data <-
data.frame(
var_1 = c("a", "b", "c"),
var_2 = c(1, 2, 3)
)
my_data %>%
ggplot(aes(x = var_1, y = var_2))+
geom_text(aes(label = var_1))
Here is the resulting plot:
What I would like to do is replace the var_1 value of "a" with the expression specified by my_exp and then have geom_text() evaluate that value as an expression, resulting in the subscript appearing on the ggplot.
I would suggest this approach. You can build another variable for your labels and then enable the option parse=T from geom_text() in order to have the desired plot. Here the code:
library(ggplot2)
library(tidyverse)
#Data
my_exp <- as.character(expression('my_exp'[s][u][b]))
my_data <-
data.frame(
var_1 = c("a", "b", "c"),
var_2 = c(1, 2, 3),stringsAsFactors = F
)
#Mutate
my_data$label <- ifelse(my_data$var_1=='a',my_exp,my_data$var_1)
#Plot
my_data %>%
ggplot(aes(x = var_1, y = var_2))+
geom_text(aes(label = label),parse = T)
Output:
Update: If there are issues with labels here a code for that:
#Label
my_exp <- "14~M~my_exp[s][u][b]"
#Code
my_data <-
data.frame(
var_1 = c("a", "b", "c"),
var_2 = c(1, 2, 3),stringsAsFactors = F
)
#Mutate
my_data$label <- ifelse(my_data$var_1=='a',my_exp,my_data$var_1)
#Plot
my_data %>%
ggplot(aes(x = var_1, y = var_2))+
geom_text(aes(label = label),parse = T)
Output:
Related
The data is facetted by two variables (see graph). Each variable has a different range. I want to specify the range so that all plots in var1 and vae2 are bound by the min and max values of those variables. See sample code attached. I don't want to use setscales = "free" on facet_wrap.
var1 <- rnorm(100, 6, 2)
var2 <- rnorm(100,15,2)
spp.val <- rnorm(100,10,2)
spp <- rep(c("A","B","C","D"), 25)
df <- data.frame(var1, var2,spp, spp.val)
df <- gather(df,
key = "var",
value = "var.val",
var1,var2)
df$var <- as.factor(as.character(df$var))
df$spp <- as.factor(as.character(df$spp))
ggplot(aes(x = var.val, y = spp.val), data = df) +
geom_point() +
facet_grid(spp~var)
#I want the limits for each facet_grid to be set as follows
xlim(min(df[df$var == "var1",]), max(df[df$var == "var1",])
xlim(min(df[df$var == "var2",]), max(df[df$var == "var2",])
Is this what you want?
library(tidyverse)
tibble(
var1 = rnorm(100, 6, 2),
var2 = rnorm(100, 15, 2),
spp.val = rnorm(100, 10, 2),
spp = rep(c("A", "B", "C", "D"), 25)
) |>
pivot_longer(starts_with("var"), names_to = "var", values_to = "var.val") |>
mutate(across(c(spp, var), factor)) |>
ggplot(aes(var.val, spp.val)) +
geom_point() +
facet_grid(spp ~var, scales = "free_x")
Created on 2022-04-23 by the reprex package (v2.0.1)
How can I scale/normalize my data per row (Observations)? Something like [-1:1] like a z score?
I have seen previous post which involve normalization of the whole dataset like this https://stats.stackexchange.com/questions/178626/how-to-normalize-data-between-1-and-1
, but id like to normalise per row so they can be plotted in a same box plot as they all show same pattern across x-axis.
Obs <- c("A", "B", "C")
count1 <- c(100,15,3)
count2 <- c(250, 30, 5)
count3 <- c(290, 20, 8)
count4<- c(80,12, 2 )
df <- data.frame(Obs, count1, count2, count3, count4)
dff<- df %>% pivot_longer(cols = !Obs, names_to = 'count', values_to = 'Value')
ggplot(dff, aes(x = count, y = Value)) +
geom_jitter(alpha = 0.1, color = "tomato") +
geom_boxplot()
Based on the link you shared, you can use apply to use the corresponding function to rescale dataframe over [-1,1].
library(scales)
library(ggplot2)
library(tidyr)
Obs <- c("A", "B", "C")
count1 <- c(100,15,3)
count2 <- c(250, 30, 5)
count3 <- c(290, 20, 8)
count4<- c(80,12, 2 )
df <- data.frame(count1, count2, count3, count4)
df <- as.data.frame(t(apply(df, 1, function(x)(2*(x-min(x))/(max(x)-min(x)))- 1)))
df <- cbind(Obs, df)
dff<- df %>%
tidyr::pivot_longer(cols = !Obs, names_to = 'count', values_to = 'Value')
ggplot(dff, aes(x = count, y = Value)) +
geom_jitter(alpha = 0.1, color = "tomato") +
geom_boxplot()
Console output:
If you pivot it longer, you can group by your observations and scale:
df %>%
pivot_longer(cols = !Obs, names_to = 'count', values_to = 'Value') %>% group_by(Obs) %>%
mutate(z=as.numeric(scale(Value))) %>%
ggplot(aes(x=count,y=z))+geom_boxplot()
Or in base R, just do:
boxplot(t(scale(t(df[,-1]))))
Recently I discovered the function geom_table(), from ggpmisc package, which allows you to put a table inside a plot. But I don't know how to put different tables into a grid plot.
I have this df and plot:
library(lubridate)
library(ggplot2)
library(ggpmisc)
Date <- c("2010-01-28", "2010-02-28", "2010-03-28",
"2010-04-28", "2010-05-28", "2010-06-28",
"2010-07-28", "2010-08-28", "2010-09-28",
"2010-10-28")
Date <- as_date(Date)
Country <- rep("Japan", 10)
A <- runif(10, min=30, max=90)
B <- runif(10, min = 1, max = 15)
df <- data.frame(Date, Country, A, B)
df %>% pivot_longer(-c(Date, Country)) %>%
ggplot(aes(x=Date,y=value,group=1,color=Country))+
geom_line(size = 0.9) +
facet_grid(name~Country, scales = "free", switch = "y")
I also have these two tables, tableA and tableB:
Time <- c("Today", "Yesterday", "One week ago")
Value_A <- 10:12
Value_B <- 1:3
tableA <- data.frame(Time, Value_A)
tableB <- data.frame(Time, Value_B)
How I put tableA in the top graph and tableB in the bottom graph?
I appreciate it if someone can help :)
You need to create a little data frame that hosts your tableA and tableB in a list column:
d <- tibble(x = c(0.95, 0.95), y = c(0.95, 0.95),
name = c("A", "B"), tb = list(tableA, tableB))
df %>% pivot_longer(-c(Date, Country)) %>%
ggplot(aes(x=Date,y=value,group=1,color=Country))+
geom_line(size = 0.9) +
geom_table_npc(data = d, aes(npcx = x, npcy = y, label = tb)) +
facet_grid(name~Country, scales = "free", switch = "y")
This is a follow-up my original question for how to pass an expression with subscript to a geom_text label in ggplot.
Duck provided a great solution using parse = T within the geom_text() command. However, I am now running into a problem because the variable I wish to pass an expression to contains other content that appears unreadable with parse = T
Here is my current code (again, thank you to Duck for this solution):
library(ggplot2)
library(tidyverse)
#Data
my_exp <- as.character(expression('my_exp'[s][u][b]))
my_data <-
data.frame(
var_1 = c("9R", "14M", "17C"),
var_2 = c(1, 2, 3),stringsAsFactors = F
)
#Mutate
my_data$label <- ifelse(my_data$var_1=='9R',my_exp,my_data$var_1)
#Plot
my_data %>%
ggplot(aes(x = var_1, y = var_2))+
geom_text(aes(label = label),parse = T)
And here is the error output that appears when I try to render the ggplot:
> library(ggplot2)
> library(tidyverse)
> #Data
> my_exp <- as.character(expression('my_exp'[s][u][b]))
> my_data <-
+ data.frame(
+ var_1 = c("9R", "14M", "17C"),
+ var_2 = c(1, 2, 3),stringsAsFactors = F
+ )
> #Mutate
> my_data$label <- ifelse(my_data$var_1=='9R',my_exp,my_data$var_1)
> #Plot
> my_data %>%
+ ggplot(aes(x = var_1, y = var_2))+
+ geom_text(aes(label = label),parse = T)
Error in parse(text = text[[i]]) : <text>:1:3: unexpected symbol
1: 14M
^
>
It appears R is having a hard time reading the cells where I have not passed the expression. Is there a way to have R only parse the relevant cell(s)?
Thanks!
As an alternative, you can use geom_richtext() from the ggtext package and create super- or subscripts with <sup>...</sup> or <sub>...</sub>.
library(ggplot2)
library(ggtext)
#Data
my_exp <- "my_exp<sub>sub</sub>"
my_data <-
data.frame(
var_1 = c("9R", "14M", "17C"),
var_2 = c(1, 2, 3), stringsAsFactors = F
)
#Mutate
my_data$label <- ifelse(my_data$var_1=='9R', my_exp, my_data$var_1)
#Plot
ggplot(my_data, aes(x = var_1, y = var_2)) +
geom_richtext(
aes(label = label),
# customization to remove background and border around labels
fill = NA,
label.colour = NA
)
Created on 2020-09-09 by the reprex package (v0.3.0)
Maybe this might not be optimal but you can create a label for your expressions and another for your classic text. Here the code:
library(ggplot2)
library(tidyverse)
#Data
my_exp <- as.character(expression('my_exp'[s][u][b]))
my_data <-
data.frame(
var_1 = c("9R", "14M", "17C"),
var_2 = c(1, 2, 3),stringsAsFactors = F
)
#Mutate label 1
my_data$label <- ifelse(my_data$var_1=='9R',my_exp,NA)
my_data$label2 <- ifelse(my_data$var_1=='9R',NA,my_data$var_1)
#Plot
my_data %>%
ggplot(aes(x = var_1, y = var_2))+
geom_text(aes(label = label),parse = T)+
geom_text(aes(label = label2))
Output:
Using geom_text() twice you can hack the plot.
I want to create a bar plot based on the following data:
Station Delay
A 5
B 6
A 4
A 3
B 8
X axis should contain stations "A" and "B", while bars (Y axis) should show average delay per a station.
I tried this, but it does not give a correct result:
barplot(c(data$Station, data$Delay),
main="BARPLOT", xlab="Stations", ylab="Delays",
names.arg=data$Station)
df <- data.frame(Station = c("A", "B", "A", "A", "B"), Delay= c(5, 6, 4, 3, 8))
library(dplyr)
df <- df %>% group_by(Station) %>% summarise(me = mean(Delay))
library(ggplot2)
ggplot(aes(x = Station, y = me), data = df) + geom_bar(stat = "identity")
or directly with stat_summary
ggplot(aes(x = Station, y = Delay), data = df) + stat_summary(fun.y = "mean", geom = "bar")
In base R, you can do:
m_data <- data.frame(data$Station, m_del=ave(data$Delay, data$Station), stringsAsFactors=F)
barplot(unique(m_data)$m_del, names=unique(m_data)$Station, main="BARPLOT", xlab="Stations", ylab="Delays")
Or with the package data.table, you can do:
library(data.table)
m_data <- setDT(data)[, mean(Delay), by=Station]
m_data[, barplot(V1, names=Station, main="BARPLOT", xlab="Stations", ylab="Delays")]