If else loop error in R - r

I am trying to solve the question of compare triplets in R posted on hackerrank
Although I have outlined the entitre steps still its not giving correct result not in hackerrank and in RStudio also . can anyone tell me
A reproducible example
m = data.frame(ints = as.integer())
m <- structure(rbind(m,c(5,6,7)), .Names = names(m))
m <- structure(rbind(m,c(3,6,10)), .Names = names(m))
names(m) = c("no1","no2","no3")
enter## the output gives m as below
`no1 no2 no3
1 5 6 7
2 3 6 10
## I need to compare the corresponding values in both rows
#if m[1,1] != m[2,1] then I need to store 1 in a vector or dataframe
#if m[1,2] != m[2,2] then I need to store 1 in a vector or dataframe
#if m[1,3] != m[2,3] then I need to store 1 in a vector or dataframe
#so We will get output as [1,1]
## defining a vector to store output as below
g = c(0,0,0)
g = c(0,0,0)
> g
[1] 0 0 0
> g[1]
[1] 0
## so my answer is as below
if(m[1,1]== m[2,1]))
{
print("nothing")
}
else
{
(g[1] = 1)
}
if((m[1,2]==m[2,2]))
{
print("nothing")
}
else
{
(g[2] = 1)
}
if((m[1,3]==m[2,3]))
{
print("nothing")
}
else
{
(g[3] = 1)
}
g = data.frame()
g = c(0,0,0)
I get the following errors after every else
Error: unexpected 'else' in " else"
also g even takes value for middle value which it should never take
g
[1] 1 1 1
Can anyone explain what is going on why it is still placing 1 for middle value.

In R an end of line marks the end of an instruction unless there are open parenthesis, open braces or an unfinished instruction, such as else to signify otherwise.
Try
if(m[1,1]== m[2,1]) {
print("nothing")
} else
{
(g[1] = 1)
}
Or shorter
if(m[1,1]== m[2,1])
print("nothing") else
g[1] = 1
Your problem in any case is better solved by:
g <- as.numeric(m[1,] != m[2,])
# [1] 1 0 1

Related

how to create function with input from dataframe and apply it over all rows?

I try to write a function in R which takes several variables from a dataframe as input and gives a vector with results as output.
Based on this post below I did write the function below.
How can create a function using variables in a dataframe
Although I receive this warning message:
the condition has length > 1 and only the first element will be used
I have tried to solve it by the post below using sapply in the function although I do not succeed.
https://datascience.stackexchange.com/questions/33351/what-is-the-problem-with-the-condition-has-length-1-and-only-the-first-elemen
# a data frame with columns a, x, y and z:
myData <- data.frame(a=1:5,
x=(2:6),
y=(11:15),
z=3:7)
myFun3 <- function(df, col1 = "x", col2 = "y", col3 = "z"){
result <- 0
if(df[,col1] == 2){result <- result + 10
}
if(df[,col2] == 11){result <- result + 100
}
return(result)
}
myFun3(myData)
> Warning messages:
> 1: In if (df[, col1] == 2) { :
> the condition has length > 1 and only the first element will be used
> 2: In if (df[, col2] == 11) { :
> the condition has length > 1 and only the first element will be used
Can someone explain me how I can apply the function over all rows of the dataframe?
Thanks a lot!
We need ifelse instead of if/else as if/else is not vectorized
myFun3 <- function(df, col1 = "x", col2 = "y", col3 = "z"){
result <- numeric(nrow(df))
ifelse(df[[col1]] == 2, result + 10,
ifelse(df[[col2]] == 11, result + 100, result))
}
myFun3(myData)
#[1] 10 0 0 0 0
Or the OP's code can be Vectorized after making some changes i.e. remove the second if with an else if ladder
myFun3 <- Vectorize(function(x, y){
result <- 0
if(x == 2) {
result <- result + 10
} else if(y == 11){
result <- result + 100
} else result <- 0
return(result)
})
myFun3(myData$x, myData$y)
#[1] 10 0 0 0 0
Regarding the OP's doubts about when multiple conditions are TRUE, then want only the first to be executed, the ifelse (nested - if more than two) or if/else if/else (else if ladder or if/else nested) both works because it is executed in that same order we specified the condition and it stops as soon as a TRUE condition occurred i.e. suppose we have multiple conditions
if(expr1) {
1
} else if(expr2) {
2
} else if(expr3) {
3
} else if(expr4) {
4
} else {
5}
checks the first expression ('expr1') first, followed by second, and so on. The moment it return TRUE, it exit i.e. it is a nested condition
if(expr1) {
1
} else {
if(expr2) {
2
} else {
if(expr3) {
3
} else {
if(expr4) {
4
} else 5
}
}
}
There is a cost for this i.e.. whereever we have the more values that matches the 1, only the expr1 is executed and thus saves time, but if there are more 5 values, then all those conditions are checked

Repeat a function until conditions are met in r using a while loop

This may not be the most efficient way for doing this, but I've created a code for a fruit machine (that works), from the help of a book (not sure if I can share the title, but it is very good for noobs). However this code is very simple, it runs a function that calls two other functions, in order:
pull() simulates the wheel mechanism by randomly selecting characters from a pre-determined vector.
prize() analyses the response from pull() to add a value to the symbols by using a lookup table.
The code works, but I wanted to modify it so that the code runs until it reaches the jackpot which is three diamonds; "DD". I also wanted it to quantify all other responses until it reaches this target, so I tried a while loop, which does not seem to produce anything:
play2 <- function(){
response <- pull()
# I put the while loop straight after calling the first function,
# hoping that if the condition is not met, then the first function
# runs again, creating a new "response" until conditions are met.
while (sum(response == "DD") != 3) {
# I set the condition so that if the jackpot is not achieved, the
# while loop causes the other responses to be investigated. It
# it determines this by counting booleans.
# The following assignments are designed to begin the count for how
# many responses that are considered prizes occur, and how often no
# prize occurs.
cherry_prize <- 0
B_prize <- 0
BB_prize <- 0
BBB_prize <- 0
seven_prize <- 0
no_prize <- 0
if ("C" %in% response){
cherry_prize <- cherry_prize + 1
# A cherry prize occurs if any "C" is returned. The following
# statements will asses the other non-jackpot three of a kinds.
}
else if (sum(response == "B") != 3) {
B_prize <- B_prize + 1
}
else if (sum(response == "BB") != 3) {
BB_prize <- BB_prize + 1
}
else if (sum(response == "BBB") != 3) {
BBB_prize <- BBB_prize + 1
}
else if (sum(response == "7") != 3) {
seven_prize <- seven_prize + 1
}
else {
no_prize <- no_prize + 1
}
}
# After the jackpot is achieved, the number of other prizes (or lack
# thereof) that were returned are quantified, prior to the jackpot
# were won. The jackpot triplicate would then also be returned and
# quantified.
print(cherry_prize)
print(B_prize)
print(BB_prize)
print(BBB_prize)
print(seven_prize)
print(no_prize)
print(response)
# The last function quantifies the jackpot, once it has been reached.
prize(response)
}
Hope I have provided enough information. All help received very gratefully, and hope it can help others.
Thank you for the suggestions above. So I followed the instructions and came across a warning that that prevented the function from running.
Error in symbols == "DD" :
comparison (1) is possible only for atomic and list types
So again I think the coding method that I am using is not the most efficient method, but I corrected this with as.list().
play2 <- function(){
runs <- 0
cherry_prize <- 0
B_prize <- 0
BB_prize <- 0
BBB_prize <- 0
seven_prize <- 0
no_prize <- 0
while (sum(as.list(response) == "DD") != 3) {
runs <- runs + 1
response <- pull()
if ("C" %in% response){
cherry_prize <- cherry_prize + 1
}
else if (sum(as.list(response) == "B") != 3) {
B_prize <- B_prize + 1
}
else if (sum(as.list(response) == "BB") != 3) {
BB_prize <- BB_prize + 1
}
else if (sum(as.list(response) == "BBB") != 3) {
BBB_prize <- BBB_prize + 1
}
else if (sum(as.list(response) == "7") != 3) {
seven_prize <- seven_prize + 1
}
else {
no_prize <- no_prize + 1
}
}
print(runs)
print(cherry_prize)
print(B_prize)
print(BB_prize)
print(BBB_prize)
print(seven_prize)
print(no_prize)
print(response)
score(response)
}
This gives the output:
> play2()
[1] 430118
[1] 12526
[1] 411199
[1] 6393
[1] 0
[1] 0
[1] 0
[1] "DD" "DD" "DD"
[1] 800
Something in part of my code that I haven't shown is affecting my BBB, 7 and no prize.

About missing value where TRUE/FALSE needed in R

I want to return the number of times in string vector v that the element at the next successive index has more characters than the current index.
Here's my code
BiggerPairs <- function (v) {
numberOfTimes <- 0
for (i in 1:length(v)) {
if((nchar(v[i+1])) > (nchar(v[i]))) {
numberOfTimes <- numberOfTimes + 1
}
}
return(numberOfTimes)
}
}
missing value where TRUE/FALSE needed.
I do not know why this happens.
The error you are getting is saying that your code is trying to evaluate a missing value (NA) where it expects a number. There are likely one of two reasons for this.
You have NA's in your vector v (I suspect this is not the actual issue)
The loop you wrote is from 1:length(v), however, on the last iteration, this will try the loop to try to compare v[n+1] > v[n]. There is no v[n+1], thus this is a missing value and you get an error.
To remove NAs, try the following code:
v <- na.omit(v)
To improve your loop, try the following code:
for(i in 1:(length(v) -1)) {
if(nchar(v[i + 1]) > nchar(v[i])) {
numberOfTimes <- numberOfTimes + 1
}
}
Here is some example dummy code.
# create random 15 numbers
set.seed(1)
v <- rnorm(15)
# accessing the 16th element produces an NA
v[16]
#[1] NA
# if we add an NA and try to do a comparison, we get an error
v[10] <- NA
v[10] > v[9]
#[1] NA
# if we remove NAs and limit our loop to N-1, we should get a fair comparison
v <- na.omit(v)
numberOfTimes <- 0
for(i in 1:(length(v) -1)) {
if(nchar(v[i + 1]) > nchar(v[i])) {
numberOfTimes <- numberOfTimes + 1
}
}
numberOfTimes
#[1] 5
Is this what you're after? I don't think there is any need for a for loop.
I'm generating some sample data, since you don't provide any.
# Generate some sample data
set.seed(2017);
v <- sapply(sample(30, 10), function(x)
paste(sample(letters, x, replace = T), collapse = ""))
v;
#[1] "raalmkksyvqjytfxqibgwaifxqdc" "enopfcznbrutnwjq"
#[3] "thfzoxgjptsmec" "qrzrdwzj"
#[5] "knkydwnxgfdejcwqnovdv" "fxexzbfpampbadbyeypk"
#[7] "c" "jiukokceniv"
#[9] "qpfifsftlflxwgfhfbzzszl" "foltth"
The following vector marks the positions with 1 in v where entries have more characters than the previous entry.
# The following vector has the same length as v and
# returns 1 at the index position i where
# nchar(v[i]) > nchar(v[i-1])
idx <- c(0, diff(nchar(v)) > 0);
idx;
# [1] 0 0 0 0 1 0 0 1 1 0
If you're just interested in whether there is any entry with more characters than the previous entry, you can do this:
# If you just want to test if there is any position where
# nchar(v[i+1]) > nchar(v[i]) you can do
any(idx == 1);
#[1] TRUE
Or count the number of occurrences:
sum(idx);
#[1] 3

switch case: several equivalent cases expressions in r

In r-programming:
i want to use the same method to handle cases 1 and 10, ie, when the loop is in round 1 and then in 10 again. same for 2 and 11.
is there a way to have several case expressions being handled by the same method
for k == 1 and later also fo 10 it should use the first case and for k ==2 and later 11 it should use the second case. the above code doesn't work.
for(i in 1:x) {
switch(k,
"1", "10"= {
correct <- test[21,1]
current <- test[i-p,1]
if(all(correct == current)){
answers[i-p,k] <- c(1)
} else{
answers[i-p,k] <- c(0)
}
},
"2","11" ={
correct <- test[21,2]
current <- test[i,2]
if(all(correct == current)){
answers[i,k] <- c(1)
} else{
answers[i,k] <- c(0)
}
}
}
the same code for only one case expression works:
for(i in 1:x) {
switch(k,
"1" = {
correct <- test[21,1]
current <- test[i-p,1]
if(all(correct == current)){
answers[i-p,k] <- c(1)
} else{
answers[i-p,k] <- c(0)
}
},
"2" ={
correct <- test[21,2]
current <- test[i,2]
if(all(correct == current)){
answers[i,k] <- c(1)
} else{
answers[i,k] <- c(0)
}
}
}
in java we can use case 1 : case 2 to do that. how is it done in r?
i appreciate your help. alternatively i could also copy the code but don't want to if i can avoid it.
My personal choice would be to remap your k to the overlapping cases. Example:
k<-1:20
kmatch<-(k-1)%%9 +1
# [1] 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 1 2
Then feed kmatch to your case expression
The syntax is along the lines of
f = function(x)
switch(x, "1"=, "10"="first", "11"="eleventh", "none")
Note the equal sign after each named expression, other than the default value.
> f("1")
[1] "first"
> f("10")
[1] "first"
> f("11")
[1] "eleventh"
> f("12")
[1] "none"
This is documented in the third paragraph of the 'Details' section of ?switch.

argument of length 0 in for loop R

I have 2 vectors of numbers. The vector "v" shows when a process starts in seconds. Vector u shows how much time does the proces in the vector u works.
I want to creeate a vector saying how many process are working at each second.
so this toy example: I create a vector "total" thats starts in second 0 (nevermind the end of the vector) and I will save in each position how many processes work in that second. So for example, in the first position of the vector(time 0) my code says I will have 1 process.
v <- c(0,1,2,3,4,5)
u <- c(1.2, 0.1, 1.2, 1, 0.5, 0)
j = 1
total <- rep(0, times = 10)
begin <- integer()
end <- integer()
repeat{
begin<- v[j] +1
end <- begin + u[j]%/%1
for(i in begin:end){
if(total[i] == 0){ total[i] <-1}
else total[i] = total[i] +1
}
if(j ==length(v)) break
j = j+1
}
total
[1] 1 2 1 2 2 1 0 0 0 0
I got this error(not here, in the real case):
Error in begin:end : argument of length 0
(I tried using an if in case begin = end) but "for" should work for only one position.
What can be happening??
You can use seq.int instead of : in this case. For example:
for (a in seq.int(from=3, to=3)) {
print(a)
}
[1] 3

Resources