This question already has answers here:
Plot two graphs in same plot in R
(17 answers)
Plotting two variables as lines using ggplot2 on the same graph
(5 answers)
Closed 3 years ago.
I want to show graphically how the summation of two different sin curves looks like.
So, I am trying to make a single graph that shows two different sin function and their sum. So, three curves on one graph.
How can I do it with ggplot layers?
I am defing two sin functions (y and z)
x <- seq(0, 16*pi, 0.01)
y <- 2*sin(3*(x-1))
z <- sin(x)
summing up the two curves:
t <- y + z
I can see the three separately with:
plot(x,y,type="l")
plot(x,z,type="l")
plot(x,t,type="l")
But how can I plot the three functions?
I tried this but it does not work
ggplot(x,
qplot(y,x,geom="path", xlab="time", ylab="Sine wave") +
qplot(z,x,geom="path", xlab="time", ylab="Sine wave"))
Store everything in a data.frame, reshape from wide to long, and plot:
library(tidyverse)
data.frame(x = x, y = y, z = z, t = y + z) %>%
pivot_longer(-x) %>%
ggplot(aes(x, value, colour = name)) +
geom_line()
Sample data
x <- seq(0, 16*pi, 0.01)
y <- 2*sin(3*(x-1))
z <- sin(x)
Related
I'm sure this can be done by separately collecting all the data and then just using ggplot for the plotting, but I'd really prefer a simpler solution implementing ggplot, particulalry stat_ecdf() because of easier access to grouping variables, facets, etc.
My dataframe contains, amongst others, two columns of corresponding data x and y. I'd like to plot the ecdf of y on an axis of the corresponding x values. In other words, I'd like to plot what cumulative portion of the y variable is reached at its corresponding x value. While x and y are correlated (both descending), they are not analytically connected, so I cannot simply scale values of y to x. My attempts to do this with separate calculations of the ecdf functions of each subset have gotten extremely messy and complicated, while the stat_ecdf function seems to be very close to getting me what I need.
If I set the x variable in the ggplot aes to x and then set the variable within stat_ecdf to y, I am able to get the ecdf of y with axis labels of x; however, the actual values on the axis correspond to x. I'm plotting This is done with something like:
ggplot(df, aes(x, color=group_var)) + stat_ecdf(aes(y))
EDIT:
To visualize this:
This sample plot
shows the ecdf of x for multiple groups. Each x value has a corresponding y value in a sorted dataframe (approximate relationship, ignore the decreasing regions at the end. I would like to have a similar plot where the horizontal axis is in the corresponding y values. Basically, I need to map the horizontal axis of the first ecdf plot from x->y as simply as possible. I could do this manually by adding ecdf values as a column in the dataframe, but I am looking to do it within ggplot for simplicity, if possible.
Instead of trying to bend stat_ecdf to do something it was not designed for, it's better to be explicit about your intention in the code.
It's quite straightforward. The most weird piece of code: ecdf(y)(y) menas 'calculate the empirical CDF for y, and then evaluate it for the actual values of y in my data. The cummax deals with the decreasing y, to get ever increasing eCDF along x.
d_sample %>%
group_by(group) %>%
arrange(group, x) %>%
mutate(
fraction = ecdf(y)(y),
maxf = pmax(fraction, cummax(fraction))) %>%
ggplot(aes(x, maxf)) +
geom_point() +
facet_wrap(~group)
I'm still not really sure if that's what you need.
Sample data
To be honest it took me most of the time to 'fake' your dataset:
library(tidyverse)
tibble(x = seq_len(300) + 100) %>%
mutate(
one = - 1e-3 * (x * x) + 50 + 0.7 * x,
two = - 1e-3 * (x * x) + 55 + 0.68 * x,
three = - 1e-3 * (x * x) + 110 + 0.5 * x,
four = - 1e-3 * (x * x) + 10 + 0.8 * x) %>%
pivot_longer(-x, names_to = "group", values_to = "y") %>%
filter(
group == "one"
| group == "two"
| (group == "three" & x < 200)
| (group == "four" & x > 250)) ->
d_sample
d_sample %>%
ggplot(aes(x, y, colour = group)) +
geom_point()
This question already has answers here:
ggplot2 line chart gives "geom_path: Each group consist of only one observation. Do you need to adjust the group aesthetic?"
(6 answers)
Closed 12 months ago.
The community reviewed whether to reopen this question 12 months ago and left it closed:
Original close reason(s) were not resolved
library(ggplot2)
x=letters[1:3]
y=1:3
qplot(x, y)
qplot(x, y, geom=c('point', 'line'))
geom_path: Each group consists of only one observation. Do you need to adjust
the group aesthetic?
I want to connect lines between the points. But when the x is a string, the above commands won't work. It works when the x is numeric. I'd think qplot should be made more user-friendly in this case.
How to make it connect the points with lines when x is a string?
One solution is provided by #stefan. Another one could be the following.
Sample data:
x=letters[1:3]
y=1:3
Sample code:
d <- data.frame(x, y) %>%
mutate(x = x %>%
factor(levels = x))
library(ggplot2)
ggplot(data = d, aes(x = x, y = y, group = 1)) +
geom_line() +
scale_x_discrete(labels = x, breaks = x)
Plot:
This question already has answers here:
How to plot a function curve in R
(7 answers)
Closed 3 years ago.
With R, how do I plot simple linear equations as lines on a plane? For example, how to plot line of the equation -2x + y = 0?
I did searched google but not got an answer.
Thanks!
Although a duplicate here is a quick answer.
If one were to do this in excel, one would create 2 columns, 1 with x values and 1 with the corrosponding y values. For your situation the equation is equivalent to y = 2x. As such plotting can be by either calculating a range of values and plotting this as one would in excel.
Alternatively one can create a function and plot the function over an interval. Both methods are shown below.
#method one
x <- seq(from = 0, to = 10)
y <- 2 * x
plot(y = y, x = x, xlab = "x", ylab = "y") #add type = 'l' for a line rather than a dot plot.
#method two
y <- function(x) 2 *x
plot(y, from = 0, to = 10)
I wish to compare the observed values to the fitted ones. To do so, I decided to use a plot in R. What I want to do is to plot X vs Y and X vs Y.fitted on the same plot. I have written some code, but it is incomplete. My plot needs to look like this one below. On the plot, circles and crosses represent the observed and fitted values respectively
set.seed(1)
x <- runif(8,0,1)
y <- runif(8,0,1)
y.fitted <- runif(8,0,1)
plot(x,y,pch=1)
plot(x,y.fitted,pch=5)
In your code, the second plot will not add points to the existing plot but create a new one. You can + use the function points to add points to the existing plot.
plot(x, y, pch = 1)
points(x, y.fitted, pch = 4)
running plot the second time will create a new one. You could use points
set.seed(1)
x <- runif(8,0,1)
y <- runif(8,0,1)
y.fitted <- runif(8,0,1)
plot(x,y,pch=1)
points(x,y.fitted,pch=5)
A solution with ggplot2 giving a better and neat graph outlook:
library(ggplot2)
df = data.frame(x=runif(8,0,1),y=runif(8,0,1),y.fitted=runif(8,0,1))
df = melt(df, id=c('x'))
ggplot() + geom_point(aes(x=x,y=value, shape=variable, colour=variable), df)
How do I plot the equivalent of contour (base R) with ggplot2? Below is an example with linear discriminant function analysis:
require(MASS)
iris.lda<-lda(Species ~ Sepal.Length + Sepal.Width + Petal.Length + Petal.Width, data = iris)
datPred<-data.frame(Species=predict(iris.lda)$class,predict(iris.lda)$x) #create data.frame
#Base R plot
eqscplot(datPred[,2],datPred[,3],pch=as.double(datPred[,1]),col=as.double(datPred[,1])+1)
#Create decision boundaries
iris.lda2 <- lda(datPred[,2:3], datPred[,1])
x <- seq(min(datPred[,2]), max(datPred[,2]), length.out=30)
y <- seq(min(datPred[,3]), max(datPred[,3]), length.out=30)
Xcon <- matrix(c(rep(x,length(y)),
rep(y, rep(length(x), length(y)))),,2) #Set all possible pairs of x and y on a grid
iris.pr1 <- predict(iris.lda2, Xcon)$post[, c("setosa","versicolor")] %*% c(1,1) #posterior probabilities of a point belonging to each class
contour(x, y, matrix(iris.pr1, length(x), length(y)),
levels=0.5, add=T, lty=3,method="simple") #Plot contour lines in the base R plot
iris.pr2 <- predict(iris.lda2, Xcon)$post[, c("virginica","setosa")] %*% c(1,1)
contour(x, y, matrix(iris.pr2, length(x), length(y)),
levels=0.5, add=T, lty=3,method="simple")
#Eqivalent plot with ggplot2 but without decision boundaries
ggplot(datPred, aes(x=LD1, y=LD2, col=Species) ) +
geom_point(size = 3, aes(pch = Species))
It is not possible to use a matrix when plotting contour lines with ggplot. The matrix can be rearranged to a data-frame using melt. In the data-frame below the probability values from iris.pr1 are displayed in the first column along with the x and y coordinates in the following two columns. The x and y coordinates form a grid of 30 x 30 points.
df <- transform(melt(matrix(iris.pr1, length(x), length(y))), x=x[X1], y=y[X2])[,-c(1,2)]
I would like to plot the coordinates (preferably connected by a smoothed curve) where the posterior probabilities are 0.5 (i.e. the decision boundaries).
You can use geom_contour in ggplot to achieve a similar effect. As you correctly assumed, you do have to transform your data. I ended up just doing
pr<-data.frame(x=rep(x, length(y)), y=rep(y, each=length(x)),
z1=as.vector(iris.pr1), z2=as.vector(iris.pr2))
And then you can pass that data.frame to the geom_contour and specify you want the breaks at 0.5 with
ggplot(datPred, aes(x=LD1, y=LD2) ) +
geom_point(size = 3, aes(pch = Species, col=Species)) +
geom_contour(data=pr, aes(x=x, y=y, z=z1), breaks=c(0,.5)) +
geom_contour(data=pr, aes(x=x, y=y, z=z2), breaks=c(0,.5))
and that gives
The partimat function in the klaR library does what you want for observed predictors, but if you want the same for the LDA projections, you can build a data frame augmenting the original with the LD1...LDk projections, then call partimat with formula Group~LD1+...+LDk, method='lda' - then you see the "LD-plane" that you intended to see, nicely partitioned for you. This seemed easier to me, at least to explain to students newer to R, since I'm just reusing a function already provided in a way in which it wasn't quite intended.