Facet skip value x-axis - r

Im working on this df:
library("ggplot2")
library("reshape2")
library("tidyr")
library("scales")
library("dplyr")
Col0 <- c("AA", "BB", "CC", "DD","EE","FF")
D01012015 <- c(2,2,2,6,1,NA)
D02012015 <- c(2,2,2,1,3,1)
D03012015 <- c(2,2,3,4,6,4)
D04012015 <- c(2,2,3,1,2,4)
D05012015 <- c(2,1,1,1,1,0)
D06012015 <- c(2,4,2,5,4,9)
D07012015 <- c(2,4,2,5,4,1)
D08012015 <- c(2,2,3,4,5,3)
D09012015 <- c(1,3,3,2,2,1)
D10012015 <- c(1,3,3,2,2,1)
D11012015 <- c(1,3,3,2,4,1)
D12012015 <- c(1,3,3,4,2,1)
D13012015 <- c(1,3,5,2,2,1)
D14012015 <- c(1,3,3,7,2,1)
D15012015 <- c(1,3,3,7,2,7)
df<-data.frame(Col0,D01012015,D02012015,D03012015,D04012015,D05012015,D06012015,D07012015,D08012015,D09012015,D10012015,D11012015,
D12012015,D13012015,D14012015,D15012015)
I know that normally, if i'd like to print a value per week on the x axis i should create this ggplot function:
f<-melt(df,id =c("Col0"))
f$date<-as.Date(f$variable, format="D%d%m%Y")
pl<- ggplot(f, aes(date, value, fill=Col0))+ geom_line(aes(color=Col0,group=Col0))+ scale_x_date(breaks = date_breaks("1 week"))
My problem is that i have to create the same x axis values, using this function:
plotfun = function(data) {
xval<-"dates"
column<- names(data)[1]
data %>%
gather_(xval, "Val", select_vars_(names(.),
names(.),
exclude = column)) %>%
ggplot(aes_string(xval, "Val", group = column, col = column)) +
facet_grid(as.formula(paste(column, "~."))) +
geom_line()
}
plotfun(df)
I don't know how to transform in dates the x values with gather and how to jump values as in the previous ggplot function

Can you not just put in a mutate statement?
plotfun <- function(data) {
xval <- "dates"
column <- names(data)[1]
data %>%
gather_(xval, "Val", select_vars_(names(.),
names(.),
exclude = column)) %>%
mutate(dates = as.Date(f$variable, format = "D%d%m%Y")) %>%
ggplot(aes_string(xval, "Val", group = column, col = column)) +
facet_grid(as.formula(paste(column, "~."))) +
geom_line()
}
plotfun(df)

Related

Using assign within ggplot loop gives incorrect plots

I'm creating three plots in a loop over I and using assign to save each plot. The y variable is scaled by the loop index. The scaling should ensure that the final panel of plots each has y going from 0 to 1. This isn't happening and the plots seem to be being changed as the loop runs. I'd be grateful if someone could explain this apparently odd behaviour.
library(dplyr)
library(ggplot2)
library(gridExtra)
loci = c(1,2,3)
x <- seq(0,1,0.01)
df <- expand.grid(x = x, loci = loci)
df <- df %>% mutate(y = loci * x)
cols = c("red", "blue", "green")
for (i in loci){
plot_this <- df %>% filter(loci == i)
my_plot = ggplot(plot_this) +
geom_point( aes( x = x, y = y/i), colour = cols[i]) +
ylim(0,3) + ggtitle(paste0("i = ", i))
assign(paste0("plot_", i), my_plot)
print(plot_1)
}
grid.arrange(plot_1, plot_2, plot_3, ncol = 3)
It's due to the lazy evaluation nature of ggplot, and more explanation can be found in this post.
"Looping" with lapply avoids the problem.
Data
library(ggplot2)
library(gridExtra)
library(dplyr)
loci = c(1,2,3)
x <- seq(0,1,0.01)
df <- expand.grid(x = x, loci = loci)
df <- df %>% mutate(y = loci * x)
cols = c("red", "blue", "green")
Code
my_plot <- lapply(loci, function(i) {
df %>%
filter(loci == i) %>%
ggplot() +
geom_point(aes(x = x, y = y/i), colour = cols[i]) +
ylim(0,3) +
ggtitle(paste0("i = ", i))
})
grid.arrange(my_plot[[1]], my_plot[[2]], my_plot[[3]], ncol = 3)
Created on 2022-04-26 by the reprex package (v2.0.1)

How to get object name as a string using tidyevaluate?

