Q1.Is there a way of avoiding the following behavior in a ggplot?
x=c(1,3,4,5,6)
y=c(0.5,2,3,7,1)
n=2
library(ggplot2)
p <- ggplot(mtcars, aes(wt, mpg))
p <-p + geom_segment(aes(x = x[1], y = y[1], xend = x[2], yend = y[2]), colour = "red")
p <-p + geom_segment(aes(x = x[2], y = y[2], xend = x[3], yend = y[3]), colour = "red")
p
x[1]=10
p
The drawing on the plot remains anchored to the value of the numeric values given in input. Do I have to create other variables for storing the coordinates?
Q2.How to draw a polygonal chain in ggplot?
n=length(x)-1
library(ggplot2)
p <- ggplot(mtcars, aes(wt, mpg))
for (i in 1:n){
p <-p + geom_segment(aes(x = x[i], y = y[i], xend = x[i+1], yend = y[i+1]), colour = "red")
p$plot_env <- list2env(list(x=x,y=y))
}
Answer here: Drawing polygonal chains in ggplot
This seems like a hack but apparently works: before modifying x, do
p$plot_env <- list2env(list(x=x,y=y))
Then
x[1] <- 10
p
leaves the plot unchanged.
Related
I am trying to highlight a specific point in a distribution. I am using geom_vline which works fine except that it extends beyond the curve drawn by geom_density. Is there any way to cut that vertical line off a the point it meets the curve drawn by geom_density?
library(ggplot2)
mtcars$car <- rownames(mtcars)
javelin <- mtcars[mtcars$car == "AMC Javelin", ]
ggplot(mtcars) +
geom_density(aes(x = mpg)) +
geom_vline(data = javelin, aes(xintercept = mpg))
You can't use geom_vline here. You'll have to calculate the correct point and use geom_segment, but this really isn't that complex:
ggplot(mtcars) +
geom_density(aes(x = mpg)) +
geom_segment(data = as.data.frame(density(mtcars$mpg)[1:2]) %>%
filter(seq(nrow(.)) == which.min(abs(x - javelin$mpg))),
aes(x, 0, xend = x, yend = y))
If you want this to be easily generalised, you can define a little helper function:
geom_vdensity <- function(data, at, ...) {
ggplot2::geom_segment(
data = dplyr::filter(as.data.frame(density(data)[1:2]),
seq_along(x) == which.min(abs(x - at))),
ggplot2::aes(x, 0, xend = x, yend = y), ...)
}
This allows:
ggplot(mtcars) +
geom_density(aes(x = mpg)) +
geom_vdensity(data = mtcars$mpg, at = javelin$mpg, color = "red")
and
ggplot(iris) +
geom_density(aes(x = Petal.Length)) +
geom_vdensity(data = iris$Petal.Length, at = 4)
I first make a plot
df <- data.frame(x = c(1:40, rep(1:20, 3), 15:40))
p <- ggplot(df, aes(x=x, y = x)) +
stat_density2d(aes(fill='red',alpha=..level..),geom='polygon', show.legend = F)
Then I want to change the geom_density values and use these in another plot.
# build plot
q <- ggplot_build(p)
# Change density
dens <- q$data[[1]]
dens$y <- dens$y - dens$x
Build the other plot using the changed densities, something like this:
# Built another plot
ggplot(df, aes(x=x, y =1)) +
geom_point(alpha = 0.3) +
geom_density2d(dens)
This does not work however is there a way of doing this?
EDIT: doing it when there are multiple groups:
df <- data.frame(x = c(1:40, rep(1:20, 3), 15:40), group = c(rep('A',40), rep('B',60), rep('C',26)))
p <- ggplot(df, aes(x=x, y = x)) +
stat_density2d(aes(fill=group,alpha=..level..),geom='polygon', show.legend = F)
q <- ggplot_build(p)
dens <- q$data[[1]]
dens$y <- dens$y - dens$x
ggplot(df, aes(x=x, y =1)) +
geom_point(aes(col = group), alpha = 0.3) +
geom_polygon(data = dens, aes(x, y, fill = fill, group = piece, alpha = alpha)) +
scale_alpha_identity() +
guides(fill = F, alpha = F)
Results when applied to my own dataset
Although this is exactly what I'm looking for the fill colors seem not to correspond to the initial colors (linked to A, B and C):
Like this? It is possible to plot a transformation of the shapes plotted by geom_density. But that's not quite the same as manipulating the underlying density...
ggplot(df, aes(x=x, y =1)) +
geom_point(alpha = 0.3) +
geom_polygon(data = dens, aes(x, y, fill = fill, group = piece, alpha = alpha)) +
scale_alpha_identity() +
guides(fill = F, alpha = F)
Edit - OP now has multiple groups. We can plot those with the code below, which produces an artistic plot of questionably utility. It does what you propose, but I would suggest it would be more fruitful to transform the underlying data and summarize that, if you are looking for representative output.
ggplot(df, aes(x=x, y =1)) +
geom_point(aes(col = group), alpha = 0.3) +
geom_polygon(data = dens, aes(x, y, fill = group, group = piece, alpha = alpha)) +
scale_alpha_identity() +
guides(fill = F, alpha = F) +
theme_minimal()
I want to overlay two plots: one is a simple point plot where a variable is used to control the dot size; and another is a simple curve.
Here is a dummy example for the first plot;
library(ggplot2)
x <- seq(from = 1, to = 10, by = 1)
df = data.frame(x=x, y=x^2, v=2*x)
ggplot(df, aes(x, y, size = v)) + geom_point() + theme_classic() + scale_size("blabla")
Now lets overlay a curve to this plot with data from another dataframe:
df2 = data.frame(x=x, y=x^2-x+2)
ggplot(df, aes(x, y, size = v)) + geom_point() + theme_classic() + scale_size("blabla") + geom_line(data=df2, aes(x, y), color = "blue") + scale_color_discrete(name = "other", labels = c("nanana"))
It produces the error:
Error in FUN(X[[i]], ...) : object 'v' not found
The value in v is not used to draw the intended curse, but anyway, I added a dummy v to df2.
df2 = data.frame(x=x, y=x^2-x+2, v=replicate(length(x),0)) # add a dummy v
ggplot(df, aes(x, y, size = v)) + geom_point() + theme_classic() + scale_size("blabla") + geom_line(data=df2, aes(x, y), color = "blue") + scale_color_discrete(name = "other", labels = c("nanana"))
An the result has a messed legend:
What is the right way to achieve the desired plot?
You can put the size aes in the geom_point() call to make it so that you don't need the dummy v in df2.
Not sure exactly what you want regarding the legend. If you replace the above, then the blue portion goes away. If you want to have a legend for the line color, then you have to place color inside the geom_line aes call.
x <- seq(from = 1, to = 10, by = 1)
df = data.frame(x=x, y=x^2, v=2*x)
df2 = data.frame(x=x, y=x^2-x+2)
ggplot(df, aes(x, y)) +
geom_point(aes(size = v)) +
theme_classic() +
scale_size("blabla") +
geom_line(data=df2, aes(x, y, color = "blue")) +
scale_color_manual(values = "blue", labels = "nanana", name = "other")
I'm trying to fill slices (x-axis) of the area under a curve in different colors using ggplot's geom_area. But I somehow can't get the sides of the areas to be vertical. Here's a minimal reproducible example:
library(ggplot2)
x = 1:10
pdat = data.frame(y = log(x), x = x)
ggplot(pdat, aes(x=x, y=y)) +
geom_area(aes(y = ifelse(y > 2 & y < 5, y, 0)),
fill = "red", alpha = 0.5) +
geom_line()
Thanks for your suggestions!
The problem is that for x = 7 the y-value is now 0 but for x = 8 the y-value is 2.0794415 and so the area in between is interpolated.
You can instead use a subset of pdat for geom_area:
ggplot() +
geom_area(data = pdat[pdat$y > 2 & pdat$y < 5,], aes(x = x, y = y),
fill = "red", alpha = 0.5) +
geom_line(data = pdat, aes(x = x, y = y))
I am using the ggplot function to plot this kind of graph
image
I want to add the specific value of the x-axis as shown in the picture
this is my code :
quantiles <- quantile(mat,prob = quant)
x <- as.vector(mat)
d <- as.data.frame(x=x)
p <- ggplot(data = d,aes(x=x)) + theme_bw() +
geom_histogram(aes(y = ..density..), binwidth=0.001,color="black",fill="white") +
geom_density(aes(x=x, y = ..density..),fill="blue", alpha=0.5, color = 'black')
x.dens <- density(x)
df.dens <- data.frame(x = x.dens$x, y = x.dens$y)
p <- p + geom_area(data = subset(df.dens, x <= quantiles), aes(x=x,y=y),
fill = 'green', alpha=0.6)
print(p)