Apply function parse_number for multiple variables depending on variable name

312 views Asked by At

I would like to test whether a number is written in a field of the data frame depending on the name of the variable.

Assume following data

dat <- data.frame(a_1=c(1,2,1,0,2), b_2=c(1,2,1,0,2), c_0=c(1,2,1,0,2))

The results should be new columns that test whether the number that is included in the variable name (i.e., 1, 2, 0 from a_1, b_2, c_0) is included in the field of the data frame, if possible in a new column and indicated by a 1 (0 otherwise).

So, the result should look like that.

  a_1 b_2 c_0 a_1test b_2test c_0test
1   1   1   1 1       0       0
2   2   2   2 0       1       0
3   1   1   1 1       0       0
4   0   0   0 0       0       1
5   2   2   2 0       1       0

Until know I did this individually:

 dat$a_1test <- ifelse(dat$a_1==parse_number("a_1"), 1, 0)
 dat$b_2test <- ifelse(dat$b_2==parse_number("b_2"), 1, 0)
 dat$c_0test <- ifelse(dat$c_0==parse_number("c_0"), 1, 0)

Is there a simpler solution? (this is an easy example, I have more than 100 lines to do that operation for.

2

There are 2 answers

0
stefan On BEST ANSWER

Using purrr::reduce you can loop over the names of your df to achieve the desired result:

dat <- data.frame(a_1=c(1,2,1,0,2), b_2=c(1,2,1,0,2), c_0=c(1,2,1,0,2))

f_help <- function(x, y) { 
  x[[paste0(y, "test")]] <- ifelse(x[[y]] == readr::parse_number(y), 1, 0)
  x
}
purrr::reduce(names(dat), f_help, .init = dat)
#>   a_1 b_2 c_0 a_1test b_2test c_0test
#> 1   1   1   1       1       0       0
#> 2   2   2   2       0       1       0
#> 3   1   1   1       1       0       0
#> 4   0   0   0       0       0       1
#> 5   2   2   2       0       1       0
0
akrun On

We can use base R

dat[paste0(names(dat), 'test')] <- +(dat == as.integer(sub("\\D+",
             "", names(dat))[col(dat)]))

-output

dat
#  a_1 b_2 c_0 a_1test b_2test c_0test
#1   1   1   1       1       0       0
#2   2   2   2       0       1       0
#3   1   1   1       1       0       0
#4   0   0   0       0       0       1
#5   2   2   2       0       1       0