Replicating is.element - r

I need to replicate the is.element function in R. I have two vectors and need to compare the values in each where if one matches the other the output is True and False for all others.
Code I've tried that does not quite work:
x <- c(3, 0, -2, 0)
y <- c(-1, 0, 1)
n <- length(x)
answer <- is.logical(x)
for (i in 1:n) {
if (x[i] == y[i]) {
answer[i] <- TRUE
} else {
answer[i] <- FALSE
}
}
answer
Intended answer:
[1] FALSE TRUE FALSE TRUE

An option would be outer to do the comparison of each element of 'x' with 'y' to return a logical matrix, which can be reduced to a logical vector
by getting the sum of TRUE elements in each row (rowSums) and check if it is greater than 0
rowSums(outer(x, y, `==`)) > 0
#[1] FALSE TRUE FALSE TRUE
Or create the logical matrix with sapply and do a `colSums
colSums(sapply(x, `==`, y)) > 0

actually, I just figured it out. Thanks again.
x <- c(3, 0, -2, 0)
y <- c(-1, 0, 1)
n <- length(x)
m <- length(y)
answer <- is.logical(x)
for (i in 1:n) {
for (j in 1:m) {
if (x[i] == y[j]) {
answer[i] <- TRUE
break
} else {
answer[i] <- FALSE
}
}
}
answer

Related

function with if...else loop in R

Can someone tell me what is wrong with this function in R? The functions can work on a single input, but when I use a vector I get an error:
input_check3 <- function(x){
if (is.finite(x)) {
if (x %% 2 == 0){
print(TRUE)
} else {
print(FALSE)
}
} else {
NA
}
}
data_for_e2 <- c(1, 2, 4, 5, 3)
input_check3(data_for_e2)
#> [1] FALSE
#> Warning messages:
#> 1: In if (is.finite(x)) { : The length of the condition is greater than one, so only its first element can be used
#> 2: In if (x%%2 == 0) { : The length of the condition is greater than one, so only its first element can be used
You could use ifelse, which is a vectorized function:
input_check3 <- function(x){
ifelse(is.finite(x),
x %% 2 == 0, # equiv to ifelse(x %% 2 == 0, TRUE, FALSE), thanks Martin Gal!
NA)
}
Result
[1] FALSE TRUE TRUE FALSE FALSE

R: Creating a function usingthe control structure 'for'

I would like to create a function that, having a vector (v) and a number (n), analyze if any of the numbers of 'v' is divisible by 'n', if it is, the function would have the outcome 'TRUE'. How could I use the control structure 'for' for it?
So far I've solved this problem using the 'while' operator:
function.while <- function(v, n){
while (n %% v == 0)
return (TRUE)
}
But I can't fully understand the logic of 'for'.
Thanks.
You can use for loop like below :
function.for <- function(v, n){
result <- logical(length(v))
for(i in seq_along(v)) {
result[i] <- v[i] %% n == 0
}
return(result)
}
function.for(1:10, 2)
#[1] FALSE TRUE FALSE TRUE FALSE TRUE FALSE TRUE FALSE TRUE
However, this is vectorised operation and you don't need for loop.
function.vectorized <- function(v, n){
v %% n == 0
}
function.vectorized(1:10, 2)
If you want to check if any value is present.
function.vectorized <- function(v, n){
any(v %% n == 0)
}

Can someone explain what they are doing at the sum part of this question

Was looking at some questions online and this was the question
Create the function unique, which given a vector will return a new vector with the elements of the first vector with duplicated elements removed.
I looked at the solution and this is what they had
f.uniq <- function (v) {
s <- c()
for(i in 1:length(v)) {
if(sum(v[i] == s) == 0) {
s <- c(s, v[i])
}
}
s
}
f.uniq(c(9, 9, 1, 1, 1, 0))
if anyone could explain what is happening here
if(sum(v[i] == s) == 0)
sum(v[i] == s) == 0 indicates the condition that v[i] is not in s. Here, v[i] == s yields a logic vector of same dimension as s, so sum(v[i] == s) counts the number of TRUEs there. If there is no TRUE i.e., sum(v[i] == s) == 0, then you can enter the if statement.
The code v[i] == s Performs elementwise comparison between v[i] and all elements of s. v[i] == s returns a list like TRUE TRUE FALSE for example. If the sum of this is larger than 0, this means that the element v[i] is already contained in the list. Otherwise it is appended.
Some cat might be useful in this kind of situation
f.uniq <- function (v) {
s <- c()
for(i in 1:length(v)) {
cat("\ni=",i,"\nv[i] ==s :", v[i] == s,"\nsum(v[i] == s):",sum(v[i] == s),"\n")
if(sum(v[i] == s) == 0) {
s <- c(s, v[i])
}
}
s
}
## > f.uniq(c(9, 9, 1, 1, 1, 0))
## i= 1
## v[i] ==s :
## sum(v[i] == s): 0
## i= 2
## v[i] ==s : TRUE
## sum(v[i] == s): 1
## i= 3
## v[i] ==s : FALSE
## sum(v[i] == s): 0
## i= 4
## v[i] ==s : FALSE TRUE
## sum(v[i] == s): 1
## i= 5
## v[i] ==s : FALSE TRUE
## sum(v[i] == s): 1
## i= 6
## v[i] ==s : FALSE FALSE
## sum(v[i] == s): 0
## [1] 9 1 0

'missing value where TRUE/FALSE needed'

I received the error
Error in if (x[i] == 0 && x[i - 1] > 0) { :
missing value where TRUE/FALSE needed
when running this function on a numeric vector
number_rn <- function(x) {
a <- 0
for (i in 1:length(x)) {
if (x[i] == 0 && x[i-1] > 0) {
a <- a +1
}
}
print(a)
}
However, the following function works fine:
number_rr <- function(x) {
a <- 0
for (i in 1:length(x)) {
if (x[i] > 0 && x[i-1] > 0) {
a <- a +1
}
}
print(a)
}
I note from previous answers to similar questions that this can occur if the if conditional does not have either a TRUE or FALSE result, but I do not believe this to be the case in my example. What could be causing this error?
There are several issues with the for loop (even if x does not contain any NA values):
In the first iteration (i == 1), x[i-1] refers to x[0] which is undefined as indexing in R starts at 1.
The code is using a for loop where vectorized functions can be used.
Unfortunately, starting the loop at i == 2, i.e., for (i in 2:length(x)), is not error-proof in case of a one element vector where length(x) == 1.
My suggestion is to use the vectorized version
number_rn_vec <- function(x) {
n <- length(x)
sum(x[2:n] == 0 & x[1:(n - 1)] > 0, na.rm = TRUE)
}
This will return a without error for many use cases:
sapply(
list(
c(),
c(1),
c(1, 0),
c(1, 0, 3),
c(0, 1, 0, 3),
c(NA, 1, 0, 3),
c(1, NA, 0, 3),
c(1, 0, NA, 3),
c(1, 0, 3, NA)
),
number_rn_vec
)
[1] 0 0 1 1 1 1 0 1 1
This is most likely occurring because you vector x has NULL or NA values. See what happens when I try to run a if condition with NULL values -
x <- NULL
if (x == 0 && x > 5) print("yes")
Make sure to remove any NAs or NULLs using is.na() or is.null() and you should be fine

How to apply a function to a matrix in R

Write a function which takes a matrix that can be coerces into a matrix; the function should return a matrix which is the same as the function argument, but every even number is not changed and odd number is doubled.
I'm very new to R. Can someone help me complete my codes:
mx = matrix(c(1,1,3,5,2,6,-2,-1,-3), nrow = 3, byrow = TRUE)
fun = function(mx){
for(i in mx){
if(i %% 2 == 0){
return(i)
}
else if(i %% 2 > 0){
return(2*i)
}
}
}
Don't need a function, just use the built-in function ifelse:
mx <- ifelse(mx %% 2 == 0, mx, 2*mx)
Or, if you prefer to encapsulate it into a function:
fun = function(mx) {
ifelse(mx %% 2 == 0, mx, 2*mx)
}
res <- fun(mx)
## [,1] [,2] [,3]
##[1,] 2 2 6
##[2,] 10 2 6
##[3,] -2 -2 -6
Explanation:
ifelse performs a vectorized comparison over all elements of the matrix mx to see if each element is even (i.e., mx %% 2 == 0). For each element if this comparison condition is TRUE, the next argument is returned, which in this case is just the value from that element in mx. Otherwise, the last argument is returned, which is 2 times the value from that element in mx as you wish.
That's easy using indices :)
double_odd <- function(mx){
odds_idx <- (mx %% 2 != 0)
mx[odds_idx] <- 2 * mx[odds_idx]
mx # If it is the last statement, you don't need return
}
Cheers
Using your try:
fun = function(mx){
res <- matrix(data = NA, ncol = ncol(mx), nrow = nrow(mx))
for(i in 1:ncol(mx)){
for(j in 1:nrow(mx))
if(mx[j, i] %% 2 == 0){
res[j, i] <- mx[j, i]
}else{
res[j, i] <- 2 * mx[j, i]
}
}
return(res)
}
of course not the most elegant solution :)

Resources