Related
I am working with the R programming language.
I generated some random data and plotted the following graph:
library(ggplot2)
var_1 = rnorm(1000,20,20)
var_2 = rnorm(1000,20,20)
my_data = data.frame(var_1, var_2)
ggplot(data=my_data, aes(x=var_1, y=var_2)) + geom_point()
I now want to make the following pattern on this graph:
I tried to do this with the following code, but this is the closest I could get:
a1 = ggplot(data=my_data, aes(x=var_1, y=var_2)) +
geom_point()+
geom_hline(yintercept=0, color = "red") +
geom_vline(xintercept=0, color = "red")
a2 = a1 + geom_point() +
geom_hline(yintercept=50, color = "red") +
geom_vline(xintercept=50, color = "red")
My Question: Could someone please show me a "direct" way to make this pattern on this graph? Is there some way to "erase" these extra lines?
Suppose I had a data frame ("my_points") that looked like this:
my_points = data.frame(var_1_point_1 = 0, var_1_point_2 = 50, var_2_point_1 = 0, var_2_point_2 = 50)
Could the graph be made using "my_data", and the lines be made by "referencing" the points in "my_points"? For example, something like this:
a1 = ggplot(data=my_data, aes(x=var_1, y=var_2)) +
geom_point()+
geom_hline(yintercept my_points[1,2], color = "red") +
geom_vline(xintercept=my_points[1,1], color = "red")
Thanks!
You'll need to use geom_segment instead of geom_hline or geom_vline since you'll need to specify xend and yend for each segment.
library(tidyverse)
var_1 = rnorm(1000,20,20)
var_2 = rnorm(1000,20,20)
my_data = data.frame(var_1, var_2)
ggplot(data=my_data, aes(x=var_1, y=var_2)) +
geom_point() +
geom_segment(aes(x = -50, xend = 0, y = 0, yend = 0), color = "red") +
geom_segment(aes(x = 0, xend = 0, y = 0, yend = -50), color = "red") +
geom_segment(aes(x = -50, xend = 50, y = 50, yend = 50), color = "red") +
geom_segment(aes(x = 50, xend = 50, y = 50, yend = -50), color = "red")
Created on 2022-03-21 by the reprex package (v2.0.1)
Update
Since OP wish to use an extra dataframe, here is the updated code:
library(ggplot2)
var_1 = rnorm(1000,20,20)
var_2 = rnorm(1000,20,20)
my_data = data.frame(var_1, var_2)
mypoint <- data.frame(var_1_point_1 = c(-50, 0),
var_1_point_2 = c(0, -50),
var_2_point_1 = c(-50, 50),
var_2_point_2 = c(50, -50))
ggplot(data=my_data, aes(x=var_1, y=var_2)) +
geom_point() +
geom_step(data = mypoint, aes(var_1_point_1, var_1_point_2), color = "red") +
geom_step(data = mypoint, aes(var_2_point_1, var_2_point_2), color = "red")
Created on 2022-03-22 by the reprex package (v2.0.1)
People tend to forget about geom_linerange - in vanilla ggplot sadly only available for vertical lines. But there is also ggstance::geom_linerangeh. Those would allow you to pass a data frame with your x/y coordinates and you will "only" need two geom layers for vertical and for horizontal lines (if your lines always start at the edge of the plot). You could apply the same idea with geom_segment of course, then without need of another package.
library(ggplot2)
library(ggstance)
## changed data frame my points:
x <- y <- c(0, 50)
my_points <- data.frame(x, y)
ggplot() +
geom_point(aes(x = var_1, y = var_2), data = my_data) +
geom_linerange(aes(x = x, ymin = -Inf, ymax = y), data = my_points, color = "red", size = 2) +
geom_linerangeh(aes(xmin = -Inf, xmax = x, y = y), data = my_points, color = "red", size = 2)
Another option would be to make your own stat and use this with geom_segment:
library(ggplot2)
var_1 <- rnorm(1000, 20, 20)
var_2 <- rnorm(1000, 20, 20)
my_data <- data.frame(var_1, var_2)
## changed data frame my points:
x <- y <- c(0, 50)
my_points <- data.frame(x, y)
StatEdge <- ggproto("StatEdge", Stat, compute_group = function(data, scales) {
x <- c(rep(-Inf, nrow(data)), data$x)
y <- c(data$y, rep(-Inf, nrow(data)))
xend <- rep(data$x, nrow(data))
yend <- rep(data$y, nrow(data))
data.frame(x, xend, y, yend)
})
## now you can use the new stat for your geom
ggplot() +
geom_point(aes(x = var_1, y = var_2), data = my_data) +
geom_segment(data = my_points, aes(x, y), stat = "edge", size = 2, color = "red")
Created on 2022-03-21 by the reprex package (v2.0.1)
I made a plot with points connected with a line. In this plot I want to draw a vertical line from a point on the x-axis to the intersection with the plot line.And at the intersection, I want to draw a horizontal line to the Y-axis. I have searched several websites, forums and tutorials, but I still can't do it. Any help?
library(ggplot2)
X <- 1:5
Y <- c(2, 6, 4, 7, 12)
DF <- data.frame(X, Y)
ggplot(data = DF,
aes(x = X,
y = Y)) +
geom_point() +
geom_line() +
geom_vline(xintercept = 4.5,
linetype = 2)
Result so far:
Example of desired result:
Already commented by #Eric but also sort of answered by #akrun in link, by applyng the apply function to the function of #akrun you can also plot all the points of the DF, something like this would work for you:
library(ggplot2)
X <- 1:5
Y <- c(2, 6, 4, 7, 12)
DF <- data.frame(X, Y)
draw_guides<- function(x, y) {
list(geom_segment(aes(x = -Inf, xend = x, y = y, yend = y), linetype = "dashed"),
geom_segment(aes(x = x, xend = x, y = y, yend = -Inf), linetype = "dashed"))
}
ggplot(data = DF,
aes(x = X,
y = Y)) +
geom_point() +
geom_line() +
apply(DF, 1, function(y) draw_guides(y[1], y[2]))
As already mentioned by #Eric in his comment geom_segment is the way to go to achieve your desired result. Moreover, you have to manually compute the y value where the segments should cut the geom_line which could be achieved using approx. As quick approach may look like so:
library(ggplot2)
X <- 1:5
Y <- c(2, 6, 4, 7, 12)
DF <- data.frame(X, Y)
# vertical line
vsegment <- function(x, X, Y) {
geom_segment(aes(x = x, xend = x, y = -Inf, yend = approx(X, Y, x)$y),
linetype = 2)
}
# horizontal line
hsegment <- function(x, X, Y) {
geom_segment(aes(x = -Inf, xend = x, y = approx(X, Y, x)$y, yend = approx(X, Y, x)$y),
linetype = 2)
}
ggplot(data = DF,
aes(x = X,
y = Y)) +
geom_point() +
geom_line() +
vsegment(4.5, X, Y) +
hsegment(4.5, X, Y)
You can use geom_path() as well for this
X <- 1:5
Y <- c(2, 6, 4, 7, 12)
DF <- data.frame(X, Y)
ggplot(data = DF, aes(x = X, y = Y)) +
geom_point() +
geom_line() +
geom_path(data = data.frame(x = c(-Inf, 4.5, 4.5), y = c(approx(X, Y, 4.5)$y, approx(X, Y, 4.5)$y, -Inf)), aes(x, y), color = "red", linetype = 2)
If you want it more flexible for more intercepts you can use this function.
Note the ... part, so you can pass the geom_path arguments along, like color, linetype, size, etc. It supports an intercept based on the x value or based on the y value.
my_intercept <- function(x, y, ...) {
if (!missing(x)) dt <- data.frame(x = c(-Inf, x, x), y = c(approx(X, Y, x)$y, approx(X, Y, x)$y, -Inf))
if (!missing(y)) dt <- data.frame(x = c(-Inf, approx(Y, X, y)$y, approx(Y, X, y)$y), y = c(y, y, -Inf))
geom_path(data = dt, aes(x, y), ...)
}
ggplot(data = DF, aes(x = X, y = Y)) +
geom_point() +
geom_line() +
my_intercept(x = 4.5, color = "blue", linetype = 2) +
my_intercept(y = 5, color = "red", linetype = 4)
I am trying to generate a dumbbell plot in ggplot, while also trying to log transform the x and y axes. System throws an error that I can't understand. Looking for some help.
Here is the sample code:
#create the data
df <- data.frame(x = c(1, 2, 3, 100),
xend = c(2, 4, 6, 110),
y = c(1, 2, 3, 100))
#plot the untransformed dumbbell plot
library('ggalt')
ggplot(df, aes(x = x, xend = xend, y = y)) +
geom_dumbbell()
#Try the plot with coordinate transformation
ggplot(df, aes(x = x, xend = xend, y = y)) +
geom_dumbbell() +
coord_trans(x = 'log2', y = 'log2')
Throws error:
Error in [.data.frame(df, , c("alpha", "colour", "size", "linetype")) :
undefined columns selected
If I amend coord_trans so that coord_trans(x = 'log2', xend = 'log2', y = 'log2), I get the error:
Error in coord_trans(x = "log2", xend = "log2", y = "log2") :
unused argument (xend = "log2")
What I want is the equivalent of this, with geom_dumbbell() rather than geom_point():
ggplot(df, aes(x = x, y = y)) +
geom_point() +
coord_trans(x = 'log2', y = 'log2')
Any thoughts on how I can get geom_dumbbell() to work with coord_trans()?
That is weird, I don't know why it doesn't work with geom_dumbbell. I also didn't know that geom_dumbbell exists! So here is a hack I've been doing for years using geom_linerange and geom_point to build the components:
ggplot(df, aes(x=x, y = y)) +
geom_linerange(aes(xmin=x, xmax=xend)) +
geom_point() +
geom_point(aes(x=xend)) +
coord_trans(x = 'log2', y = 'log2')
I have a boxplot and by my supervisor's advice I have to indicate the mean, outliers and median in the legend, like this image:
How can I do this using ggplot2?
library(ggplot2)
A <- 1:20
DF <- data.frame(A)
ggplot(data = DF) +
geom_boxplot(aes(x = "", y = A))
There is no straightforward way. But you could make a custom legend using another plot:
p <- ggplot(mtcars) +
geom_boxplot(aes(x = factor(cyl), y = mpg))
d1 <- data.frame(x = 1, y = c(1:1000, 1502))
d2 <- data.frame(
y = c(boxplot.stats(d1$y)$stats, 1502),
x = 1,
label = c('min', '1st quartile', 'median', '3rd quartile', 'max', 'outlier')
)
leg <- ggplot(d1, aes(x, y)) + geom_boxplot(width = 0.2) +
geom_text(aes(x = 1.15, label = label), d2, hjust = 0) +
xlim(0.9, 1.5) +
theme_void() + theme(panel.background = element_rect(fill = 'white', color = 1))
p + annotation_custom(ggplotGrob(leg), xmin = 3, xmax = 3.5, ymin = 25, ymax = 35)
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")