简体   繁体   中英

Using purrr map to apply function to selection of columns in DataFrame in dplyr pipeline

I have the following dataframe

test <- data.frame(x = c(6, 9, 3, NA),
                   y = c(3, NA, 2, 3),
                   z = c(6, 3, NA, 5),
                   h = c(NA, 6, 7, 2))

This is the list of columns i would like to iterate over

mylist <- list(test$y, test$z)

I want to change columns "y" and "z" based on the condition in ifelse

Here is my attempt...seems not to work

test <- test %>%
          map_df(mylist, if(is.na(mylist), 0, 1))

(in reality i have a much larger dataframe, this is just test data)

Do I need to use mutate?
Can I use select in the pipeline? like this?

test <- test %>%
          map_df(select(y, z), if(is.na(.), 0, 1))

Here is the expected output

test <- data.frame(x = c(6, 9, 3, NA),
                   y = c(1, 0, 1, 1),
                   z = c(1, 1, 0, 1),
                   h = c(NA, 6, 7, 2))

Thanks for the help

We can use mutate_at to specify columns

library(dplyr)
test %>%  mutate_at(vars(y, z), ~as.integer(!is.na(.)))

#   x y z  h
#1  6 1 1 NA
#2  9 0 1  6
#3  3 1 0  7
#4 NA 1 1  2

Or if ifelse is preferred

test %>% mutate_at(vars(y, z), ~ifelse(is.na(.), 0, 1))

We can also do the same in base R

cols <- c("y", "z")
test[cols] <- as.integer(!is.na(test[cols]))

As the OP mentioned about map from purrr , use map_at

library(tidyverse)
test %>%
    map_at(vars('y', 'z'), ~ +(!is.na(.x))) %>%
    bind_cols
# A tibble: 4 x 4
#       x     y     z     h
#  <dbl> <int> <int> <dbl>
#1     6     1     1    NA
#2     9     0     1     6
#3     3     1     0     7
#4    NA     1     1     2

Or we can do this in base R

test[c('y','z')] <- +(!is.na(test[c('y', 'z')]))
test
#   x y z  h
#1  6 1 1 NA
#2  9 0 1  6
#3  3 1 0  7
#4 NA 1 1  2

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM