Multiple curves in ggplot2 with same independent variable - r

I have a sequence of points in the x-axis for each of which there are two points in the y-axis.
x<-seq(8.5,10,by=0.1)
y<-c(0.9990276914, 0.9973015358, 0.9931704801, 0.9842176288, 0.9666471511, 0.9354201700, 0.8851624615, 0.8119131899, 0.7152339504, 0.5996777045, 0.4745986612, 0.3519940258, 0.2431610835, 0.1556738744, 0.0919857178, 0.0500000000, 0.0249347645, 0.0113838852, 0.0047497169, 0.0018085048, 0.0006276833)
y1<-c(9.999998e-01,9.999980e-01,9.999847e-01,9.999011e-01,9.994707e-01,9.976528e-01,9.913453e-01, 9.733730e-01, 9.313130e-01, 8.504646e-01, 7.228116e-01, 5.572501e-01,3.808638e-01,2.264990e-01, 1.155286e-01, 5.000000e-02, 1.821625e-02, 5.554031e-03, 1.410980e-03, 2.976926e-04, 5.203069e-05)
I would now like to create two curves in ggplot2. This is quite easy to accomplish in the normal way in R. The result is in the plot below. I am not sure, however, how to do that in ggplot2. For just one curve, I can use
library(ggplot2)
p<-qplot(x,y,geom="line")
Could you please help me generalise the above? Any help is greatly appreciated, thank you.

Note that the lengths of your x and y values don't match. Combine your data and use a grouping variable:
x<-seq(8.5,10, length.out = 21)
DF <- data.frame(x=rep(x, 2), y=c(y, y1), g=c(y^0, y1^0*2))
library(ggplot2)
ggplot(DF, aes(x=x, y=y, colour=factor(g), linetype=factor(g))) +
geom_line()

As #Roland also pointed out first you should fix the length of x. A possible solution using the reshape2 package:
library(reshape2)
library(ggplot2)
x<-seq(8.5,10,length.out = 21)
y<-c(0.9990276914, 0.9973015358, 0.9931704801, 0.9842176288, 0.9666471511, 0.9354201700, 0.8851624615, 0.8119131899, 0.7152339504, 0.5996777045, 0.4745986612, 0.3519940258, 0.2431610835, 0.1556738744, 0.0919857178, 0.0500000000, 0.0249347645, 0.0113838852, 0.0047497169, 0.0018085048, 0.0006276833)
y1<-c(9.999998e-01,9.999980e-01,9.999847e-01,9.999011e-01,9.994707e-01,9.976528e-01,9.913453e-01, 9.733730e-01, 9.313130e-01, 8.504646e-01, 7.228116e-01, 5.572501e-01,3.808638e-01,2.264990e-01, 1.155286e-01, 5.000000e-02, 1.821625e-02, 5.554031e-03, 1.410980e-03, 2.976926e-04, 5.203069e-05)
df <- data.frame(x, y, y1)
df <- melt(df, id.var='x')
ggplot(df, aes(x = x, y = value, color = variable))+geom_line()
EDIT:
Changing the linetype and legend:
g <- ggplot(df, aes(x = x, y = value, color = variable, linetype=variable)) + geom_line()
g <- g + scale_linetype_discrete(name="Custom legend name",
labels=c("Curve1", "Curve2"))
g <- g + guides(color=FALSE)
print(g)

Related

R plot x and y axes changes

I have my data:
x <- list(10,50,100,250,500,2500)
y <- list(0.09090909,0.01960784,0.003984064,0.003984064,0.001996008,0.0003998401)
I want to link my data to code found on this website
log_c <- seq(-12, 0, by = 0.1)
df <- data.frame(log_c = log_c, response = V(log_c, E, HS, log_EC50))
ggplot(df, aes(log_c, response)) +
geom_line()
I want to put the x data in place of log_c and y data in place of response. These are my beginnings in R, so I am asking for help
At a minimum this will work:
you have expressed your x and y values as lists; it will work better if they are (atomic) vectors (which you would have gotten using c() instead of list()). Put them into a data frame (not strictly necessary, but best practice):
df <- data.frame(x=unlist(x), y = unlist(y))
Use the data frame to draw your plot:
library(ggplot2)
ggplot(df, aes(x, y)) + geom_line()
To get your graph looking a little more like the example in your post,
scalefun <- function(y) (y-min(y))/diff(range(y))
ggplot(df, aes(x, y = scalefun(y))) + geom_line() + scale_x_log10()
Same logic as #Ben Bolker: Just another way:
library(tidyverse)
tibble(x,y) %>%
unnest() %>%
ggplot(aes(x, y))+
geom_line()

Change axes label and scale using ggplot and patchwork in R

(I am trying to make this question as short and concise as possible, as other related answers may be tough for the non-savvy like myself.)
With the following code in mind, is it possible to have both y-axes on the same scale (that of the graph with the highest y-limit), and to have independent labels for each of the axes (namely the y-axes)? I tried to use facet_wrap but haven't so far been able to succeed as Layer 1 is missing)
library(ggplot2)
library(patchwork)
d <- cars
d$Obs <- c(1:50)
f1 <- function(a) {
ggplot(data=d, aes_string(x="Obs", y=a)) +
geom_line() +
labs(x="Observation",y="Speed/Distance")
}
f1("speed") + f1("dist")
You could add two additional arguments to your function, one for the axis label and one for your desired limits.
library(ggplot2)
library(patchwork)
d <- cars
d$Obs <- c(1:50)
f1 <- function(a, y_lab) {
ggplot(data = d, aes_string(x = "Obs", y = a)) +
geom_line() +
scale_y_continuous(limits = range(c(d$speed, d$dist))) +
labs(x = "Observation", y = y_lab)
}
f1("speed", "Speed") + f1("dist", "Distance")
Reshape wide-to-long, then use facet. Instead of having different y-axis labels we will have facet labels:
library(ggplot2)
library(tidyr)
pivot_longer(d, 1:2, names_to = "grp") %>%
ggplot(aes(x = Obs, y = value)) +
geom_line() +
facet_wrap(vars(grp))

