I'm trying to run an if statement, where I want to run something IF any of 23 values is below a certain value.
test.df<-as.data.frame(c(1:50))
if (test.df[,c(27:50)] <30){ print("hi")}
I get the error that the condition has length > 1 and only the first element will be used. Which is true... Does anyone know how I can test this if statement for 23 values, whithout having to type them one by one?
Thanks!
See the functions all or any, isTRUE and in newer versions of R, isFALSE, where the latter two to some degree takes care of fringe cases of NULLs and NAs.
For your example:
if (all(test.df[,c(27:50)] <30)) {
print("hi")
}
you can try this:
if (any(test.df[,c(27:50)] <30)){ print("hi")}
Related
I am new to R and I have troubles understanding how displaying an index works.
# Find indices of NAs in Max.Gust.SpeedMPH
ind <- which(is.na(weather6$Max.Gust.SpeedMPH))
# Look at the full rows for records missing Max.Gust.SpeedMPH
weather6[ind, ]
My code here works, no problem but I don't understand why weather6[ind] won't display the same thing as weather6[ind, ] . I got very lucky and mistyped the first time.
I apologize in advance that the question might have been posted somewhere else, I searched and couldn't find a proper answer.
So [ is a function just like any other function in R, but we call it strangely. Another way to write it in this case would be:
'[.data.frame'(weather6,ind,)
or the other way:
'[.data.frame'(weather6,ind)
The first three arguments to the function are named x, i and j. If you look at the code, early on it branches with the line:
if (Narg < 3L)
Putting the extra comma tells R that you've called the function with 3 arguments, but that the j argument is "missing". Otherwise, without the comma, you have only 2 arguments, and the function code moves on the the next [ method for lists, in which it will extract the first column instead.
I want to check a list named "answer,if it contains FALSE element,then return a boolean (F),if there is no any FALSE element,in other words all TRUE,return a boolean (T)
here is the code(not good too many lines,but I don't know the easier one)
>answer=c(TRUE,FALSE,FALSE)
>l=length(answer)
>ind <- 1
>t=0
>f=0
>while(ind<(length(answer)+1)){
>ifelse(answer[ind]==TRUE,t<-t+1,f<-f+1)
>ind<-ind+1
>}
>ifelse(f>0,print("False"),print("True"))
This part code could give me right result.BUT it give me twice!!
like this:
[1] "True"
[1] "True"
WHY WHY give me twice...please help me I don't want to use this function so many lines
The reason you get the print twice is that ifelse(f>0,print("False"),print("True")) will first evaluate f>0 (which is TRUE), and then evaluate print("False") (which will result in "False" being printed to the console), and finally the ifelse will return the value of print("False") ("False") which will then be auto-printed to the console (the second print).
To get around the double print you could replace your last line with
> ifelse(f>0,"False","True")
Note however that neither this code or your code is returning booleans, both of them are returning character-strings. If you want a boolean you should instead use
> ifelse(f>0,FALSE,TRUE)
There are however a number of things that could be done to improve this code. You could use a for-loop to iterate directly over the answer vector (eliminating the need for the ind variable. Even better, you could use the fact that R is allowing you to add the value of two booleans (TRUE=1, and FALSE=0), so sum(answer) will give you the number of TRUE-values in the vector.
The easiest way to solve this is doing what baptiste is hinting at all(answer) will evaluate to TRUE if answer only contains TRUE-values, which seems to be what you want.
Here is my code:
>ipo_num_year<- do.call(length,list(as.name(paste0("all_data_align_",year))))
>ipo_num_year
>90
>ipo_num_year<- length(as.name(paste0("all_data_align_",year)))
>ipo_num_year
>1
year is an string object "1999";
In previous code,all_data_align_1999 has been assigned as an list with 90 elements,so the right result is ipo_num_year equals to 90.But the second line makes ipo_num_year equals to 1,it means length() function look the return value of as.name() as an symbol object,so its length is just 1.
Why does the return value of as.name() can not be directly used as the argument of function length()?
And why the first solution works fine?
Some one may ask that why don't you just use length(all_data_align_1999).That is because the year is an loop variable in my code.
Really appreciate your kindly reply!
Instead of as.name you should use get:
length(get(paste0("all_data_align_",year)))
You need to retrieve the object not just the name.
I am a new R user and having some difficulty when trying to rename certain records in a column.
My data have columns named classcode and fish_tl, among others. Classcode is a character value, fish_tl is numeric.
When classcode='OCAL' and fish_tl<20, I need to rename that value of classcode so that it is now "OCALYOY". I don't want to change any of the other records in classcode.
I'm running the following code:
data$classcode<-ifelse(data$classcode=='OCAL'& data$fish_tl<20,
'OCALYOY',data$classcode)
My problem seems to be with the "else" aspect: the code runs fine, and returns 'OCALYOY' as expected, but the other values of classcode have now been converted to numeric (although when I look at the mode of that field, it still returns as "character").
What am I doing wrong?
Thanks very much!
You can make the else part as.character(data$classcode). ifelse has some odd semantics with regard to the classes of the arguments, and it is turning your factor into it's underlying numeric representation. as.character will keep it as a character value.
You may be getting tripped up in a factor vs character issue, though you point out that R thinks it's character. Regardless, wrapping as.character() around your code seems to fix the problem for me:
> ifelse(data$classcode=='OCAL'& data$fish_tl<20,
+ 'OCALYOY',as.character(data$classcode))
#-----
[1] "BFRE" "BFRE" "BFRE" "HARG" "OCALYOY" "OYT" "OYT" "PFUR"
[9] "SPAU" "BFRE" "OCALYOY" "OCAL"
If this isn't it, can you make your question reproducible by adding the output of dput() to your question instead of the text representation?
I've got a function that uses readline to ask people to enter in data. But I'm at a loss as to the best method to insure that the data entered meet my criteria. I'm figuring "if" statements may be the best way to go to check for errors, but I'm not sure how to incorporate them. My attempt at using them is obviously flawed (see below).
As a simple example, 2 of the most likely problems I'm going to run into would be I'd like to insure that at least some value is entered in for x (and if a value is entered for x it is a number) and that V1 and V2 contain the same number of values.
fun<-function(){
T<-readline("What is x" )
if(T=="" | typeof(x)!=numeric)
{print("Input non-aceptable")
T<-readline("What is x ")}
else
V<-readline("Enter 4 values" )
V2<-readline("Enter 4 more values ")
if(length(V1)!=length(V2))
{print("V1 & V2 do not contain equal # of values")
V<-readline("Enter 4 values ")
V<-readline("Enter 4 more values ")}
else
T<-as.numeric(T)
V<-as.numeric(V)
V2<-as.numeric(V2)
return(list(x,V1,V2)
}
As you can see, my hope is to try and spot potential errors before they cause an actual error to happen, and then to give the person an opportunity to re-enter the data. If "if" statements are the way to go, can I get some help on using the correctly?
Thanks!
In R the boolean types TRUE and FALSE can also be represented by T and F. So first off try changing the variables that you have named T to something sensible... like x maybe???
Secondly, in your typeof(x) argument, you called the variable T, so that won't work. In addition there were no quotes around numeric. Try if(!(is.numeric(x)))
Thirdly, your variables are inconsistently named, V and V, and then V1 and V2. Aside from hard to read, it also just won't work.
Lastly, your return statement needs a second closing parenthesis, the function code block needs a closing curly brace.