If statement doesn't work with a matrix condition - r

I have absolutely no idea why this is happening. My if statement doesn't work with a condition involving matrices.
This is my input:
i = matrix(c(1,0,0,1),nrow=2,ncol=2,byrow=TRUE)
j = matrix(c(1,0,0,2),nrow=2,ncol=2,byrow=TRUE)
if(i%*%i == j){
print("yes")
}
This is my output:
> i = matrix(c(1,0,0,1),nrow=2,ncol=2,byrow=TRUE)
> j = matrix(c(1,0,0,2),nrow=2,ncol=2,byrow=TRUE)
> if(i%*%i == j){
+ print("yes")
+ }
[1] "yes"
Warning message:
In if (i %*% i == j) { :
the condition has length > 1 and only the first element will be used

Related

Question about passing sapply index to function

I am sure this is a simple problem. But I am new to programming so I am struggling. I think what I am trying to accomplish should be pretty clear from the code. Essentially, I want to generate a vector of random numbers of length i, check if there is less than i unique numbers. And I want to do this a bunch of times as a sort of simulation. When I do it i by i manually using the following code:
experiment<- function() {
ab <- rdunif(i, 1, 365)
ab <- data.frame(ab)
count <- uniqueN(ab)
if (count < i)
return(1)
else
return(0)
}
vector <- replicate(10, experiment(), simplify=FALSE)
sum <- sum(as.data.frame((vector)))
probability <- sum/(10)
It works fine. But I need to run this simulation 40 times and I would rather not do it by hand. However, I can't seem to get sapply to work for me and I cannot figure out what I am doing wrong:
i<-10:50
experiment<- function(i) {
ab <- rdunif(i, 1, 365)
ab <- data.frame(ab)
count <- uniqueN(ab)
if (count < i)
return(1)
else
return(0)
}
complete <- function(i) {
vector <- replicate(10, experiment(i), simplify=FALSE)
sum <- sum(as.data.frame((vector)))
probability <- sum/(10)
return(probability)
}
sapply(i, complete(i), simplify=FALSE)
This is the error I am currently experiencing:
Error in match.fun(FUN) :
'complete(i)' is not a function, character or symbol
In addition: Warning messages:
1: In if (count < i) return(1) else return(0) :
the condition has length > 1 and only the first element will be used
2: In if (count < i) return(1) else return(0) :
the condition has length > 1 and only the first element will be used
3: In if (count < i) return(1) else return(0) :
the condition has length > 1 and only the first element will be used
4: In if (count < i) return(1) else return(0) :
the condition has length > 1 and only the first element will be used
5: In if (count < i) return(1) else return(0) :
the condition has length > 1 and only the first element will be used
6: In if (count < i) return(1) else return(0) :
the condition has length > 1 and only the first element will be used
7: In if (count < i) return(1) else return(0) :
the condition has length > 1 and only the first element will be used
8: In if (count < i) return(1) else return(0) :
the condition has length > 1 and only the first element will be used
9: In if (count < i) return(1) else return(0) :
the condition has length > 1 and only the first element will be used
10: In if (count < i) return(1) else return(0) :
the condition has length > 1 and only the first element will be used
I figured it out:
experiment<- function(i) {
ab <- rdunif(i, 1, 365)
count <- length(unique(ab))
if (count < i) return(1)
else return(0)
}
i <- 10:50
replication <- function(i) {
replicate(100, experiment(i))
}
data<- sapply(i, replication)
colMeans(data)

Error argument is of length zero occurs when creating my own sorting function

*> csort <- function(c){
i<-1
for (i in 1:length(c)-1) {
j <- i+1
for (j in 2:length(c)) {
if(c[i] >= c[j])c[c(i,j)] <- c[c(j,i)]
j = j + 1
}
i = i + 1
}
}
> csort(a)
Error in if (c[i] >= c[j]) c[c(i, j)] <- c[c(j, i)] :
argument is of length zero*
This is what RStudio do when I run it. I do not know what cause the zero here.
csort <- function(c){
p <- 1
povit <- c[1]
c <- c[-1]
left <- c()
right <- c()
left <- c[which(c <= povit)]
right <- c[which(c > povit)]
if(length(left) > 1){
left <- csort(left)
}
if(length(right) > 1){
right <- csort(right)
}
return(c(left ,povit,right))
}
I viewed more about sorting online and this is a pivot sort way.
your mistake is in this line
for (i in 1:length(c)-1)
and should be
for (i in 1:(length(c)-1))
since $:$ operator precedes $-$.
an example is
1:(5-1)
#[1] 1 2 3 4
1:5-1
#[1] 0 1 2 3 4
so error happen in index with Zero value.
csort <- function(d){
for (i in 1:(length(d)-1)) {
for (j in (i+1):length(d)) {
if(d[i] >= d[j])d[c(i,j)] <- d[c(j,i)]
}
}
return(d)
}
d<-c(5:1,-1:3,-9,-3,10,9,-20,1,20,-6,5)
any((csort(d)==sort(d))==F)
#[1] FALSE
you can improve this function.

Why subscript is out of bounds during for loops execution?

In my script is it possible to get d[[x]] "empty". I tried to do it with else, but it does not work.
How to write else so that it can give a result of checking zero?
for (x in 1:licznik3)
{
if(a[[x]] > d[[x]])
{
out3[[x]] <- wspolne3[[x]]
}
else (a[[x]] < d[[x]])
{
out3[[x]] <- NA
}
}
variables:
> a
[1] 0.1
> d
numeric(0)
> licznik3
[1] 16
Error in d[[x]] : subscript out of bounds
Example:
I have 3 loops.
If a[[x]] is greater than d[[x]]
this value goes to out3
and the next loop checks a similar condition.
My problem is that in the second loop (shown code) d[[x]] can be empty (in the previous loop no value was greater than a[[x]])
Then we have how
> a
  [1] 0.1
> d
numeric (0)
Just add additional check that your counter aka licznik3 ;) would not exceed length of vector d. If it exceeds break for-loop.
a <- 1:10
licznik3 <- 7
out3 <- rep_along(a, NA)
wspolne3 <- 2:12
d <- -c(1, 4, 2)
for (x in 1:licznik3) {
if (x > length(d)) {
break
}
if (a[[x]] > d[[x]]) {
out3[[x]] <- wspolne3[[x]]
} else {
out3[[x]] <- NA
}
}
out3

