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)
Related
I want to create a vector of functions with two parameters where one parameter is over a continuous range of values and the other runs over a fixed number of numerical values saved in the column vector dat[,2].
# Example functions
icc <- function(year, x) {
z = exp(year - x)
inf = z / (1 + z)
return (inf)
}
# Example data
year <- seq(-4, 4, 0.1)
x1 <- dat[1, 2]
x2 <- dat[2, 2]
# Plots
plot(t, icc(year, x1), type = "l")
plot(t, icc(year, x2), type = "l")
The issues are
dat[,2] has more than just 2 values and I want to be able to plot all the corresponding functions on the same plot but with different colors
manually assigning colors to each line is difficult as there are a large number of lines
dat[,1] stores the corresponding label to each plot; would it be possible to add them over each line?
I have something like this in mind-
UPDATE: dat is simply a 40 x 2 table storing strings in the first column and numerical values in the second. By 'a vector of functions', I mean an array containing functions with parameter values unique to each row. For example- if t^i is the function then, element 1 of the array is the function t^1, element 2 is t^2 and so on where t is a 'range'. (Label and color are extras and not too important. If unanswered, I'll post another question for them).
The function to use is matplot, not plot. There is also matlines but if the data to be plotted is in a matrix, matplot can plot all columns in one call.
Create a vector of y coordinates, yy, from the x values. This is done in a sapply loop. In the code below I have called the x coordinates values xx since there is no dat[,2] to work with.
Plot the resulting matrix in one matplot function call, which takes care of the colors automatically.
The lines labels problem is not addressed, only the lines plotting problem. With so many lines their labels would make the plot more difficult to read.
icc <- function(year, x) {
z = exp(year - x)
inf = z / (1 + z)
return (inf)
}
# Example data
year <- seq(-4, 4, 0.1)
xx <- seq(-1, 1, by = 0.2)
yy <- sapply(xx, \(x) icc(year, x))
matplot(year, yy, type = "l", lty = "solid")
Created on 2022-07-26 by the reprex package (v2.0.1)
Note
Function icc is the logistic distribution CDF with location x and scale 1. The base R plogis function can substitute for it, the results are equal within floating-point precision.
icc2 <- function(year, x) plogis(year, location = x, scale = 1)
yy2 <- sapply(xx, \(x) icc2(year, x))
identical(yy, yy2)
#> [1] FALSE
all.equal(yy, yy2)
#> [1] TRUE
This question already has an answer here:
R: Get the min/max of each item of a vector compared to single value
(1 answer)
Closed 2 years ago.
I tried the following two ways. It seems to me they all take x as a vector instead of a single point. Is there a way to correctly plot this function?
eq = function(x){max(x,0)}
curve(eq, from=1, to=50, , xlab="x", ylab="y")
# It produces the following error:
#Error in curve(eq, from = 1, to = 50, , xlab = "x", ylab = "y") :
# 'expr' did not evaluate to an object of length 'n'
ggplot(data.frame(x=c(1,50)), aes(x=x)) + stat_function(fun=eq)
#It will draw a horizontal line at x=50
You probably want parallel maxima, pmax.
eq = function(x){pmax(x,0)}
curve(eq, from=-50, to=50, , xlab="x", ylab="y")
ggplot(data.frame(x=c(-50,50)), aes(x=x)) + stat_function(fun=eq)
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)
So I want to superimpose a regression line in a barplot in R. Similar to the attached image by Rosindell et al. 2011. However, when I try to do this with my data the line does not stretch the entire length of the barplot.
For a reproducible example, I made a dummy code:
x = 20:1
y = 1:20
barplot(x, y, space = 0)
lines(x, y, col = 'red')
How do I get the lines to transverse the entire stretch of the barplot bins?
PS: the line does not need to be non-linear. I just want to superimpose a straight line on the barplot
Thank you.
A more general solution could be to rely on the x-values that are generated by barplot(). This way, you can deal with scenarios where you only have counts (rather than x and y values). I am referring to a variable like this one, where your "x" is categorical (precisely, x-axis values correspond to the names of y).
p.x <- c(8,12,14,9,5,3,2)
x <- sample(c("A","B","C","D","E","F","G"),
prob = p.x/sum(p.x),
replace = TRUE,
size = 200)
y <- table(x)
y
# A B C D E F G
# 27 52 46 36 21 11 7
When you use barplot(), you can collect the x-positions of the bars in a variable (plot.dim in this case) and use to guide your line
plot.dim <- barplot(y)
lines(plot.dim, y, col = "red", lwd = 2)
The result
Now, back to your data. Even if you have both x and y, in a barplot you are displaying only your y variable, while x is used for the labels of y.
x <- 20:1
y <- as.integer(22 - 1 * sample(seq(0.7, 1.3, length.out = length(x))) * x)
names(y) <- x
y <- y[order(as.numeric(names(y)))]
Let's plot your y values again. Collect the barplot positions in the xpos variable.
xpos <- barplot(y, las = 2)
Note that the first bar (x=1) is not positioned at 1. Similarly, the last bar is positioned at 23.5 (and not 20).
xpos[1]
# x=1 is indeed at 0.7
xpos[length(xpos)]
# x=20 is indeed at 23.5
Do your regression (for example, use lm()). Compute the predicted y values at the first and the last x (y labels).
lm.fit <- lm(y~as.numeric(names(y)))
y.init <- lm.fit$coefficients[2] * as.numeric(names(y))[1] + lm.fit$coefficients[1]
y.end <- lm.fit$coefficients[2] * as.numeric(names(y))[(length(y))] + lm.fit$coefficients[1]
You can now over-pose a line using segments(), but remember to set your x-values according to what stored in xpos.
segments(xpos[1], y.init, xpos[length(xpos)], y.end, lwd = 2, col = "red")
Check out the help page ?barplot: the second argument is width - optional vector of bar widths, not the y coordinate. The following code does what you want, but I don't believe it's a general purpose solution.
barplot(y[x], space = 0)
lines(x, y, col = 'red')
Edit:
A probably better way would be to use the return value of barplot.
bp <- barplot(y[x], space = 0)
lines(c(bp), y[x], col = 'red')
I am working with 2 vectors with different lengths 105,102. Call them y1,y2
Although they are different in length, each vector represents activity that happens in 30 seconds.
Assume the first element of all vectors start at time = 0 seconds, I was able to plot them out with the following code:
y1 <- plot(seq(0,100,length = 105), rnorm(length(seq(0,100,length = 105))), type = "l")
y2 <- plot(seq(0,100,length = 102), rnorm(length(seq(0,100,length = 102))), type = "l")
l <- length(y1)
x <- seq(0,l,length= l)
y <- y1
plot(x, y, type = "l", xlab = "time", ylab = "bla")
l <- length(y2)
x <- seq(0,l,length= l)
y <- y2
lines(x,y, type = "l")
Now the above code will produce a graph with x-axes ranging from $(0,105)$. However, I want the x-axes to display $(0, 30)$ seconds.
I know the major problem is that the two vectors are in different lengths, but suppose I want to split the elements of each vector along the time interval $0 - 30$ seconds.
How should I approach this ?
I think OP's just looking to equally distribute each y vector in time interval of 30 sec and plot the same. In that case, following should do the trick. Essentially, for x argument of plot and lines function, we need to provide vector which has number of elements equal to number of elements in y corresponding argument, spread out from 0 to 30.
set.seed(1234)
y1 <- rnorm(length(seq(0,100,length = 105)))
y2 <- rnorm(length(seq(0,100,length = 102)))
plot((30/length(y1))*seq_along(y1), y1, type = 'l',col='red', xlab='time', ylab='y')
lines((30/length(y2))*seq_along(y2), y2, col='green')
which gives