I want function to check if value of count = NA then it will print out the line say that "Not valid" or else it will say "Succees"
order = data.frame(item = c("A","B","C"), count = c(1,2,NA))
check <- function(order){
if (order$count[is.na(order$count),] ){
print(paste(order$item,"not value"))
}
else {
print("success")
}
}
But it generates the errors
I think you could shorten the whole function like so:
# define function:
check <- function(x) {
ifelse(is.na(x), "not value", "success")
}
# input function:
check(order$count)
[1] "success" "success" "not value"
You may try this way
check <- function(order){
if (any(is.na(order$count)) ){
print(paste(order$item[is.na(order$count)],"not value"))
}
else {
print("success")
}
}
check(order)
[1] "C not value"
Reason of error Error in order$count[is.na(order$count), ] : incorrect number of dimensions is that order$count is vector but you call [is.na(order$count), ].
Also, order$count[is.na(order$count)] is NA, it's not appropriate to input as a condition for if statement.
If you want to check items row-wise, you may try
check <- function(order){
for (i in 1:nrow(order)){
if (is.na(order$count[i])) {
print(paste(order$item[i], "not value"))
} else {
print(paste(order$item[i], "success"))
}
}
}
check(order)
[1] "A success"
[1] "B success"
[1] "C not value"
Here is an alternative way:
library(car)
recode(is.na(order$count), "FALSE='success'; TRUE='not valid'")
[1] "success" "success" "not valid"
Related
I don't get any error but I was expecting that when I type an integer that is not 1,2,3,4 the code should enter in else statement and print what is in paste0 function. What is wrong?
escolha <- as.integer(readline(prompt="Enter your choice: "))
if(escolha == 1){
print("Cool you choose addition!")
} else if (escolha == 2) {
print("Cool, you choose subtraction!")
} else if (escolha == 3) {
print("Cool, you choose multiplication!")
} else if (escolha == 4){
print("Cool, you choose division!")
} else{
paste0("It's not possible to use ", escolha," as input.")
escolha<- as.integer(readline(prompt="Choose a valid number (1 a 4): "))
}
num1 <- as.double(readline(prompt="What is the first number? "))
num2 <- as.double(readline(prompt="What is the second number? "))
resultado <- switch (escolha, (num1+num2), (num1-num2), (num1*num2), (num1/num2))
cat("The result is: ", resultado)
paste0() (and paste()) assemble a string and return it. You still need to print the result to the screen with print() or cat(), like this:
cat(paste0("It's not possible to use ", escolha," as input.\n"))
(added the \n at the end, so the readline() prompt that follows will be on a separate line)
I have a value which can be one of 3 strings, or NULL. When the value is NULL the following code does not work
value <- NULL
if( value == "test" ){
print("1")
} else {
print("2")
}
It seems I have to write the code as below to make it work:
if ( !is.null(value) && value== "test" ) {
print("1")
} else {
print("2")
}
Writing it like that however seems unnecessarily complicated and messy.
Is there a cleaner way to do this?
You could surround the condition with isTRUE()
value <- NULL
if ( isTRUE(value == "test") ) {
print("1")
} else {
print("2")
}
# [1] "2"
or replace == with identical():
identical(value, "test")
# [1] FALSE
You can use function setequal in base R:
value <- NULL
setequal(value, "test")
[1] FALSE
How about using %in% operator:
if( "test" %in% value){
print("1")
} else {
print("2")
}
[1] "2"
I am working on optimizing job orders, with a precedence matrix.
For example; job 8 cannot be performed before job 6 is finished. If this is the case, my precedence matrix on position [8,6] shows a one. If there is no precedence relation, for example for position [1,2], then it shows a zero.
In my current code I use the 'next' command to go to the next iteration if the precedence matrix shows a 1. However, the way it is programmed right now it just goes to the next j, while I want it to go to the next 'i' (next job to consider). However, the i is one loop before the if loop where 'next' is used. Is there a way to make it go to the for(i in n:jobs) loop instead of the next for(j in n:jobs)?
Below my current code
# Initialisatie
nJobs = 10
jobDone = rep(FALSE, nJobs)
currentJob = 1;
jobDone[currentJob] = TRUE;
totalFine = 0;
finishingTime = durations[currentProject]
jobOrder = c(currentJob);
jobFines = c(totalFine);
jobIndFines = c(totalFine)
jobTimes = c(finishingTime)
jobIndTimes = c(durations[currentJob])
for(iter in 1:(nJobs-1))
{
bestFine = -1;
bestOrder = -1;
for(i in 1:nJobs)
{
for(j in 1:nJobs){
if(precedences[i,j] == 1){ next } #hoe kom ik nu naar de volgende i ipv de volgende j?
else{
if( ! jobDone[i] )
{
# If this is the first option or the cheapest option, we update the best option
if(bestOrder == -1 || ((finishingTime+durations[i])-deadlines[i])*fines[i] > bestFine)
{
bestFine = ((finishingTime+durations[i])-deadlines[i])*fines[i];
bestOrder = i;
}
}
}
}
}
# Add the best job to the order of jobs
jobDone[bestOrder] = TRUE;
jobOrder[iter+1] = bestOrder;
# Update the current order of projects
fine = ((finishingTime+durations[bestOrder])-deadlines[bestOrder])*fines[bestOrder]
jobIndFines[iter+1] = fine
if (fine>0){
totalFine = totalFine + fine;
}
jobFines[iter+1] = totalFine;
#jobIndFines[iter+1] = totalFine - jobFines[iter];
finishingTime = finishingTime + durations[bestOrder];
jobTimes[iter+1] = finishingTime
jobIndTimes[iter+1] = durations[bestOrder]
}
totalFine
finishingTime
jobOrder
jobFines
jobTimes
jobIndTimes
jobDone
jobIndFines
Thanks a lot!!
Try break.
These code snippets illustrate the difference between next and break.
next restarts the current loop at its next index value:
for (i in 1:2) {
for (j in 1:2) {
print(paste("j =", j))
next
print("Python is better than R at everything.") # Never prints, obviously.
}
print(paste("i =", i))
}
#> [1] "j = 1"
#> [1] "j = 2"
#> [1] "i = 1"
#> [1] "j = 1"
#> [1] "j = 2"
#> [1] "i = 2"
break gets you out of the current loop entirely and passes control to the next statement outside the loop:
for (i in 1:2) {
for (j in 1:2) {
print(paste("j =", j))
break
print("Python is better than R at everything.") # Never prints, obviously.
}
print(paste("i =", i))
}
#> [1] "j = 1"
#> [1] "i = 1"
#> [1] "j = 1"
#> [1] "i = 2"
RStudio provides a nice function View (with uppercase V) to take a look into the data, but with R it's still nasty to get orientation in a large data set. The most common options are...
names(df)
str(df)
If you're coming from SPSS, R seems like a downgrade in this respect. I wondered whether there is a more user-friendly option? I did not find a ready-one, so I'd like to share my solution with you.
Using RStudio's built-in function View, it's white simple to have a variable listing for a data.frame similar to the one in SPSS. This function creates a new data.frame with the variable information and displays in the RStudio GUI via View.
# Better variables view
Varlist = function(sia) {
# Init varlist output
varlist = data.frame(row.names = names(sia))
varlist[["comment"]] = NA
varlist[["type"]] = NA
varlist[["values"]] = NA
varlist[["NAs"]] = NA
# Fill with meta information
for (var in names(sia)) {
if (!is.null(comment(sia[[var]]))) {
varlist[[var, "comment"]] = comment(sia[[var]])
}
varlist[[var, "NAs"]] = sum(is.na(sia[[var]]))
if (is.factor(sia[[var]])) {
varlist[[var, "type"]] = "factor"
varlist[[var, "values"]] = paste(levels(sia[[var]]), collapse=", ")
} else if (is.character(sia[[var]])) {
varlist[[var, "type"]] = "character"
} else if (is.logical(sia[[var]])) {
varlist[[var, "type"]] = "logical"
n = sum(!is.na(sia[[var]]))
if (n > 0) {
varlist[[var, "values"]] = paste(round(sum(sia[[var]], na.rm=T) / n * 100), "% TRUE", sep="")
}
} else if (is.numeric(sia[[var]])) {
varlist[[var, "type"]] = typeof(sia[[var]])
n = sum(!is.na(sia[[var]]))
if (n > 0) {
varlist[[var, "values"]] = paste(min(sia[[var]], na.rm=T), "...", max(sia[[var]], na.rm=T))
}
} else {
varlist[[var, "type"]] = typeof(sia[[var]])
}
}
View(varlist)
}
My recommendation is to store that as a file (e.g., Varlist.R) and whever you need it, just type:
source("Varlist.R")
Varlist(df)
Again please take note of the uppercase V using as function name.
Limitation: When working with data.frame, the listing will not be updated unless Varlist(df) is run again.
Note: R has a built-in option to view data with print. If working with pure R, just replace the View(varlist) by print(varlist). Yet, depending on screen size, Hmisc::describe() could be a better option for the console.
I recently posed this question and thankfully was pointed to withRestarts() which seems pretty awesome and powerful to me :-) Now I'm eager to understand R's error handling capabilities in a bit more detail.
Actual questions
What is the recommended usage of simpleCondition()? Never used it before, but I thought it might be useful for designing custom errors and warnings that are in fact "true" conditions. Could it be used to build a database of specific conditions for which specific handlers are available?
Is there a way to "freeze" a certain state of the entire R workspace and return to it to restart a computation at a certain point? I'm aware of save.image(), but AFAIU, this doesn't store the "state" of the search path (search() or searchpaths()).
For those interested
Two code examples
illustration of my current use of withRestarts in dependence on this blog post
attempt to define a "custom condition"
I'd appreciate any comments/suggestion on what to do better ;-)
Example 1
require("forecast")
autoArimaFailsafe <- function(
x,
warning=function(w, ...) {
message("autoArimaFailsafe> warning:")
message(w)
invokeRestart("donothing")},
error=function(e, ...) {
message("autoArimaFailsafe> error:")
message(e)
invokeRestart("abort")}
) {
withRestarts(
out <- tryCatch(
{
expr <- expression(auto.arima(x=x))
return(eval(expr))
},
warning=warning,
error=error
),
donothing=function(...) {
return(eval(expr))
},
abort=function(...) {
message("aborting")
return(NULL)
}
)
}
data(AirPassengers)
autoArimaFailsafe(x=AirPassengers)
autoArimaFailsafe(x="a")
Example 2
require("forecast")
autoArimaFailsafe <- function(
x,
warning=function(w, ...) {
message("autoArimaFailsafe> warning")
invokeRestart("donothing")},
error=function(e, ...) {
message("autoArimaFailsafe> error")
invokeRestart("abort")},
condition=function(cond, ...) {
out <- NULL
message(cond)
condmsg <- conditionMessage(c=cond)
condclass <- class(cond)
if (any(class(cond) == "simpleWarning")) {
out <- warning(w=cond)
} else if (any(class(cond) == "simpleError")) {
out <- error(e=cond)
} else if (any(class(cond) == "simpleCondition")) {
if (condmsg == "invalid class: character") {
out <- invokeRestart("forcedefault")
}
}
return(out)
}
) {
withRestarts(
out <- tryCatch(
{
expr <- expression(auto.arima(x=x))
if (class(x) == "character") {
expr <- signalCondition(
simpleCondition("invalid class: character",
call=as.call(expr))
)
}
return(eval(expr))
},
condition=condition
),
donothing=function(...) {return(eval(expr))},
abort=function(...) {
message("aborting")
return(NULL)
},
forcedefault=function(...) {
data(AirPassengers)
expr <- expression(auto.arima(x=AirPassengers))
return(eval(expr))
}
)
}
autoArimaFailsafe(x=AirPassengers)
autoArimaFailsafe(x=NULL)
autoArimaFailsafe(x="a")
This post references the inspiration for R's condition handling.
For 1., I think of simpleCondition as illustrating how one can construct custom conditions, e.g,.
myCondition <-
function(message, call=NULL, type=c("overflow", "underflow", "zero"))
{
type <- match.arg(type) # only allowed types past here
class <- c(type, "my", "condition")
structure(list(message = as.character(message), call = call),
class = class)
}
is a constructor for making custom conditions
> myCondition("oops")
<overflow: oops>
> myCondition("oops", type="underflow")
<underflow: oops>
These conditions can be used in tryCatch or withCallingHandlers
xx <- tryCatch({
signalCondition(myCondition("oops", type="underflow"))
}, underflow=function(e) {
message("underflow: ", conditionMessage(e))
NA # return value, assigned to xx
})
These are S3 classes so can have a linear hierarchy -- bad and worse are both subclasses of error.
myError <-
function(message, call=NULL, type=c("bad", "worse"))
{
type <- match.arg(type)
class <- c(type, "error", "condition")
structure(list(message=as.character(message), call=call),
class=class)
}
One might also create an error that extends the 'simpleError' S3 class as cond <- simpleError("oops"); class(cond) = c("myerr", class(cond)
With tryCatch we just get access to a single handler, the first (in the sense described on ?tryCatch) to match the class of condition
tryCatch({
stop(myError("oops", type="worse"))
}, bad = function(e) {
message("bad error: ", conditionMessage(e))
}, worse = function(e) {
message("worse error: ", conditionMessage(e)) # here's where we end up
}, error=function(e) {
message("error: ", conditionMessage(e))
})
With withCallingHandlers we have the opportunity to hit multiple handlers, provided we don't invoke a restart
withCallingHandlers({
stop(myError("oops", type="bad"))
}, bad = function(e) { # here...
message("bad error: ", conditionMessage(e))
}, worse = function(e) {
message("worse error: ", conditionMessage(e))
}, error=function(e) { # ...and here...
message("error: ", conditionMessage(e))
}) # ...and top-level 'error'
withCallingHandlers({
x <- 1
warning(myError("oops", type="bad"))
"OK"
}, bad = function(e) { # here, but continue at the restart
message("bad warning: ", conditionMessage(e))
invokeRestart("muffleWarning")
}, worse = function(e) {
message("worse warning: ", conditionMessage(e))
})
I'm not so sure about your question 2; I think this is the situation that calling handlers are designed to address -- the entire frame where the condition was invoked is poised waiting to continue, once you invoke the restart.