Logical not correctly evaluated?

I wondering why my first if statement returns Error when my input data is an object of class numeric?
I have clearly stated for the first if statement to only turn on IF the data class is "data.frame", but when data class is numeric, this first if statement return an error! am I missing anything here?
Update:
I have changed instances of & to && but when data is a data.frame, the function doesn't produce any output? For example, run: standard(mtcars)
standard <- function(data){
if(class(data) == "data.frame" && ncol(data) > 1){
data[paste0(names(data), ".s")] <- scale(data)
data
}
if(class(data) == "data.frame" && ncol(data) == 1){
colnames(data) <- paste0(names(data), ".s")
data <- scale(data)
data
}
if(class(data) != "data.frame"){
d <- as.data.frame(data)
colnames(d) <- paste0("Var", ncol(d), ".s")
data <- scale(d)
data
}
}
###### EXAMPLES: #######
standard(mtcars[,2]) ##Problem: `Error in if(class(data) == "data.frame" & ncol(data) > 1)`
standard(mtcars["wt"]) ## OK
standard(mtcars) ## after UPDATE, doesn't give any output
am I missing anything here?
& evaluate both elements while && does not
FALSE && stop("boh")
#R> [1] FALSE
TRUE && stop("boh")
#R> Error: boh
FALSE & stop("boh")
#R> Error: boh
See help("Logic")
& and && indicate logical AND and | and || indicate logical OR. The shorter form performs elementwise comparisons in much the same way as arithmetic operators. The longer form evaluates left to right examining only the first element of each vector. Evaluation proceeds only until the result is determined.
After your edits
You do not get any results because you do not call return or use if else. See help("function") and help("if"). Here is a small example
f1 <- function(x){
if(x < 0){
x <- -1
x
}
if(x > 0){
x <- 1
x
}
}
f1(-1)
f2 <- function(x){
if(x < 0){
x <- -1
x
}
else if(x > 0){
x <- 1
x
}
}
f2(-1)
#R> [1] -1
f3 <- function(x){
if(x < 0){
x <- -1
return(x)
}
if(x > 0){
x <- 1
return(x)
}
}
f3(-1)
#R> [1] -1
tl;dr you should use && rather than & when doing flow-control, because & always evaluates its second argument, while && short-circuits if the first argument is false. If the argument isn't a data frame (or matrix) then ncol(x) doesn't make sense: see e.g. this question for more information.
Go ahead and unpack it with a simple example.
x <- 1:5
The first part is fine:
class(x) ## "integer"
class(x)=="data.frame" ## TRUE
(although note that you have to be careful, because class(x) might be a vector with more than one element: inherits(x,"data.frame") is safer).
The second part causes the problem:
ncol(x) ## NULL (uh-oh)
ncol(x)>1 ## numeric(0) (uh-oh)
Put them together:
class(x)=="data.frame" & ncol(x)>1 ## logical(0)
What does this do?
if (logical(0)) print("hello")
Error in if (logical(0)) print("hello") : argument is of length zero

