How to adjust the height of each geom_line depending on the facet group (y-lims differ depending on the group, see image below)?
I tried to build a custom data.frame which contains heights for each condition but this is not accepted by geom_line.
I have this little working example:
carData <- mtcars
carData$cyl <- factor(carData$cyl)
maxval <- max(carData$mpg)
maxval <- maxval * 1.1
lowval <- maxval - maxval * 0.02
txtval <- maxval * 1.04
llev <- "4"
rlev <- "6"
lpos <- which(levels(carData$cyl) == llev)
rpos <- which(levels(carData$cyl) == rlev)
mpos <- (lpos + rpos) / 2
df1 <- data.frame(a = c(lpos,lpos,rpos,rpos), b = c(lowval, maxval, maxval, lowval))
p <- ggplot(carData, aes(cyl, mpg))
p <- p + geom_boxplot()
p <- p + geom_line(data = df1, aes(x = a, y = b)) + annotate("text", x = mpos, y = txtval, label = "3.0")
p <- p + facet_wrap( ~ gear,ncol=2,scales="free")
You need to capture the variable you are using to facet with, in your summary data.frame. We could capture group wise maxima and use them for the y positions of the geom_segment() and geom_text:
library(tidyverse)
# get the max for each gear facet
df2 <- carData %>% group_by(gear) %>%
summarise(ypos = max(mpg)*1.1) %>%
mutate(x = lpos, xend = rpos) # use your factor level locators
p <- ggplot(carData, aes(cyl, mpg)) +
geom_boxplot() +
geom_segment(data = df2, aes(y = ypos, yend = ypos, x = x, xend = xend)) +
geom_text(data = df2, aes(y = ypos*1.02, x = mean(c(x, xend))), label = "3.0") +
facet_wrap( ~ gear,ncol=2, scales="free")
# if you want the end ticks
p + geom_segment(data = df2, aes(y = ypos, yend = ypos * .99, x = x, xend = x)) +
geom_segment(data = df2, aes(y = ypos, yend = ypos *.99, x = xend, xend = xend))
Related
I have the following script I'm working on, I want to re order the bar graph in descending order by their values.
library(tidyverse)
library(lubridate)
library(ggplot2)
#df <- read_csv('dataframe.csv')
df %>%
mutate(date=mdy(date), year=year(date), year = year + (date >= mdy(paste0("10/01/", year))))%>%
group_by(year) %>%
summarize(avg = mean(flow)) -> df
y <- df$avg
x <- ymd(sprintf("%d-01-01",df$year))
d <- data.frame(x = x, y = y)
# interpolate values from zero to y and create corresponding number of x values
vals <- lapply(d$y, function(y) seq(0, y, by = 0.1))
y <- unlist(vals)
mid <- rep(d$x, lengths(vals))
d2 <- data.frame(x = mid - 100,
xend = mid + 100,
y = y,
yend = y)
ggplot(data = d2, aes(x = x, xend = xend, y = y, yend = yend, color = y)) +
geom_segment(size = 2)
Results
I want to reorder the bars in descending order by values
The dataset can be found through the following link
https://drive.google.com/file/d/11PVub9avzMFhUz02cHfceGh9DrlVQDbD/view?usp=sharing
the output I'm looking for is like this.
Kindly assist.
To arrange the data you need to adjust the factor levels. You could arrange the data based on avg column and change year to factor.
library(dplyr)
library(ggplot2)
df %>%
arrange(desc(avg)) %>%
mutate(year = factor(year, unique(year))) %>%
ggplot() + aes(year, avg) + geom_col(aes(fill = 'red')) + guides(fill=FALSE)
Or :
df %>%
arrange(desc(avg)) %>%
mutate(year = factor(year, unique(year))) %>%
ggplot() + aes(year, avg, fill = avg) + geom_col()
Try this:
library(scales)
#Custom Transform function
dttrans <- function(a, b, breaks = b$breaks, format = b$format) {
a <- as.trans(a)
b <- as.trans(b)
name <- paste(a$name, b$name, sep = "-")
trans <- function(x) a$trans(b$trans(x))
inv <- function(x) b$inverse(a$inverse(x))
trans_new(name, trans, inv, breaks, format = format)
}
ggplot(data = d2, aes(x = x, xend = xend, y = y, yend = yend, color = y)) +
geom_segment(size = 2) +
scale_x_continuous(trans = dttrans("reverse", "date"))
Credits: Mikko Marttila
I'm trying to create a boxplot using ggplot2 with :
X as a continuous variable
Colors for different groups
Here is an example :
x <- sample(c(1,2,5),300,replace = TRUE)
y <- sapply(x,function(mu) rnorm(1,mean = mu))
color <- sample(c("color 1","color 2"),300,replace = TRUE)
data <- data.frame(x, y, color)
I can either have colors and x as a factor :
ggplot(data = data) + geom_boxplot(aes(x = factor(x),y = y,col = color))
or x as a continuous variable and no colors :
ggplot(data = data) + geom_boxplot(aes(x = x,y = y,group = x))
But not both.
Does somebody know how to do this ?
Thanks
I think you need one more column for group, which is the combination of color and x. For example, how about simply paste()ing them?
set.seed(1)
x <- sample(c(1,2,5),300,replace = TRUE)
y <- sapply(x,function(mu) rnorm(1,mean = mu))
color <- sample(c("color 1","color 2"),300,replace = TRUE)
data <- data.frame(x, y, color)
library(ggplot2)
ggplot(data = data) +
geom_boxplot(aes(x = x, y = y, col = color, group = paste(color, x)))
You can use scales to change the x-axis scale.
library(ggplot2)
library(scales)
x <- sample(c(1,2,5),300,replace = TRUE)
y <- sapply(x,function(mu) rnorm(1,mean = mu))
color <- sample(c("color 1","color 2"),300,replace = TRUE)
data <- data.frame(x, y, color)
ggplot(data = data) + geom_boxplot(aes(x = factor(x),y = y,col = color)) + scale_x_discrete(limit = c('1','2','3','4','5'))
Hack for dynamic limits:
min = min(data$x)
max = max(data$x)
limits <- as.character(seq(min:max))
ggplot(data = data) + geom_boxplot(aes(x = factor(x),y = y,col = color)) + scale_x_discrete(limit = limits)
You could misuse the fill aesthetic:
ggplot(data = data) +
geom_boxplot(aes(x = x, y = y, col = color, fill = factor(x))) +
scale_fill_manual(values = rep(NA, 3), guide = "none")
I want to produce a scatter plot and mean value with error bars. My code is as follows. When I add the geom_errorbar(), there is an error message:
Error in FUN(X[[i]], ...) : object 'value' not found
Z <- c(.1,.5,1.)
T <- seq(1:10)
ZT <- expand.grid(Z,T)
colnames(ZT) <- c("Z","T")
n <- nrow(ZT)
nrep <- 100
rmat <- replicate(nrep, rnorm(n))
ave <- apply(rmat,1,mean)
var <- apply(rmat,1,var)
se <- sqrt(var)/sqrt(nrep)
rmat.summary <- as.data.frame(cbind(ZT,ave,se))
colnames(rmat.summary) <- c("Z","T","ave","se")
library(reshape)
library(ggplot2)
rmat <- as.data.frame(cbind(ZT,rmat))
rmat <- melt(as.data.frame(rmat),id=c(1,2))
ggplot(rmat, aes(x = T, y = value)) + geom_point() + geom_line(data =
rmat.summary, aes(x = T, y = ave)) + facet_wrap( ~ Z)
ggplot(rmat, aes(x = T, y = value)) + geom_point() + geom_line(data =
rmat.summary, aes(x = T, y = ave)) +
geom_errorbar(data = rmat.summary, aes(ymin = ave - se, ymax = ave + se))
+ facet_wrap( ~ Z)
So can anybody please help me to correct this error? Thanks in advance!
This should work:
ggplot() +
geom_point(data = rmat, aes(x = T, y = value)) +
geom_line(data = rmat.summary, aes(x = T, y = ave)) +
geom_errorbar(data = rmat.summary, aes(x = T, y = ave, ymin = ave - se, ymax = ave + se)) +
facet_wrap( ~ Z)
But I think you have to play around with ymin and ymax.
I have a ggplot graph defined like this:
x <- seq(0, 10, by = 0.1)
y1 <- cos(x)
y2 <- sin(x)
df1 <- data.frame(x = x, y = y1, type = "sin", id = 1)
df2 <- data.frame(x = x, y = y2, type = "cos", id = 2)
df3 <- data.frame(x = 2, y = 0.5, type = "constant", id = 3)
df4 <- data.frame(x = 4, y = 0.2, type = "constant", id = 4)
combined <- rbind(df1, df2, df3, df4)
ggplot(combined, aes(x, y, colour = interaction(type, id))) + geom_line() +
geom_point(data = subset(combined, type == "constant"))
This works very well as illustrated below:
Now I would like to extract the interaction in a variable to reuse it later (e.g. customize the legend style or labels).
I did that in a very naïve way:
my.interaction <- interaction(combined$type, combined$id)
ggplot(combined, aes(x, y, colour = my.interaction)) + geom_line() +
geom_point(data = subset(combined, type == "constant"))
But then I have an error:
Error: Aesthetics must be either length 1 or the same as the data (2):
x, y, colour
Edit:
Here is the kind of manipulation I could do: edit the linetype of the legend
displayed <- levels(factor(my.interaction))
line.style <- rep(1, length.out = length(displayed))
line.style[grep("constant", displayed)] <- 0
That works:
ggplot(combined, aes(x, y, colour = interaction(type, id))) + geom_line() +
geom_point(data = subset(combined, type == "constant")) +
guides(colour=guide_legend(override.aes=list(linetype = line.style)))
That does not:
ggplot(combined, aes(x, y, colour = my.interation) + geom_line() +
geom_point(data = subset(combined, type == "constant")) +
guides(colour=guide_legend(override.aes=list(linetype = line.style)))
In the end, I could also edit the shapes or the legend labels (e.g. "Id: 1 / Type: sin" or any other advanced transformation of the labels based on the interaction values).
This'll work. What's wrong with adding a column to your data frame?
combined %>% mutate(my.interaction = paste(type, id, sep='.')) %>%
ggplot(aes(x, y, colour = my.interaction)) + geom_line() +
geom_point(data = subset(combined, type == "constant"))
I created a plot with several geom_area according to the following code :
library(ggplot2)
set.seed(1)
dat <- data.frame(matrix(rnorm(100, 10, 2), 100, 1))
dat_density <- data.frame(density(dat[, 1])[c("x", "y")])
quant <- quantile(dat[, 1], probs = seq(0, 1, 0.10))
library(RColorBrewer)
color_pal <- brewer.pal(length(quant)-1, "RdYlBu")
dens <- ggplot(data = dat_density, aes(x = x, y = y)) +
geom_line(size = 2)
for(i in 1:(length(color_pal))){
dens <- dens +
geom_area(data = subset(dat_density, x > quant[[i]] & x < quant[[i + 1]]), fill = color_pal[i])
}
dens
How can I add a common legend with each color of the color_pal vector (corresponding to all the 10% area of data) ?
The easiest way is to define the groups in your dataset
dat_density$quant <- cut(dat_density$x, breaks = c(-Inf, quant, Inf))
ggplot(data = dat_density, aes(x = x, y = y, fill = quant)) +
geom_line(size = 2) +
geom_area() +
scale_fill_brewer(palette = "RdYlBu")