Raster-like timeseries graph in ggplot2 - r

I'm trying to recreate a graph like the one here using ggplot2.
I can get pretty close if I mess around with the size and shape of points using coord_equal, but...
Example data and code
library(ggplot2)
df <- data.frame()
Years <- 1990:2020
for(i in 1:length(Years)) {
Year <- Years[i]
week <-1:52
value <- sort(round(rnorm(52, 50, 30), 0))
df.small <- data.frame(Year = Year, week = week, value = value)
df <- bind_rows(df, df.small)
}
ggplot(df, aes(week, Year, color = value)) +
geom_point(shape = 15, size = 2.7) +
scale_color_gradientn(colours = rainbow(10)) +
coord_equal()
The problem is,
with my real data I want to "stretch" the graph so I can see it more clearly (my timeseries is shorter) and when I don't use coord_equal, squares don't fill the graphing area:
ggplot(df, aes(week, Year, color = value)) +
geom_point(shape = 15, size = 2.7) +
scale_color_gradientn(colours = rainbow(10))

Is this as simple as using the geom_raster geom?
ggplot(df, aes(week, Year)) +
geom_raster(aes(fill = value)) +
scale_fill_gradientn(colours = rainbow(10)) +
coord_equal()

Related

How do you change the X axis number? [duplicate]

This question already has answers here:
Add legend to ggplot2 line plot
(4 answers)
Closed 3 years ago.
p = ggplot() +
geom_line(data = Month_time, aes(x = Month, y = CarrierDelay), color = "red") +
geom_line(data = Month_time, aes(x = Month, y = WeatherDelay), color = "purple") +
geom_line(data = Month_time, aes(x = Month, y = NASDelay), color = "yellow") +
geom_line(data = Month_time, aes(x = Month, y = SecurityDelay), color = "green") +
geom_line(data = Month_time, aes(x = Month, y = LateAircraftDelay), color = "blue") +
xlab('Month') +
ylab('Delay Types [min]')
print(p)
Q How do you change the X-axis the Month to be just 1, 2, 3, 4 ...?
Q Also how do you add the label for each graph?
you can use scale_x_continuous. Also, you can get the desired plot by specifying the data source once at the beginning:
ggplot(month_time) +
geom_line(aes(x = Month, y = WeatherDelay), color = "purple") +
geom_line(aes(x = Month, y = NASDelay), color = "yellow") +
scale_x_continuous(breaks = 1:12)
Here, a sample of code that should re-organize your data to be ready to be plot by ggplot2:
library(tidyr)
library(dplyr)
library(ggplot2)
Month_subset = Month_time %>% select(., Month, CarrierDelay, WeatherDelay, NASDelay, SecurityDelay, LateAircraftDelay) %>%
pivot_longer(-Month,names_to = "Conditions", values_to = "Value")
ggplot(Month_subset, aes(x = Month, y = Value, color = Conditions)) +
geom_line() +
ylab("Delay Types [min]") +
scale_x_continuous(breaks = 1:12)
Basically, using dplyr and tidyr, we are going to select columns of interest then, re-organise the data in a long format using pivot_longer. And finally, we are going to plot everything in once using ggplot2. Like that, each of your conditions will be plot with a different color and a legend will be added mentioning each labels.
Warning this code is based on what I understand of what you are trying to do, but I can't verify it since you are not provding a reproducible example of your dataset. If you are adding one in your question, I will be happy to test my code and update it based on your real data

Plot labels at ends of lines in stacked area chart

