library(glue)
library(tidyverse)
data = crossing(id = c(1:4),q = letters[1:5], nums = c(1:10))
set.seed(25)
data$val = sample(c(NA,"foo", "bar"), nrow(data), prob = c(0.95,0.02,0.03), replace = T)
data = data %>% mutate(q = glue("{q}{nums}")) %>%
select(-nums) %>%
pivot_wider(id_cols = id, names_from = q, values_from = val)
#Output Im looking for
data %>%
select(id,starts_with("a")) %>%
mutate(
a_none = apply(.[,grep("a", names(.))], 1, function(x) all(is.na(x)))
)
I want to create similar columns as b_none, c_none and so on. While posting the question I got an idea to run a loop and got the answer. I'll add that as well.
You can use split.default
to split dataframe based on similar named columns and use imap
from purrr
to get logical values for each group.
library(dplyr)
library(purrr)
result <- split.default(data[-1], sub('\\d+', '', names(data)[-1])) %>%
imap_dfc(~.x %>% transmute(!!paste0(.y, '_none') := rowSums(!is.na(.)) == 0))
result
# a_none b_none c_none d_none e_none
# <lgl> <lgl> <lgl> <lgl> <lgl>
#1 FALSE FALSE TRUE TRUE FALSE
#2 TRUE TRUE TRUE TRUE TRUE
#3 FALSE TRUE TRUE TRUE FALSE
#4 FALSE TRUE TRUE FALSE FALSE
If you want to add this as new columns to your original data you can do:
data <- bind_cols(data, result)
To keep this in base R you can use sapply
instead of imap
:
sapply(split.default(data[-1], sub('\\d+', '', names(data)[-1])),
function(x) rowSums(!is.na(x)) == 0)
for (pattern in letters[1:5]) {
varname = glue("{pattern}_none")
data[[varname]] = apply(data[,grep(pattern, names(data))], 1, function(x) all(is.na(x)))
}
This for loop did the job for me. Any better ideas?
I tried inserting output using dput()
but failed.
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.