R Highlight point on ecdf line graph

I'm creating a frequency plot using ggplot and the stat_ecdf function. I would like to add the Y-value to the graph for specific X-values, but just can't figure out how. geom_point or geom_text seems likely options, but as stat_ecdf automatically calculates Y, I don't know how to call that value in the geom_point/text mappings.
Sample code for my initial plot is:
x = as.data.frame(rnorm(100))
ggplot(x, aes(x)) +
stat_ecdf()
Now how would I add specific y-x points here, e.g. y-value at x = -1.
The easiest way is to create the ecdf function beforehand using ecdf() from the stats package, then plot it using geom_label().
library(ggplot2)
# create a data.frame with column name
x = data.frame(col1 = rnorm(100))
# create ecdf function
e = ecdf(x$col1)
# plot the result
ggplot(x, aes(col1)) +
stat_ecdf() +
geom_label(aes(x = -1, y = e(-1)),
label = e(-1))
You can try
library(tidyverse)
# data
set.seed(123)
df = data.frame(x=rnorm(100))
# Plot
Values <- c(-1,0.5,2)
df %>%
mutate(gr=FALSE) %>%
bind_rows(data.frame(x=Values,gr=TRUE)) %>%
mutate(y=ecdf(x)(x)) %>%
mutate(xmin=min(x)) %>%
ggplot(aes(x, y)) +
stat_ecdf() +
geom_point(data=. %>% filter(gr), aes(x, y)) +
geom_segment(data=. %>% filter(gr),aes(y=y,x=xmin, xend=x,yend=y), color="red")+
geom_segment(data=. %>% filter(gr),aes(y=0,x=x, xend=x,yend=y), color="red") +
ggrepel::geom_label_repel(data=. %>% filter(gr),
aes(x, y, label=paste("x=",round(x,2),"\ny=",round(y,2))))
The idea is to add the y values in the beginning, together with the index gr specifing which Values you want to show.
Edit:
Since this code adds points to the actual data, which could be wrong for the curve, one should consider to remove these points at least in the ecdf function stat_ecdf(data=. %>% filter(!gr))

Plotting two variables using ggplot2 - same x axis

I have two graphs with the same x axis - the range of x is 0-5 in both of them.
I would like to combine both of them to one graph and I didn't find a previous example.
Here is what I got:
c <- ggplot(survey, aes(often_post,often_privacy)) + stat_smooth(method="loess")
c <- ggplot(survey, aes(frequent_read,often_privacy)) + stat_smooth(method="loess")
How can I combine them?
The y axis is "often privacy" and in each graph the x axis is "often post" or "frequent read".
I thought I can combine them easily (somehow) because the range is 0-5 in both of them.
Many thanks!
Example code for Ben's solution.
#Sample data
survey <- data.frame(
often_post = runif(10, 0, 5),
frequent_read = 5 * rbeta(10, 1, 1),
often_privacy = sample(10, replace = TRUE)
)
#Reshape the data frame
survey2 <- melt(survey, measure.vars = c("often_post", "frequent_read"))
#Plot using colour as an aesthetic to distinguish lines
(p <- ggplot(survey2, aes(value, often_privacy, colour = variable)) +
geom_point() +
geom_smooth()
)
You can use + to combine other plots on the same ggplot object. For example, to plot points and smoothed lines for both pairs of columns:
ggplot(survey, aes(often_post,often_privacy)) +
geom_point() +
geom_smooth() +
geom_point(aes(frequent_read,often_privacy)) +
geom_smooth(aes(frequent_read,often_privacy))
Try this:
df <- data.frame(x=x_var, y=y1_var, type='y1')
df <- rbind(df, data.frame(x=x_var, y=y2_var, type='y2'))
ggplot(df, aes(x, y, group=type, col=type)) + geom_line()

ggplot2 Scatter Plot Labels

I'm trying to use ggplot2 to create and label a scatterplot. The variables that I am plotting are both scaled such that the horizontal and the vertical axis are plotted in units of standard deviation (1,2,3,4,...ect from the mean). What I would like to be able to do is label ONLY those elements that are beyond a certain limit of standard deviations from the mean. Ideally, this labeling would be based off of another column of data.
Is there a way to do this?
I've looked through the online manual, but I haven't been able to find anything about defining labels for plotted data.
Help is appreciated!
Thanks!
BEB
Use subsetting:
library(ggplot2)
x <- data.frame(a=1:10, b=rnorm(10))
x$lab <- letters[1:10]
ggplot(data=x, aes(a, b, label=lab)) +
geom_point() +
geom_text(data = subset(x, abs(b) > 0.2), vjust=0)
The labeling can be done in the following way:
library("ggplot2")
x <- data.frame(a=1:10, b=rnorm(10))
x$lab <- rep("", 10) # create empty labels
x$lab[c(1,3,4,5)] <- LETTERS[1:4] # some labels
ggplot(data=x, aes(x=a, y=b, label=lab)) + geom_point() + geom_text(vjust=0)
Subsetting outside of the ggplot function:
library(ggplot2)
set.seed(1)
x <- data.frame(a = 1:10, b = rnorm(10))
x$lab <- letters[1:10]
x$lab[!(abs(x$b) > 0.5)] <- NA
ggplot(data = x, aes(a, b, label = lab)) +
geom_point() +
geom_text(vjust = 0)
Using qplot:
qplot(a, b, data = x, label = lab, geom = c('point','text'))

Resources