R: convert vectors of different lengths into a fixed time interval - r

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

Related

Plot multiple line graphs on the same window with auto-assigned different colors

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

How do I superimpose a regression line in a barplot in R?

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')

Given a vector, apply a function to each element of another vector

Question 1
I have a function that takes in p and n. I need to graph every combination of p=c(0.05,0.1,0.25,0.5,0.9,0.95) and n=c(5,10,30,50,100). So total of 6*5=30 plots. I've tried using mapply which returns a plot shown below (EDIT: too low reputation to upload img but I shows I get 6 plots only). Based on where my ablines are, I think it's trying all values of p over only a single value of n!
Question 2
I am trying to put values of n and p into the plot using paste0() to track which plot belongs to which combination of n and p, but it does not seem to work when I use mapply (it works fine for single graphs that I manually plot)
ci.auto <- function(p,n,alpha){
# Repeat the process nsim times
nsim <- 10000
ci.mat <- replicate(nsim, conf.int(p, n, alpha))
# Graphing the first 100 intervals
matplot(rbind(1:100, 1:100), ci.mat[, 1:100], type = "l", lty = 1,
xlab = paste0("sample number n=",n), ylab = "confidence interval")
abline(h = p)
text(2.5, 0.8, paste0("p=",p), col = "red")
# Proportion of times the interval is correct
mean( (p >= ci.mat[1,])*(p <= ci.mat[2,]) )
}
par(mfrow = c(5,6))
mapply(ci.auto, p = c(0.05,0.1,0.25,0.5,0.9,0.95), n = c(5,10,30,50,100), alpha)
df<-expand.grid(p,n)
mapply(Fun = ci.auto, df$Var1,df$Var2,alpha)

perspective plot in R (tick marks and understanding what is going on)

I plot a 3d plot in R using persp. I have two questions with respect to this:
Want to verify that I understand the docs correctly. persp will take the valuex from x and y, then depending on the index of each value in those vectors, say (i,j) corresponding to the current element in x and y, (x[i],y[j]), it will pluck out zfit[i,j] and plot (x[i],y[j],zfit[i,j]). Is this correct?
This does not produce the numbers on the actual axis but arrows in the increasing direction. How do I make numbers appear?
Example:
set.seed(1)
x = 1:10
y = rnorm(10)
z = x + y^2
g = expand.grid(list(x=seq(from=min(x), to=max(x), length.out=100),y=seq(from=min(y), to=max(y), length.out=100)))
mdl = loess(z ~ x+ y)
zfit = predict(mdl, newdata=g)
persp(x = seq(from=min(x), to=max(x), length.out=100), y = seq(from=min(y), to=max(y), length.out=100), z= zfit)
1 - Your understanding is correct.
2 - Add ticktype = "detailed" to show numbers on axis.

Plot fitted line within certain range R

Using R, I would like to plot a linear relationship between two variables, but I would like the fitted line to be present only within the range of the data.
For example, if I have the following code, I would like the line to exist only from x and y values of 1:10 (with default parameters this line extends beyond the range of data points).
x <- 1:10
y <- 1:10
plot(x,y)
abline(lm(y~x))
In addition to using predict with lines or segments you can also use the clip function with abline:
x <- 1:10
y <- 1:10
plot(x,y)
clip(1,10, -100, 100)
abline(lm(y~x))
Instead of using abline(), (a) save the fitted model, (b) use predict.lm() to find the fitted y-values corresponding to x=1 and x=10, and then (c) use lines() to add a line between the two points:
f <- lm(y~x)
X <- c(1, 10)
Y <- predict(f, newdata=data.frame(x=X))
plot(x,y)
lines(x=X, y=Y)
You can do this using predict.
You can predict on specific values of x (see ?predict)
x<-1:10
y<-1:10
plot(x,y)
new <- data.frame(x = seq(1, 5, 0.5))
lines(new$x, predict(lm(y~x), new))
The plotrix library has the ablineclip() function for just this:
x <- 1:10
y <- 1:10
plot(x,y)
ablineclip(lm(y~x),x1=1,x2=5)
An alternative is to use the segments function (doc here).
Say you estimated the line, and you got an intercept of a and a slope of b. Thus, your fitted function is y = a + bx.
Now, say you want to show the line for x between x0 and x1. Then, the following code plots your line:
# inputs
a <- 0.5
b <- 2
x0 <- 1
x1 <- 5
# graph
plot(c(0,5), c(0,5), type = "n", xlab = "", ylab = "", bty='l')
segments(x0, a+b*x0, x1, a+b*x1)
Simply replace the values of a, b, x0, x1 with those of your choosing.
For those like me who came to this question wanting to plot a line for an arbitrary pair of numbers (and not those that fit a given regression), the following code is what you need:
plot(c(0,5), c(0,5), type = "n", xlab = "", ylab = "", bty='l')
segments(x0, yo, x1, y1)
Simply replace the values of x0, y0, x1, y1 with those of your choosing.

Resources