R: putting a function and for loop together to create a function

I'm trying to reverse and invert to see if the digits to see if they are the same when the numbers are upside down
I got up to this far and im confused...
revdigits =
function(n) {
sapply(lapply(strsplit(as.character(n),""),rev),paste,collapse="")
}
for(i in 1:length(n)){
n[i]=
if(n[i]==0) 0
else if(n[i] == 1) 1
else if(n[i] == 6) 9
else if(n[i] == 8) 8
else if(n[i] == 9) 6
else -1
}
invertible=
function(n)
n[1] == revdigits(n[1])
is there anyway to put them together (or relate them) to produce
invertible(c(99, 123, 1691))
[1] FALSE FALSE TRUE
this outcome??
You're already using apply in your code, so I may be misunderstanding the question, but I suppose the answer is
> invertible = function(n) sapply(n, function(x) x == revdigits(x))
> invertible(c(99, 123, 1691))
[1] TRUE FALSE FALSE
This alerts us to the fact that revdigits isn't quite working right. It's a bit hard to say what you intended to do since your code as is doesn't include the for loop in the function and has syntax errors:
> revdigits =
+ function(n) {
+ sapply(lapply(strsplit(as.character(n),""),rev),paste,collapse="")
+ }
>
>
> for(i in 1:length(n)){
+ n[i]=
+ if(n[i]==0) 0
+ else if(n[i] == 1) 1
+ else if(n[i] == 6) 9
+ else if(n[i] == 8) 8
+ else if(n[i] == 9) 6
+ else -1
+ }
Error: object 'n' not found
> }
Error: unexpected '}' in "}"
revdigits as is simply reverses the order of digits and converts numbers to strings:
> revdigits(c(123,69))
[1] "321" "96"
To find out how it does that, let's have a look at the sapply that looks like you didn't write it yourself, analyzing from the inside out with a simple example:
> n <- 69
> as.character(n)
[1] "69"
> strsplit(as.character(n),"")
[[1]]
[1] "6" "9"
> lapply(strsplit(as.character(n),""),rev)
[[1]]
[1] "9" "6"
> sapply(lapply(strsplit(as.character(n),""),rev),paste,collapse="")
[1] "96"
So your loop looks like it should be applied to the digit vector before the final step.
Packaging your loop into a function:
rotate = function(n) {
for(i in 1:length(n)){
n[i]=
if(n[i]==0) 0
else if(n[i] == 1) 1
else if(n[i] == 6) 9
else if(n[i] == 8) 8
else if(n[i] == 9) 6
else -1
}
n
}
Testing:
> rotate(0:9)
[1] 0 1 -1 -1 -1 -1 9 -1 8 6
and applying in revdigits
revdigits = function(n) {
sapply(lapply(lapply(strsplit(as.character(n),""),rev),rotate),paste,collapse="")
}
we get something that seems to work:
> revdigits(69)
[1] "69"
> revdigits(99)
[1] "66"
Even better, it already works with vectors!
> n <- c(99, 123, 1691)
> revdigits(n)
[1] "66" "-1-11" "1691"
> invertible <- function(n) n == revdigits(n)
> invertible(n)
[1] FALSE FALSE TRUE
No need to use indexes at all.
my try:
invertible <- function(n){
nd <- unlist(strsplit(as.character(n),split=""))
if (all(nd %in% c("0","1","6","9","8"))){
n == as.integer(paste(rev(sapply(nd, function(x){
ifelse(!x %in% c("9","6"),x,
ifelse(x == "9","6","9"))
})), collapse=""))
} else {
FALSE
}
}
sum(sapply(1:1e6, invertible))
# 198
Edit: you can put the sapply() inside still:
invertible <- function(N){
sapply(N, function(n){
nd <- unlist(strsplit(as.character(n),split=""))
if (all(nd %in% c("0","1","6","9","8"))){
n == as.integer(paste(rev(sapply(nd, function(x){
ifelse(!x %in% c("9","6"),x,
ifelse(x == "9","6","9"))
})), collapse=""))
} else {
FALSE
}
})
}

Resources