I need to pass column names to the plotting function. The problem is that my column names are in the arguments and I don't know how to extract those as text.
Here is code that works, but I need to get the strings dynamically from the arguments.
create_plot <- function(df, group, subgroup, y){
var_group <- enquo(group)
var_subgroup <- enquo(subgroup)
var_y <- enquo(y)
df %>%
select(!!var_group, !!var_subgroup, !!var_y) %>%
mutate(!!var_group := as.factor(!!var_group),
!!var_subgroup := as.factor(!!var_subgroup)) %>%
ggsummarystats(., x = "COUNTRY", y="VALUE", # Need to get these from the arguments
palette = custom_pal,
ggfunc = ggboxplot,
color = "YEAR", #Same here
fill = "YEAR", #And here
summaries = c("n", "mean"))
}
create_plot(sales, YEAR, COUNTRY, VALUE)
Example using mtcars:
create_plot <- function(df, group, subgroup, y){
var_group <- enquo(group)
var_subgroup <- enquo(subgroup)
var_y <- enquo(y)
df %>%
select(!!var_group, !!var_subgroup, !!var_y) %>%
mutate(!!var_group := as.factor(!!var_group),
!!var_subgroup := as.factor(!!var_subgroup)) %>%
ggsummarystats(., x = "carb", y="mpg",
palette = custom_pal,
ggfunc = ggboxplot,
fill = "gear",
color = "gear",
summaries = c("n", "mean"))
}
create_plot(mtcars, gear, carb, mpg)
You can use rlang::as_name() for that:
library(tidyverse)
library(rlang)
library(ggpubr)
create_plot <- function(df, group, subgroup, y){
var_group <- enquo(group)
var_subgroup <- enquo(subgroup)
var_y <- enquo(y)
df %>%
select(!!var_group, !!var_subgroup, !!var_y) %>%
mutate(
!!var_group := as.factor(!!var_group),
!!var_subgroup := as.factor(!!var_subgroup)
) %>%
ggsummarystats(
x = as_name(var_group),
y = as_name(var_y),
fill = as_name(var_subgroup),
ggfunc = ggboxplot,
summaries = c("n", "mean"))
}
create_plot(mtcars, gear, carb, mpg)
Created on 2021-06-14 by the reprex package (v1.0.0)

Barplot subgroup factor reordering doesn't work

I want to order each bar within year like this: A, B, C.
I have looked at this post: https://ilari.scheinin.fi/ggplot-2-0-and-the-missing-order-aesthetic/
but it doesn't work at all.
Here's my code:
# data --------------------------------------------------------------------
ID <- c('1','2','3','4','5','6','7','7','8','9','10','11')
TypeCourtier <- c('A','A','A','A','B','B','B','B','C','C','C','C')
année_survenance <- c('2009','2010','2011','2012','2009','2010','2011','2012','2009','2010','2011','2012')
moyenne_charge <- c('1515','1551','89754','9148','787','9848','8474','3465','7488','884','8948','8484')
mediane_charge <- c('8185','5919','20409','8979','7777','9294','87484','8488','1881','18819','8484','84444')
totalComptage <- c('9989','849444','848','684','9845','1448','9844','2151','7171','5051','3959','9896')
data <- data.frame(ID, TypeCourtier, année_survenance, moyenne_charge, mediane_charge,totalComptage)
# main --------------------------------------------------------------------
install.packages("ggplot2")
library(ggplot2)
library(magrittr)
library(dplyr)
data$TypeCourtier <- factor(data$TypeCourtier, levels = c("A","B","C"), ordered= TRUE)
data %>%
ungroup() %>%
arrange(as.integer(TypeCourtier)) %>%
ggplot( aes(x=année_survenance, y = moyenne_charge, fill=TypeCourtier)) +
geom_bar(stat="identity", position=position_dodge())+
geom_text(aes(label=TypeCourtier),position = position_dodge(width = 0.9),vjust=-0.25) + theme(legend.position = "none")
The variable for the y-axis has to be numeric:
data$moyenne_charge <- as.numeric(as.character(data$moyenne_charge))

How to plot a(n unknown) number of data series as geom_line in same chart