I have the following code
library(ggplot2)
library(dplyr)
# create data
time <- as.numeric(rep(seq(1,7),each=7)) # x Axis
value <- runif(49, 10, 100) # y Axis
group <- rep(LETTERS[1:7],times=7) # group, one shape per group
data <- data.frame(time, value, group)
# stacked area chart
ggplot(data, aes(x=time, y=value, fill=group)) +
geom_area()+
geom_text(data = data %>% filter(time == last(time)), aes(label = group,
x = time + 0.5,
y = value,
color = group)) +
guides(color = FALSE) + theme_bw() +
scale_x_continuous(breaks = scales::pretty_breaks(10))
Where i get
But i am aiming for link
Is there any solution for stacked area plot?
The question code is plotting the text labels in the value's of the last time, when in fact the areas are cumulative. And in reverse order.
Also, the following graph plots data created with the same code but with
set.seed(1234)
Then the data creation code is the same as in the question.
# stacked area chart
ggplot(data, aes(x=time, y=value, fill=group)) +
geom_area()+
geom_text(data = data %>%
filter(time == last(time)) %>%
mutate(value = cumsum(rev(value))),
aes(label = rev(group),
x = time + 0.5,
y = value,
color = rev(group))) +
guides(color = FALSE) + theme_bw() +
scale_x_continuous(breaks = scales::pretty_breaks(10))
Edit.
Following the discussion in the comments to this answer, I have decided to post code based on the comment by user Jake Kaupp.
ggplot(data, aes(x = time, y = value, fill = group)) +
geom_area()+
geom_text(data = data %>% filter(time == last(time)),
aes(x = time + 0.5, y = value,
label = rev(group), color = rev(group)),
position = position_stack(vjust = 0.5)) +
guides(color = FALSE) +
theme_bw() +
scale_x_continuous(breaks = scales::pretty_breaks(10))
You can use the text function to put text wherever you want. For example:
text(7.2, 350, "B", col="brown")
Here we go
time <- as.numeric(rep(seq(1,7),each=8)) # x Axis
value <- runif(56, 10, 100) # y Axis
group <- rep(LETTERS[1:8],times=7) # group, one shape per group
data <- data.frame(time, value, group)
round_df <- function(x, digits) {
# round all numeric variables
# x: data frame
# digits: number of digits to round
numeric_columns <- sapply(x, mode) == 'numeric'
x[numeric_columns] <- round(x[numeric_columns], digits)
x
}
data$value<- round_df(data$value, 2)
# stacked area chart
ggplot(data, aes(x=time, y=value, fill=group)) +
geom_area()+
geom_text(aes(x = time + 0.5, y = value, label=ifelse(time == max(time), group, NA)),position = position_stack(vjust = 0.5),check_overlap = TRUE)+
guides(color = FALSE) + theme_bw()+
scale_x_continuous(breaks = scales::pretty_breaks(10)) +
geom_text(aes(label=ifelse(time != min(time) & time != max(time),value, NA)),position = position_stack(vjust = 0.5),check_overlap = TRUE)+
geom_text(aes(x = time + 0.18,label=ifelse(time == min(time),value, NA)),position = position_stack(vjust = 0.5),check_overlap = TRUE)+
geom_text(aes(x = time - 0.18,label=ifelse(time == max(time),value, NA)),position = position_stack(vjust = 0.5),check_overlap = TRUE)
And get
Factor levels but why not letters? That is the next step :)
UPDATED
just converted factor to char data$group <- as.character(data$group)

ggplot2 and facet_grid : add highest value for each plot

I am using facet_grid() to plot multiple plot divided per groups of data. For each plot, I want to add in the corner the highest value of the Y axis. I've tried several hacks but it never gives me the expected results. This answer partially helps me but the value I want to add will constantly be changing, therefore I don't see how I can apply it.
Here is a minimal example, I'd like to add the red numbers on the graph below:
library(ggplot2)
data <- data.frame('group'=rep(c('A','B'),each=4),'hour'=rep(c(1,2,3,4),2),'value'=c(5,4,2,3,6,7,4,5))
ggplot(data,aes(x = hour, y = value)) +
geom_line() +
geom_point() +
theme(aspect.ratio=1) +
scale_x_continuous(name ="hours", limits=c(1,4)) +
scale_y_continuous(limits=c(1,10),breaks = seq(1, 10, by = 2))+
facet_grid( ~ group)
Thanks for your help!
library(dplyr)
data2 <- data %>% group_by(group) %>% summarise(Max = max(value))
ggplot(data,aes(x = hour, y = value)) +
geom_line() +
geom_point() +
geom_text(aes(label = Max), x = Inf, y = Inf, data2,
hjust = 2, vjust = 2, col = 'red') +
theme(aspect.ratio=1) +
scale_x_continuous(name ="hours", limits=c(1,4)) +
scale_y_continuous(limits=c(1,10),breaks = seq(1, 10, by = 2))+
facet_grid( ~ group)
This does the trick. If you always have fixed ranges you can position the text manually.
library(ggplot2)
data <- data.frame('group'=rep(c('A','B'),each=4),'hour'=rep(c(1,2,3,4),2),'value'=c(5,4,2,3,6,7,4,5))
ggplot(data,aes(x = hour, y = value)) +
geom_line() +
geom_point() +
geom_text(
aes(x, y, label=lab),
data = data.frame(
x=Inf,
y=Inf,
lab=tapply(data$value, data$group, max),
group=unique(data$group)
),
vjust="inward",
hjust = "inward"
) +
theme(aspect.ratio=1) +
scale_x_continuous(name ="hours", limits=c(1,4)) +
scale_y_continuous(limits=c(1,10),breaks = seq(1, 10, by = 2))+
facet_grid( ~ group)

Shapes on line graph using stat_summary

