Reputation: 353
I'm trying to come up with a generic R function to produce figure (b) in the image, where x is the x-axis and g is the y-axis. I'm trying to come up with a function f
with the prototype f(x, start_x, dx, init_g, end_g)
where x
is a vector of ints representing timesteps (e.g. 1:100
), start_x
represents the step to start the ramp, dx
represents the distance between start_x
and end of ramp. init_g
is the starting value of the function on the vertical axis, and end_g
is the value at the end of the ramp. The function will return the ramp which I can plot to get that figure.
If dx=0
, we get a step function like in figure (a). Also, the ramp can slope down depending on whether end_g
is more or less than init_g
.
I don't care about figures (c) or (d) in the image. I just can't figure out what to do to get the part between start_x
and start_x + dx
. Thanks for the help.
Upvotes: 0
Views: 732
Reputation: 5747
It only takes four x and four g values to define a plot like this.
plot_fun <- function(x, start_x, dx, init_g, end_g) {
x <- c(x[1], start_x, start_x + dx, tail(x, 1))
g <- c(init_g, init_g, end_g, end_g)
plot(x, g, type = "l")
}
plot_fun(x = 1:100, start_x = 20, dx = 30, init_g = 2, end_g = 5)
plot_fun(x = 1:100, start_x = 20, dx = 0, init_g = 2, end_g = 5)
If you just want to generate a vector g
of the same length as x
that is needed to produce the plot, here is how that can work:
make_g <- function(x, start_x, dx, init_g, end_g) {
require(dplyr)
require(tidyr)
x_g <- data.frame(x = c(x[1], start_x + dx),
g = c(init_g, end_g))
x_g <- data.frame(x) %>%
left_join(x_g) %>%
fill(g, .direction = "down")
return(x_g$g)
}
make_g(x = 1:100, start_x = 20, dx = 30, init_g = 2, end_g = 5)
Joining, by = "x"
[1] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 5 5 5 5 5
[55] 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
Upvotes: 1
Reputation: 160447
Here's a function that returns data that you can use to plot.
f <- function(x, start_x, dx, init_g, end_g, type = c("ramp", "step")) {
type <- match.arg(type)
y <- numeric(length(x))
if (!length(x)) return(y)
end_x <- start_x + dx
y[x < start_x] <- init_g
y[x > end_x] <- end_g
mid <- (x >= start_x & x <= end_x)
y[mid] <-
if (type == "ramp") {
approx(c(start_x, end_x), c(init_g, end_g), xout = x[mid])$y
} else c(rep(init_g, length(mid) - 1), end_g)
return(data.frame(x = x, y = y))
}
Demonstration:
plot(y ~ x, data = f(1:100, 50, 10, 10, 20, "ramp"), type = "b")
plot(y ~ x, data = f(1:100, 50, 10, 10, 20, "step"), type = "b")
Upvotes: 0
Reputation: 353
I figured out something that seems to work, not sure exactly why. There's probably a more elegant way to do it.
f <- function(x, x0, dx, g0, g1) {
s <- (x0 - dx) * (g1-g0)/dx
ifelse(x < x0, g0,
ifelse(x < (x0+dx), (x-dx) * (g1 - g0)/dx + (g0 - s),
g1))
}
Upvotes: 0