Grouping boxplot together - ggplot2

I have the following data and would like to create a group boxplot. I created a bargraph in excel and would like to create the boxplot in the exact same way using R (see bargraph here). I tried using ggplot but was unsuccessful. Any help will be appreciated. Thank you.
Fruit spring summer fall
Banana 19.36 91.51 49.99
Apple 65.27 51.55 42.83
orange 16.21 94.71 62.33

It's not clear what exactly you are looking for. To have the bar graph, you can do something like this:
library(tidyverse)
df %>%
pivot_longer(!Fruit) %>%
ggplot(aes(x = Fruit, y = value, fill = name)) +
geom_bar(position="dodge", stat="identity")
Output
As far as a boxplot, you would need more than 1 data point, but if you wanted to do a box plot by Fruit, then you could do something like this:
df %>%
pivot_longer(!Fruit) %>%
ggplot(aes(x = Fruit, y = value, fill = Fruit)) +
geom_boxplot()
Output

Related

Filtering and calculating mean within groups ggplot2

I'm working with a large df trying to make some plots by filterig data through different attributes of interest. Let's say my df looks like:
df(site=c(A,B,C,D,E), subsite=c(w,x,y,z), date=c(01/01/1985, 05/01/1985, 16/03/1995, 24/03/1995), species=c(1,2,3,4), Year=c(1985,1990,1995,2012), julian day=c(1,2,3,4), Month=c(6,7,8,11).
I would like plot the average julian day per month each year in which a species was present in a Subsite and Site. So far I've got this code but the average has been calculated for each month over all the years in my df rather than per year. Any help/ directions would be welcome!
Plot1<- df %>%
filter(Site=="A", Year>1985, Species =="2")%>%
group_by(Month) %>%
mutate("Day" = mean(julian day)) %>%
ggplot(aes(x=Year, y=Day, color=Species)) +
geom_boxplot() +
stat_summary(fun=mean, geom="point",
shape=1, size=1, show.legend=FALSE) +
stat_summary(fun=mean, colour="red", geom="text", show.legend = FALSE,
vjust=-0.7,size=3, aes(label=round(..y.., digits=0)))
Thanks!
I think I spotted the error.
I was missing this:
group_by(Month, **Year**) %>%

Sorting a dataframe to create a "quilt" chart using geom_tile in ggplot2

I am looking to create a "quilt" chart that would show the best performing category in each year. This is a fairly common chart, but I have no idea how to produce this in R. Below is a simple reproducible example.
fruit <- c("Apples", "Oranges", "Pears", "Peaches")
yield2020 <- c("200", "100", "250", "125")
yield2021 <- c("40", "90", "85", "100")
yield2022 <- c("150", "110", "150", "170")
DF <- data.frame (Fruit, yield2020, yield2021, yield2022)
As you can see in DF, each year, Apples, Oranges, Peaches, and Pears have different output levels. I'm looking to create a geom_tile chart that would show Pears as the top performer in 2020, Peaches in 2021, and Peaches again in 2022, with the other fruit groups shown, color coded, below it. Any advice is greatly appreciated!
I found the below example of a different quilt chart, which might help frame my ultimate goal here
One option to achieve your desired result would be to reshape your data to long and to add a column with the rank per year which could then be mapped on the y aes. Additionally I use scale_y_reverse to put the top performers on top of the chart:
library(dplyr)
library(tidyr)
library(ggplot2)
df <- DF |>
pivot_longer(-fruit, names_to = "year", names_prefix = "yield") |>
mutate(across(c(year, value), as.numeric)) |>
group_by(year) |>
mutate(rank = rank(-value, ties.method = "first"))
ggplot(df, aes(year, rank, fill = fruit)) +
geom_tile() +
geom_text(aes(label = paste(fruit, value, sep = "\n"))) +
scale_y_reverse() +
guides(fill = "none")

Grouping the factors in ggplot

I am trying to create a graph based on matrix similar to one below... I am trying to group the Erosion values based on "Slope"...
library(ggplot2)
new_mat<-matrix(,nrow = 135, ncol = 7)
colnames(new_mat)<-c("Scenario","Runoff (mm)","Erosion (t/ac)","Slope","Soil","Tillage","Rotation")
for ( i in 1:nrow(new_mat)){
new_mat[i,2]<-sample(10:50, 1)
new_mat[i,3]<-sample(0.1:20, 1)
new_mat[i,4]<-sample(c("S2","S3","S4","S5","S1"),1)
new_mat[i,5]<-sample(c("Deep","Moderate","Shallow"),1)
new_mat[i,7]<-sample(c("WBP","WBF","WF"),1)
new_mat[i,6]<-sample(c("Intense","Reduced","Notill"),1)
new_mat[i,1]<-paste0(new_mat[i,4],"_",new_mat[i,5],"_",new_mat[i,6],"_",new_mat[i,7],"_")
}
#### Graph part ########
grphs_mat<-as.data.frame(new_mat)
grphs_mat$`Runoff (mm)`<-as.numeric(as.character(grphs_mat$`Runoff (mm)`))
grphs_mat$`Erosion (t/ac)`<-as.numeric(as.character(grphs_mat$`Erosion (t/ac)`))
ggplot(grphs_mat, aes(Scenario, `Erosion (t/ac)`,group=Slope, colour = Slope))+
scale_y_continuous(limits=c(0,max(as.numeric((grphs_mat$`Erosion (t/ac)`)))))+
geom_point()+geom_line()
But when i run this code.. The values are distributed in x-axis for all 135 scenarios. But what i want is grouping to be done in terms of slope but it also picks up the other common factors such as Soil+Rotation+Tillage and place it in x-axis. For example:
For these five scenarios:
S1_Deep_Intense_WBF_
S2_Deep_Intense_WBF_
S3_Deep_Intense_WBF_
S4_Deep_Intense_WBF_
S5_Deep_Intense_WBF_
It separates the S1, S2, S3,S4,S5 but also be able to know that other factors are same and put them in x-axis such that the slope lines are stacked on top of each other in 135/5 = 27 x-axis points. The final figure should look like this (Refer image). Apologies for not being able to explain it better.
I think i am making a mistake in grouping or assigning the x-axis values.
I will appreciate your suggestions.
In the example you give, I didn't get every possible factor combination represented so the plots looked a bit weird. What I did instead was start with the following:
set.seed(42)
new_mat <- matrix(,nrow = 1000, ncol = 7)
And then deduplicated this by summarising the values. A possible relevant step here for you analysis is that I made new variable with the interaction() function that is the combination of three other factors.
library(tidyverse)
df <- grphs_mat
df$x <- with(df, interaction(Rotation, Soil, Tillage))
# The simulation did not yield unique combinations
df <- df %>% group_by(x, Slope) %>%
summarise(n = sum(`Erosion (t/ac)`))
Next, I plotted this new x variable on the x-axis and used "stack" positions for the lines and points.
g <- ggplot(df, aes(x, y = n, colour = Slope, group = Slope)) +
geom_line(position = "stack") +
geom_point(position = "stack")
To make the x-axis slightly more readable, you can replace the . that the interaction() function placed by newlines.
g + scale_x_discrete(labels = function(x){gsub("\\.", "\n", x)})
Another option is to simply rotate the x axis labels:
g + theme(axis.text.x.bottom = element_text(angle = 90))
There are a few additional options for the x-axis if you go into ggplot2 extension packages.

Plotly is not reading ggplot output well

I am using the following code to plot some data points and it works well in ggplot. However, when I feed this into ggplotly, the visualization and Y-axis labels change completely. Y-axis label shift to right and gets flipped, and the lines in the center get thinner.
Code
library(ggplot2)
library(tidyverse)
library(plotly)
file2 <- read.csv( text = RCurl::getURL("https://gist.githubusercontent.com/gireeshkbogu/806424c1777ff721a046b3e30e85af5a/raw/50ac0b4696f514677b4987b90305fdf879fbcd84/reproducible.examples.txt"), sep="\t")
p <- ggplot(data=subset(file2,!is.na(datetime)),
aes(x=datetime, y=Count,
color=Type,
group=Subject)) +
geom_point(size=4, alpha=0.6) +
scale_y_continuous(breaks=c(0,1))+
theme(axis.text.x=element_text(angle=90, size = 5))+
facet_grid(Subject ~ ., switch = "y") +
theme(axis.title.y=element_blank(),
axis.text.y=element_blank(),
axis.ticks.y=element_blank())+
theme(strip.text.y.left = element_text(angle = 0, size=5)) +
scale_color_manual(values=c("red", "#990000", "#330000", "#00CC99", "#0099FF"))
ggplotly(p)
Ggplot image
Ggplotly image
Reproducible Example
Subject datetime Type Count
user1 4/16/20 15:00 A1 1
user1 3/28/20 13:00 A1 1
user2 4/29/20 15:00 A1 1
user2 5/02/20 09:00 A1 1
user1 2/19/20 18:00 A2 1
user1 4/20/20 16:00 A2 1
Converting ggplot to plotly turns out to be surprisingly complicated! Many ggplot features are silently dropped or incorrectly translated over to plotly.
If I am not mistaken, switch = "y" within your facet_grid is being silently dropped.
In addition, you have too many facets in your plot. Looks like "Subject" is creating 30+ facets. I know that it is tempting to try and fit as much data into one plot, but you are really pushing the limits of what you can do with facets here.
I made some modifications. See if this is something you can work with:
library(ggplot2)
library(tidyverse)
library(plotly)
library(RCurl)
# your original file
file2 <- read.csv( text = RCurl::getURL("https://gist.githubusercontent.com/gireeshkbogu/806424c1777ff721a046b3e30e85af5a/raw/50ac0b4696f514677b4987b90305fdf879fbcd84/reproducible.examples.txt"), sep="\t")
head(file2)
# scaling down the dataframe so that you have fewer facets per plot
file3 <- file2 %>%
as_tibble() %>%
na.omit() %>%
filter(Subject %in% c("User1", "User2", "User3", "User4")) %>%
arrange(Subject, datetime)
head(file3)
# sending the smaller data frame to ggplot
p_2 <- ggplot(data=file3,
aes(x=datetime, y=Count, color=Type, group=Subject)) +
geom_point(size=4, alpha=0.6) +
scale_y_continuous(breaks=c(0,1))+
theme(axis.text.x=element_text(angle=90, size = 5)) +
facet_grid(Subject ~ .) + # removing "Switch" ; it is being dropped by plotly
theme(axis.title.y=element_blank(),
axis.text.y=element_blank(),
axis.ticks.y=element_blank(),
legend.position = "left") + # move legend to left on ggplot
theme(strip.text.y.left = element_text(angle = 0, size=5)) +
scale_color_manual(values=c("red", "#990000", "#330000", "#00CC99", "#0099FF"))
p_2
ggplotly(p_2) %>%
layout(title = "Modified & Scaled Down Plot",
legend = list(orientation = "v", # fine-tune legend directly in plotly,
y = 1, x = -0.1)) # you may need to fiddle with these
The modified code yields me this plot. You will probably need to make a few small groups by "Subject" and call a plot for each group.

How to add two boxplots in a same graph in ggplot2

I have this sample data.
sample <- data.frame(sample = 1:12,
site = c('A','A','A','B','B','B','A','A','A','B','B','B'),
month = c(rep('Feb', 6), rep('Aug', 6)),
Ar = c(7,8,9,8,9,9,4,5,7,5,8,9))
And created two boxplots
ggplot(sample, aes(x=factor(month), y=Ar)) +
geom_boxplot(aes(fill=site))
ggplot(sample, aes(x=factor(month), y=Ar)) +
geom_boxplot()
I wonder if there is a way to combine them in the same graph so that total, site A and site B are right next to each other per each month.
You could utilize dplyr (via the tidyverse package) and reshape2.
library(dplyr)
library(reshape2)
sample%>%
dplyr::select(-sample) %>%
mutate(global = 'Global') %>%
melt(., id.vars=c("month", "Ar")) %>%
ggplot(aes(month, Ar)) + geom_boxplot(aes(month, Ar, fill=value))
This drops the sample column as you aren't currently using it, adds the term global in a separate column, reshapes the data via the melt function and generates a figure. Note that I changed the input code format in your original question. With the changes to the data.frame you no longer need to coerce the variables to factors.