Home > Enterprise >  Get vector of column names depending on logicals of same dataframe
Get vector of column names depending on logicals of same dataframe

Time:07-06

I have a named dataframe containig logicals with missings and I want to get a vector with the column names where values are TRUE (going down the rows and, if multiple TRUEs in one row, going from left to right). Here an example:

df <- data.frame(a= c(FALSE, NA, TRUE, TRUE),
                 b= c(TRUE, FALSE, FALSE, NA),
                 c= c(TRUE, TRUE, NA, NA))
df
#       a     b    c
# 1 FALSE  TRUE TRUE
# 2    NA FALSE TRUE
# 3  TRUE FALSE   NA
# 4  TRUE    NA   NA

expected <- c("b", "c", "c", "a", "a")

Going from first to last row we see TRUE in the first row. Here are multiple TRUEs, thus we go from left to right and get "b" and "c". In second tow we get "c", and so on.

How to do this (in an elegant way)?

CodePudding user response:

You can do in base R:

pos <- which(t(df) == TRUE, arr.ind = TRUE)
names(df)[pos[, "row"]]
[1] "b" "c" "c" "a" "a"

CodePudding user response:

You can also try using apply

unlist(apply(df, 1, function(x){na.omit(names(df)[x])}))

[1] "b" "c" "c" "a" "a"

CodePudding user response:

Here is a tidyverse way:

library(dplyr)
library(tidyr)

vector <- df %>% 
  mutate(across(, ~case_when(.==TRUE ~ cur_column()), .names = 'new_{col}')) %>%
  unite(New_Col, starts_with('new'), na.rm = TRUE, sep = ', ') %>% 
  separate_rows(New_Col) %>% 
  pull(New_Col)

Or:

library(dplyr)
library(tidyr)

df %>% 
  mutate(across(, ~case_when(.==TRUE ~ cur_column()))) %>% 
  pivot_longer(everything()) %>% 
  na.omit() %>% 
  pull(value)
[1] "b" "c" "c" "a" "a"

CodePudding user response:

Another possible solution, based on purrr::pmap:

library(tidyverse)

pmap(df, ~ names(df)[c(...)] %>% na.omit) %>% unlist

#> [1] "b" "c" "c" "a" "a"

CodePudding user response:

You can use %%(modulo) to identify the column indices.

names(df)[(which(t(df)) - 1) %% ncol(df)   1]

# [1] "b" "c" "c" "a" "a"
  • Related