I'm trying to code the following continuous function in R Programming.
I was trying to create a function called fun1 that takes a single argument vecA. I want the function to return the values of f(x) evaluated at the values of vecA.
fun1(vecA) <- function(x){
x^2+2x+3
}
I don't know how I can continue it.
Ideally your function should be able to take vectorized input, in which case you should use ifelse or case_when.
For example:
f <- function(x) {
ifelse(x < 0, x^2 + 2*x + 3,
ifelse(x >= 2, x^2 + 4 * x - 7,
x + 3))
}
Or
f <- function(x) {
dplyr::case_when(x < 0 ~ x^2 + 2*x + 3,
x > 2 ~ x^2 + 4 * x - 7,
TRUE ~ x + 3)
}
both of which produce the same output. We can see what the function looks like by doing:
plot(f, xlim = c(-5, 5))
Created on 2022-09-25 with reprex v2.0.2
Try studying the patterns here:
fun1 <- function(x){
if (x < 0) {
x^2+2*x+3
} else if (x < 2) {
x + 3
} else {
# Your turn
}
}
Related
I’m going to make a continuous graph with conditional log, in particular:
f <- function(x) {
if (0 < x && x <= 2) {
return (log(x));
} else {
return (x^2*log(x));
}
}
Now, I want to plot it:
ggplot(data.frame(x=seq(0,5,length.out=1000)), aes(x)) + geom_function(fun=f)
This code shows the graph fine on the part that is from x = 2 on, but for some reasons even on x between 0 and 2, it uses the second function x^2*log(x), not the first one.
This is more easily seen if I change the seq to seq(0, 2.1, length.out=1000).
But why does this happen and how can I fix it? I think I'm fine with the if statement with multiple conditions...
if is not vectorized. try ifelse instead:
f <- function(x) {
ifelse(test = 0 < x & x <= 2,
yes = log(x),
no = (x^2) * log(x))
}
df <- data.frame(x = seq(0, 5, length.out = 10000))
ggplot(df, aes(x)) +
geom_function(fun = f)
Vectorized means that ifelse takes a logical vector and applies the corresponding logic to each element of the vector, whether test was TRUE or FALSE.
if instead can handle just a single TRUE or FALSE. In case a vector is provided, only the first element of the vector is considered. Hence you probably received the following warning:
#> Warning messages:
#> 1: In 0 < x && x <= 2 : 'length(x) = 1000 > 1' in coercion to 'logical(1)'
I want to calculate the following integral in R.
I tried to use Vectorize and integrate functions but I got error
Error in (log(z)) * (InIntegl2) : non-numeric argument to binary operator
fxyz= function(x,y,z) { (x*y*z)+z+x+2*y}
InIntegl1 = Vectorize(function(x) { integrate(fxyz, 0,5)$value})
InIntegl2 = Vectorize(function(y) { integrate( InIntegl1, 0,3)$value})
InIntegl3 = Vectorize(function(z) { integrate((log(z))*(InIntegl2), 2,6)$value})
Integral = integrate(InIntegl3 , 2, 6)$value
The first integral must be parameterized by y and z and the second by z. Then we can perform the final integration.
int1 <- Vectorize(function(y, z) integrate(fxyz, 0, 5, y = y, z = z)$value)
int2 <- Vectorize(function(z) integrate(int1, 0, 3, z = z)$value)
integrate(function(z) log(z) * int2(z), 2, 6)$value
## [1] 2071.71
In the spirit of Numerical Triple Integration in R
integrate(Vectorize(function(z) {
log(z)*integrate(Vectorize(function(y) {
integrate(function(x) { x*y*z +x + 2*y + z}, 0, 5)$value }), 0,3)$value }), 2,6)
Package cubature can solve triple integrals with one call.
library(cubature)
f <- function(X){
x <- X[1]
y <- X[2]
z <- X[3]
log(z)*(x*y*z + x+ 2*y + z)
}
loLim <- c(0, 0, 2)
hiLim <- c(5, 3, 6)
tol <- .Machine$double.eps^0.5
hcubature(f, loLim, hiLim, tol = tol)
#$integral
#[1] 2071.71
#
#$error
#[1] 2.059926e-05
#
#$functionEvaluations
#[1] 165
#
#$returnCode
#[1] 0
If only the integral's value is needed,
hcubature(f, loLim, hiLim, tol = tol)$integral
#[1] 2071.71
This is the function I need to create in R
I have used ifelse for the first parts, but I am not quite sure how to input the third of the three equations in the piece-wise function
Personally, I would avoid using ifelse here because the the function is recursive. It needs to be defined for the atomic case and then vectorized:
g <- function(x, alpha= 0.001) {
g_single <- function(x, alpha) {
if(x <= 10^-4) return(0)
if(x >= 0.5) return(1 - g_single(1 - x, alpha))
return(2^alpha * x^(1 + alpha))
}
sapply(x, g_single, alpha = alpha)
}
g(runif(10))
#> [1] 0.7320931 0.9902868 0.8253122 0.5982243 0.2137887 0.6439024
#> [7] 0.8232719 0.3756205 0.2926292 0.4411532
Below is an analytical expression of function g
g <- function(x,a = 0.001) {
2**a*x**(1+a)*(x>=1e-4 & x <= 0.5) + (1-2**a*(1-x)**(1+a))*(x>0.5 & x <= 1-1e-4) + 1*(x>1-1e-4)
}
where a is an optional argument, set to some value by default.
You can pass a vector x to g to get a vectorized output, e.g.,
> g(runif(10))
[1] 0.26534066 0.37201400 0.57292063 0.90836325 0.20149890 0.89855147
[7] 0.94479693 0.66092938 0.62922482 0.06165721
The following problem is given: https://imgur.com/a/2OpPKfW
Write a function polyPrint, which prints the polynomial of Equation (1) in a nice way. For example,
if a corresponds to the vector c(2, 0, 1, -2, 5), then polyPrint(a) is supposed to print:
2 + x^2 + (-2)*x^3 + 5*x^4
Note how polyPrint is supposed to handle the cases where an element of a is either 0, 1 or negative!
At the moment I am using a loop and cat. Thats pretty rough because I need to do a lot of exeptions with ifelse statements for 1,0 and any negative.
Are there any other functions I could be using to streamline this process?
# Regular function
polyFunction <- function(x,a){
n <- seq(1, length(a))
sum(ax^(n-1))
}
# Printing the calculation method
a <- c(2,0,1,-2,5)
polyPrint <- function(a){
n <- seq(1, length(a))
for(i in n){
result <- c()
result <- c(result, cat(a[i],'x^', 1+i, '+ '))
}
}
polyPrint(a)
The expected output is a polynomial function that has this format:
p(x) = a0 + a1x + a2x^2 + ... + anxn
At the moment I am getting 2 *x^ 2 + 0 *x^ 3 + 1 *x^ 4 + -2 *x^ 5 + 5 *x^ 6 +
with the vector c(2, 0, 1, -2, 5)
I think you have an error in the way you are aggregating values and also the way you are taking in considerations special values (0,1, negative values).
Here an example of how you can do that (maybe not the best solution, but it does the job):
polyPrint <- function(a){
formule = NULL
for(i in 1:length(a))
{
if(a[i]==0){}
else{
if(i == 1) {formule = a[i]}
else{
if(a[i]<0){formule = paste0(formule, " + (",a[i],")x^",i)}
else{
if(a[i] == 1){formule = paste0(formule," + x^",i)}
else{formule = paste0(formule, " + ", a[i],"x^",i)}
}
}
}
}
print(formule)
}
And the result for a <- c(2,0,1,-2,5):
> polyPrint(a)
[1] "2 + x^3 + (-2)x^4 + 5x^5"
T <- function (p,q) {
for (x in 1:3) {
for (y in 1:3) {
sum(p*x + q*y)
print(sum(p*x + q*y))
}
}
}
sum(T(2,2))
I want the sum of 4, 6, 8, 6, 8, 10, 8, 10, 12 which is the output of the loop where p=2 and q=2 but the result is
sum(T(2,2))
[1] 4
[1] 6
[1] 8
[1] 6
[1] 8
[1] 10
[1] 8
[1] 10
[1] 12
Is there any way that I can get the sum or change the printed value to a vector rather than a list of each value? sum() function doesn't work on printed value.
Printing to the screen does exactly that; it doesn't return the value printed to the calling code. Your function needs to build a vector and return that. Here's a few different ways of doing it:
Code along the lines of what you were trying to do, but starting with an empty numeric vector and building it for each iteration:
T1 <- function(p, q) {
out <- numeric(0)
for (x in 1:3) {
for (y in 1:3) {
out <- c(out, p * x + q * y)
}
}
out
}
Preassigning the vector size and assigning to specific members of the vector
T2 <- function(p, q) {
out <- numeric(3 ^ 2)
for (x in 1:3) {
for (y in 1:3) {
out[(x - 1) * 3 + y] <- p * x + q * y
}
}
out
}
Using one of the map functions in purrr (overkill here but can be extended to functions which don't easily vectorise)
library(purrr)
T3 <- function(p, q) {
map2_dbl(rep(1:3, each = 3), rep(1:3, 3), function(x, y) p * x + q * y)
}
Using vector arithmetic to return the result in one command
T4 <- function(p, q) {
rep(1:3, each = 3) * p + rep(1:3, 3) * q
}
Using outer to achieve the same as T4 (as per #alistaire's comment):
T5 <- function(p, q) {
c(outer(1:3 * p, 1:3 * q, `+`))
}
It should be noted that the efficiency of these method will vary as the size of the loops increases, but that in general method 4 will be the most efficient closely followed by method 5. For small loops, interestingly method 1 seems to be better than 2, but 1 becomes inefficient as the loop size increases because R has to move memory around to keep increasing the size of the vector.