I'm sure the answer is very simple but at the moment it eludes me. I want to make a line graph using stat_summary(), with different shapes for each group (representing an experimental condition) at each x-axis tick (representing a separate time point).
Here's the data
set.seed(124)
ID <- rep(1:12, times = 3)
Group <- rep(c("A", "B", "C"), times = 12)
score <- rnorm(36, 25, 3)
session <- rep(c("s1","s2", "s3"), each = 12)
df <- data.frame(ID, Group, session, score)
Now I can get there by making a table of means for each time point. Like so.
gMeans <- aggregate(score ~ session + Group, data = df, mean)
And then graphing it like so.
pMeans <- ggplot(data = gMeans, aes(x = session, y = score, group = Group, shape = Group)) +
geom_line(aes(linetype = Group), size = 1) +
geom_point(size = 5, fill = "white") +
scale_color_hue(name = "Group", l = 30) +
scale_shape_manual(name = "Group", values = c(23,22, 21)) +
scale_linetype_discrete(name = "Group") +
theme_bw()
pMeans
However I would like to be able to skip the step of having to make the table of means by using stat_summary(). I can get a similar graph with different line types, but I can't work out how to get the different shapes on each axis tick for each group. I tried the code below and many different permutations of geom_point() and geom_line(), but to no avail. How do I alter the code below to get output that looks like the output derived from the code above?
pline <- ggplot(df, aes(x=session, y=score, group = Group, shape = Group)) +
stat_summary(fun.y="mean", geom="line", size=1.1, aes(linetype=Group, shape = Group)) +
scale_shape_manual(values=c(1:3))
pline
This should help and also clean up the legend:
library(ggplot2)
set.seed(124)
ID <- rep(1:12, times = 3)
Group <- rep(c("A", "B", "C"), times = 12)
score <- rnorm(36, 25, 3)
session <- rep(c("s1","s2", "s3"), each = 12)
df <- data.frame(ID, Group, session, score)
gg <- ggplot(df, aes(x=session, y=score, group = Group, shape = Group))
gg <- gg + stat_summary(fun.y="mean", geom="line", size=1.1,
aes(linetype = Group), show.legend=FALSE)
gg <- gg + stat_summary(fun.y="mean", geom="point", size=5,
aes(shape = Group), fill="white")
gg <- gg + scale_shape_manual(name = "Group", values = c(23, 22, 21))
gg <- gg + theme_bw()
gg <- gg + theme(legend.key=element_blank())
gg
The lines were obscured, so it makes little sense to keep them in the legend. Since you used stat_summary() for the line (vs geom_line() with an embedded stat="summary" it's best to keep the idiom for the point geom as well IMO).

Difference plot

I don't know the name of this type of plot (comments around this are welcomed). Essentially it is a barplot with glyphs that are filled to indicate a loss/gain. The glyph is arrow like encoding information about direction, magnitude, and allowing the bar geom under to be seen.
This looks interesting but can't think of how to do it in ggplot2 (grid frame work). How could we recreate this plot in ggplot2/grid framework (base solutions welcomed as well for completeness of question). Specifically the glyphs, not the text as this is pretty straight forward in ggplot2 already.
Here is some code to create data and traditional overlaid & coordinate flipped dodged bar plots and line graphs to show typical ways of visualizing this type of data.
set.seed(10)
x <- sample(30:60, 12)
y <- jitter(x, 60)
library(ggplot2)
dat <- data.frame(
year = rep(2012:2013, each=12),
month = rep(month.abb, 2),
profit = c(x, y)
)
ggplot() +
geom_bar(data=subset(dat, year==2012), aes(x=month, weight=profit)) +
geom_bar(data=subset(dat, year==2013), aes(x=month, weight=profit), width=.5, fill="red")
ggplot(dat, aes(x=month, fill=factor(year))) +
geom_bar(position="dodge", aes(weight=profit)) +
coord_flip
ggplot(dat, aes(x=month, y=profit, group = year, color=factor(year))) +
geom_line(size=1)
Here is an example, perhaps there are other ways though,
dat <- data.frame(
year = rep(2012:2013, each=12),
month = factor(rep(1:12, 2), labels=month.abb),
profit = c(x, y)
)
dat2 <- reshape2::dcast(dat, month~ year, value.var = "profit")
names(dat2)[2:3] <- paste0("Y", names(dat2)[2:3])
ggplot(dat2) +
geom_bar(aes(x=month, y = Y2012), stat = "identity", fill = "grey80", width = 0.6) +
geom_segment(aes(x=as.numeric(month)-0.4, xend = as.numeric(month)+0.4, y = Y2013, yend = Y2013)) +
geom_segment(aes(x = month, xend = month, y = Y2013, yend = Y2012, colour = Y2013 < Y2012),
arrow = arrow(60, type = "closed", length = unit(0.1, "inches")), size = 1.5) +
theme_bw()

Resources