R Объединить имена столбцов в новый столбец при сортировке по их значению

Я пытаюсь объединить строку, которая определяет порядок столбцов по их значению.

set.seed(100)

df <- tibble(id = 1:5,
             col1 = sample(1:50, 5),
             col2 = sample(1:50, 5),
             col3 = sample(1:50, 5)) %>% 
  mutate_at(vars(-id), ~if_else(. <= 20, NA_integer_, .))

# A tibble: 5 x 4
     id  col1  col2  col3
  <int> <int> <int> <int>
1     1    NA    44    NA
2     2    38    23    34
3     3    48    22    NA
4     4    25    NA    48
5     5    NA    NA    43

res <- df %>% 
  add_column(order = c('col2',
                       'col2_col3_co1',
                       'col2_col1',
                       'col1_col3',
                       'col3'))

# A tibble: 5 x 5
     id  col1  col2  col3 order        
  <int> <int> <int> <int> <chr>        
1     1    NA    44    NA col2         
2     2    38    23    34 col2_col3_co1
3     3    48    22    NA col2_col1    
4     4    25    NA    48 col1_col3    
5     5    NA    NA    43 col3 

Мои текущие данные представлены в виде df, а столбец, который я пытаюсь добавить, - это столбец порядка в res. Порядок элементов в строке определяется значением каждого столбца, а также необходимо пропустить NA. Я пытаюсь определить последовательность, которую использует каждый идентификатор для заполнения значения в каждом столбце, поскольку значения представляют собой время в днях. Тем не менее, не все идентификаторы будут иметь значение во всех столбцах, поэтому пропущенные значения отсутствуют. Я обычно работаю в tidyverse, но любое решение или мысли будут высоко оценены.

Всего 1 ответ


Более простой вариант - apply , зациклить строки ( MARGIN = 1 ), удалить элементы NA , order остальные не-NA, использовать индекс, чтобы получить имена столбцов и paste их вместе

df$order <- apply(df[-1], 1, function(x) {x1 <- x[!is.na(x)]
           paste(names(x1)[order(x1)], collapse="_")})
df$order
#[1] "col2"           "col2_col3_col1" "col2_col1"      "col1_col3"      "col3" 

Или используя tidyverse

library(dplyr)
library(tidyr)
library(stringr)
df %>%
   pivot_longer(cols = -id, values_drop_na = TRUE) %>%
   arrange(id,  value) %>%
   group_by(id) %>%
   summarise(order = str_c(name, collapse="_")) %>% 
   right_join(df) %>%
   select(names(df), order)
# A tibble: 5 x 5
#     id  col1  col2  col3 order         
#  <int> <int> <int> <int> <chr>         
#1     1    NA    44    NA col2          
#2     2    38    23    34 col2_col3_col1
#3     3    48    22    NA col2_col1     
#4     4    25    NA    48 col1_col3     
#5     5    NA    NA    43 col3       

Или используя pmap от purrr

library(purrr)
df %>% 
   mutate(order = pmap_chr(select(., starts_with('col')), ~
         {x <- c(...)
         x1 <- x[!is.na(x)]
         str_c(names(x1)[order(x1)], collapse="_")}))

Есть идеи?

10000