Reputation: 73
I hope nobody is getting (too) tired of me. I have given a completely fictional example of the problem below. The error is only given after including a mixture of numeric and string column in a data frame, even if the numeric columns are excluded from the function (not shown below). The function looks in column c for contents of d and vice-versa using grepl and then the should make a new column of the 'yes' and 'no' statements from ifelse. I need to ifelse to return the 'yes' and 'no' after the test but this is the part that is giving the error.
a <- c(5:10)
b <- c(105:110)
c <- c("a","b","c","d","e","f")
d <- c("aa","bc","cd","ff","ee", "gf")
df <- data.frame(a,b,c,d)
newfunction <- function(x, col1, col2, col3, col4){ifelse(((sapply(lapply(x[[col4]], grepl,
x[[col3]]),any)) | (sapply(lapply(x[[col3]], grepl, x[[col4]]),any))), (11 - x[[col1]]), (1 -
x[[col2]]))}
df$new <- apply(df, 1, newfunction, "a", "b", "c", "d")
Error in 11 - x[[col1]] : non-numeric argument to binary operator
Upvotes: 2
Views: 358
Reputation: 11046
You can also vectorize grepl
to simplify your code:
Vgrepl <- Vectorize(grepl)
TF <- Vgrepl(pattern=df$c, x=df$d) | Vgrepl(pattern=df$d, x=df$c)
df$comp <- ifelse(TF, "Yes", "No")
df
# a b c d comp
# 1 5 105 a aa Yes
# 2 6 106 b bc Yes
# 3 7 107 c cd Yes
# 4 8 108 d ff No
# 5 9 109 e ee Yes
# 6 10 110 f gf Yes
Upvotes: 0
Reputation: 1119
Into the question. The best way to approach the question is using the function case_when
from the package dplyr
. I used the function str_detect
from stringr
.
> library(tidyverse)
> library(stringr)
>
> a <- c(5:10)
> b <- c(105:110)
> cc <- c("a","b","c","d","e","f")
> d <- c("aa","bc","cd","ff","ee", "gf")
> df <- data.frame(a, b, cc, d)
>
>
>
> df %>% mutate(case_when((str_detect(cc, d) | str_detect(d, cc)) ~ 'Yes',
+ TRUE ~ 'No'))
a b cc d case_when(...)
1 5 105 a aa Yes
2 6 106 b bc Yes
3 7 107 c cd Yes
4 8 108 d ff No
5 9 109 e ee Yes
6 10 110 f gf Yes
The error is caused since you use apply
which forces the matrix to a character matrix (transforming the numeric values to character). Example,
> apply(df, 2, function(x) x)
a b cc d
[1,] " 5" "105" "a" "aa"
[2,] " 6" "106" "b" "bc"
[3,] " 7" "107" "c" "cd"
[4,] " 8" "108" "d" "ff"
[5,] " 9" "109" "e" "ee"
[6,] "10" "110" "f" "gf"
Some pointers as it seems that you are new to R. First of all, do not use c
as a name it is very commonly used function to combine elements to a vector.
Second, the way the function is written is very hard to read. You should break it up into multiple step to make it easier.
Upvotes: 1