My first Q here, so please go lightly if I'm out of step anywhere.
I'm trying to code R to produce a single chart to contain a number of data series lines. The number of data series may vary but will be provided in the data frame. I have tried to rearrange another thread's content to print the geom_line , but not successfully.
The logic is:
#desire to replace loop of 1:5 with ncol(df)
print(ggplot(df,aes(x=time))
for (i in 1:5) {
print (+ geom_line(aes(y=df[,i]))
}
#functioning geom point loops ggplot production:
for (i in 1:5) {
print(ggplot(df,aes(x=time,y=df[,i]))+geom_point())
}
#functioning multi-line ggplot where n is explicit:
ggplot(data=df, aes(x=time), group=1) +
geom_line(aes(y=df$`3`))+
geom_line(aes(y=df$`4`))
The functioning example code produces n number of point charts, 5 in this case. I would like just one chart to contain n line series.
This may be similar to How to plot n dimensional matrix? for which there are currently no relevant answers
Any contributions much appreciated, thanks
You can use gather from tidyverse "world" to do that.
As you didn't supply a sample data I used mtcars.
I created two data.frames one with 3 columns one with 9. In each one of them I plotted all of the variables against the variable mpg.
library(tidyverse)
df3Columns <- mtcars[, 1:4]
df9Columns <- mtcars[, 1:10]
df3Columns %>%
gather(var, value, -mpg) %>%
ggplot(aes(mpg, value, group = var, color = var)) +
geom_line()
df9Columns %>%
gather(var, value, -mpg) %>%
ggplot(aes(mpg, value, group = var, color = var)) +
geom_line()
Edit - using the sample data in comments.
library(tidyverse)
df %>%
rownames_to_column("time") %>%
gather(var, value, -time) %>%
ggplot(aes(time, value, group = var, color = var)) +
geom_line()
Sample data:
df <- structure(list("39083" = c(96, 100, 100), "39090" = c(99, 100, 100), "39097" = c(99, 100, 100)), row.names = 3:5, class = "data.frame")
To strictly answer your question, you can simply store your ggplot in a variable and add the geom_line one by one:
df <- structure(list("39083" = c(96, 100, 100), "39090" = c(99, 100, 100), "39097" = c(99, 100, 100)), row.names = 3:5, class = "data.frame")
g <- ggplot(df, aes(x = 1:nrow(df)))
for (i in colnames(df))
{
g <- g + geom_line(y = df[,i])
}
g <- g + scale_y_continuous(limits = c(min(df), max(df)))
print(g)
However, this is not a very convenient solution. I would highly recommend to refactor your data frame to be more ggplot style.
df.ultimate <- data.frame(time = numeric(), value = numeric(), group = character())
for (i in colnames(df))
{
df.ultimate <- rbind(df.ultimate, data.frame(time = 1:nrow(df), value = df[, i], group = i))
}
g <- ggplot(df.ultimate, aes(x = time, y = value, color = group))
g <- g + geom_line()
print(g)
A one-line solution:
ggplot(data.frame(time = rep(1:nrow(df), ncol(df)),
value = as.vector(as.matrix(df)),
group = rep(colnames(df), each = nrow(df))),
aes(x = time, y = value, color = group)) + geom_line()

r - make plotting function with ggplot2, aes_string and reorder

I'm trying to make a function that will use ggplot2inside,aes_stringand reorder but with no luck so far.
Basically if we have a sample dataset like the following:
library(ggplot2)
library(dplyr)
set.seed(123)
dt <- data.frame(
id = c(1,1,1,2,2),
a = c("b", "d", "c", "a", "b"),
b = sample(1:10, 5, replace = F),
cat = c(1,1,2,2,2)) %>%
mutate(a = as.factor(a)) %>%
as_tibble()
I want the function to accept the following arguments: the dataset, a filtering variable, and two variables for plotting.
This is what I managed to do:
myplot <- function(df, filtval, var1, var2) {
data <- df %>% filter(id == filtval)
ggplot(data) +
geom_point(
aes_string(
x = reorder(var1, var2),
y = var2)
)
}
Unfortunately when running it returns the error:
myplot(dt, 1, "a", "b")
Warning message:
In mean.default(X[[i]], ...) :
argument is not numeric or logical: returning NA
This is what I want the function to do:
data <- dt %>% filter(id == 1)
ggplot(data) +
geom_col(aes(x = reorder(a, - b), y = b))
With the latest version of ggplot, you should be use aes with !! and sym() to turn your strings into symbols.
myplot <- function(df, filtval, var1, var2) {
data <- df %>% filter(id == filtval)
ggplot(data) +
geom_point(
aes(
x = reorder(!!sym(var1), !!sym(var2)),
y = !!sym(var2))
)
}
After discussing with mr Flick (see below), this should do NOT be used:
myplot <- function(df, filtval, var1, var2) {
data <- df %>% filter(id == filtval)
data$new_order <- reorder(data[[var1]], data[[var2]])
ggplot(data) +
geom_point(mapping=
aes_string(
x = "new_order",
y = var2)
)
}
Take his solution instead :)

Resources