Reputation: 165
I have a data frame called 'bank' like below, it has around 40K rows
age job salary marital education targeted default balance housing loan contact day month
58 management 100000 married tertiary yes no 2143 yes no unknown 5 may
duration campaign pdays previous poutcome response
261 1 -1 0 unknown no
I created the following function that checks some conditions and then returns a value that gets added as a new value under a new column called 'new'.
decide <- function(x){
if(x$marital=='married' & x$salary > 60000 & x$housing=='yes'){
return('yes')
}else if(x$marital=='single' & x$salary > 40000 & x$education=='tertiary'){
return('yes')
}else{
return('no')
}
}
Then I would use the below loop to run over all the rows and derive the new value
for(i in 1:nrow(bank)){
person<-bank[i,]
bank[i,'new']<-decide(person)
}
This satisfies my requirement.
However when I try to use an apply function instead of a for loop like below,
bank$new1<-sapply(bank,decide)
it returns the below error
Error: $ operator is invalid for atomic vectors
What is the issue with the apply function I wrote, can I ask you to write the correct apply function that works like the for loop ?
Upvotes: 2
Views: 3278
Reputation: 20095
I think, you can use dplyr::case_when
in such situations where there are multiple conditions will decide value of new
column. The logic will look simpler and neat as:
library(dplyr)
bank %>% mutate(new = case_when(
marital=='married' & salary > 60000 & housing=='yes' ~ 'yes',
marital=='single' & salary > 40000 & education=='tertiary' ~ 'yes',
TRUE ~ 'no'
))
Upvotes: 2
Reputation: 11514
Try something like this:
decide <- function(x){
if(x["cyl"]==6 & x["disp"] > 150){
return('yes')
}else if(x["cyl"] == 8 & x["disp"] > 200){
return('yes')
}else{
return('no')
}
}
apply(mtcars, 1, decide)
Slightly more elegant and efficient:
with(mtcars, ifelse(cyl == 6 & disp > 150, "yes", ifelse(cyl==8 & disp > 200, "no", "no")))
Here, ifelse
works on vectors, which means you do not have to loop through the entire dataframe.
To understand your error, note that the apply
-function would pass a vector to the function, and vectors are not accessed with $. See:
vec <- c("a"=1, "b"=2)
vec
# a b
# 1 2
vec$a
# Error in vec$a : $ operator is invalid for atomic vectors
vec["a"]
# a
# 1
Upvotes: 2