After checking condition need to add a column and assign a value - r

I have a data frame(final1) with few columns
for(i in final1$Total.Tyres)
{
if(final1$Total.Tyres[i] >= 500){
final1$flag_tyres[i]<-1
} else {
final1$flag_tyres[i]<-0
}
}
I need to check if tires are greater than 500 if so need to assign 1 adding a new column flag_tyres
when tried the above code give me below error
Error in if (final1$Total.Tyres[i] >= 500) { :
missing value where TRUE/FALSE needed

You may want to consider vectorizing your code instead of using for to loop over the rows, saves you typing, hassle and is faster:
final1$flag_tyres <- ifelse(final1$Total.Tyres >= 500, 1, 0)

Simple mistake, should be 1:length(final1$Total.Tyres) in the outer loop. Alternatively, you could vectorize the result, as already answered.

Related

How do you generate the output of for loop and if statement into a list or vector?

I have tried the following but the output brings an argument stating,
Error in append("0") : argument "values" is miss
for (rowz in final_data$Ingridients) {
Cobalt_row<-lst()
if (sum(str_detect(rowz, 'Cobalt'))>0) {
Cobalt_row.append(1)
} else {
Cobalt_row<-append(0)
}
print(Cobalt_row)
}
I intended to loop through the list and generate a boolean of ones and twos depending on
whether or not I had the value.
Please help
Without the data, I can't test it, but this should work:
Cobalt_row<-lst()
k <- 1
for (rowz in final_data$Ingridients) {
Cobalt_row[[k]] <- ifelse(str_detect(rowz, 'Cobalt'), 1, 0)
k <- k+1
}
or even simpler if you need a list:
Cobalt_row <- as.list(as.numeric(str_detect(final_data$Ingredients, "Cobalt")))

How to include logical checks in a custom function

I have written a custom function that performs a mathematical transformation on a column of data with the inputs being the data and one other input (temperature). I would like to have 2 different logical checks. The first one is whether or not any values in the column exceed a certain threshold, because the transformation is different above and below the threshold. The second is a check if the temperature input is above a certain value and in that case, to deliver a warning that values above the threshold are unusual and to check the data.
Right now, I have the function written with a series of if/else statements. However, this a warning that it is only using the first element of the string of T/F statements. A simplified example of my function is as follows:
myfun = function(temp,data) {
if(temp > 34){
warning('Temperature higher than expected')
}
if (data > 50) {
result = temp*data
return(result)
} else if(data <= 50) {
result = temp/data
return(result)
}
}
myfun(temp = c(25,45,23,19,10), data = c(30,40,NA,50,10))
As you can see, because it is only using the first value for the if/else statements, it does not properly calculate the return values because it doesn't switch between the two versions of the transformation. Additionally, it's only checking if the first temp value is above the threshold. How can I get it to properly apply the logical check to every value and not just the first?
-edit-simplified the function per #The_Questioner's suggestion and changed < 50 to <= 50.
The main issue with your code is that you are passing all the values to the functions as vectors, but then are doing single element comparisons. You need to either pass the elements one by one to the function, or put some kind of vectorized comparison or for loop into your function. Below is the for loop approach, which is probably the least elegant way to do this, but at least it's easy to understand what's going on.
Another issue is that NA's apparently need to be handled in the data vector before passing to any of your conditional statements, or you'll get an error.
A final issue is what to do when data = 50. Right now you have conditional tests for greater or less than 50, but as you can see, the 4th point in data is 50, so right now you get an NA.
myfun = function(temp,data) {
result <- rep(NA,length(temp))
for (t in 1:length(temp)) {
if(temp[t] > 34) {
warning('Temperature higher than expected')
if (!is.na(data[t])) {
if (data [t] > 50) {
result[t] <- temp[t]*data[t]
} else if(data[t] < 50) {
result[t] <- temp[t]/data[t]
}
}
} else {
if (!is.na(data[t])) {
if (data[t] > 50) {
result[t] <- temp[t]*data[t]
} else if(data[t] < 50) {
result[t] <- temp[t]/data[t]
}
}
}
}
return(result)
}
Output:
> myfun(temp = c(25,45,23,19,10), data = c(30,40,NA,50,10))
[1] 0.8333333 1.1250000 NA NA 1.0000000

R function length error message

I made a function to to compute the sum of I(Xi
my.ecdf<- function(x,y) {
if(!is.null(dim(y)))
stop("y has more than one dimension")
n<-length(x)
i<-1:n
p<-if(x[i]<y) 1 else {
0
}
(sum(p))/n
}
But when I run it with input (rnorm(11),6), I get this error:
Warning message:
In if (x[i] < y) 1 else { :
the condition has length > 1 and only the first element will be used
Any ideas? I'm new to r so sorry if it's something obvious. (Also I don't want to use the for loop)
There are a number of issues in your code:
1) Whats the point of x[1:length(x)] in the if statement? Right now these are meaningless and can be dropped:
n<-length(x)
i<-1:n
x[i]
2) If statement accepts a logical argument not a vector of logical, you can consider adding all() any() etc like
if(all(x < y)) 1 else {0}
or use ifelse() statement for the assignment
3) Finally from what I can understand you overcomplicate things and the whole thing can be written as one-liner:
sum(x < y)/length(x)
This is a logical vector of the same length as y
is.null(dim(y))
You're using it as a logical test. An object with a length greater than 1 can't be unambiguously interpreted by the if statement. Consider if (TRUE FALSE FALSE TRUE) <do something>. When should you do that thing?
If you want to make sure y doesn't have more than one dimension, do
if(length(dim(y)) > 1){
stop("message")
}

If else statement doesnt work and cant figure out why

Can someone explain why my else part of my function doesnt work?
finaltable;
Duplicate Digit6 Digit7 Digit7a Digit7b Digit7c Digit7d Dead carried
137401 137401 2017681 2017681 2018047 2018047 2018219 1 0
137402 137402 2017731 2017731 2017856 2017856 2018279 0 0
w <- function(finaltable){
if (nchar(tail(names(finaltable),1) >= nchar(c("carried")))) {(ncol(finaltable)-2)
} else (ncol(finaltable)-1)
}
I have colnames (Duplicate, digit, dead, carried). I want the last digit column. Depending on the day I will have tail(names(finaltable),1 = carried or dead. If carried, I need to subtract two columns, if dead then one column. However, I have several columns named dead or carried that are associated with number. However, the max dead will be is dead99. Thus I have a max of 6 characters.
I then want to dump my function into below.
SubtractROW<-finaltable[paste(ROWS), w(finaltable)];
BarCODEtable<-cbind(ILS,ROWS,SubtractROW);
BarCODEtable;
Here's your function, corrected so that it returns the right values:
w <- function(finaltable){
if (nchar(tail(names(finaltable),1)) >= nchar("carried")) {
(ncol(finaltable)-2)
} else {
ncol(finaltable)-1
}
}
w(finaltable) # if last column is dropped
#[1] 7
The problem was in your if statement, where a ) was at the wrong place. Running your original if statement results in:
nchar(tail(names(finaltable),1) >= nchar(c("carried")))
#[1] 4
where it should be
nchar(tail(names(finaltable),1)) >= nchar("carried")
#[1] FALSE
But as commented above, you could more easily use
max(which(grepl("^Digit", names(finaltable))))
instead.

If statement with multiple actions in R

I would like to write an if statement of the following form:
a=5
b=2
la<-function(a,b){
if(a>3){a}
else{b}
}
Now what I would like to do is not only have one action in the if statement but two, for example:
if(a>3){a and c<<-1000}
In this case to return 'a' and also write 1000 in variable 'c'
My question is how to put in multiple actions after the if statement.
You should use the semicolon
if(a>3){c<-1000;a}
The last statement is the return value.
EDIT This works for multiple statements, too. You can omit the semicolon if you use line breaks, as in
if(a>3) {
c<-1000
d<-1500
a
} else {
e <- 2000
b
}
EDIT: this should work with ifelse too. You would have to keep in mind that you are operating on a vector, though. Here is an example:
x <- sample(10, 100, replace=TRUE)
ifelse(x>3, {y <- 100; y+x}, x)
This adds 100 only to those elements of x that are larger than 3.

Resources