R: новый столбец, хранящий имя любого из уже существующих на основе условия

#r #dplyr

#r #dplyr

Вопрос:

Скажем, если у нас есть фрейм данных, выглядящий так, как показано ниже:

 a    b     c     d
22   18    25    9
12   24    6     18
37   8     22    25
24   19    12    27
  

Я хотел бы создать два новых столбца из этих:
a) Один столбец, хранящий имя столбца, в котором каждая строка получает свое наибольшее значение.
б) Другой столбец, хранящий его наибольшее значение.

Другими словами, мой желаемый результат будет выглядеть следующим образом:

 a    b     c     d    max_col  max_val
22   18    25    9    c        25
12   24    6     18   b        24
37   8     22    25   a        37
24   19    12    27   d        27
  

Как я должен сделать, чтобы получить это?

Ответ №1:

Работает ли это:

 > library(dplyr)
> df %>% rowwise() %>% mutate(max_col = names(df)[which.max(c_across(a:d))], max_val = max(c_across(a:d)))
# A tibble: 4 x 6
# Rowwise: 
      a     b     c     d max_col max_val
  <dbl> <dbl> <dbl> <dbl> <chr>     <dbl>
1    22    18    25     9 c            25
2    12    24     6    18 b            24
3    37     8    22    25 a            37
4    24    19    12    27 d            27
> 
  

Ответ №2:

Это также может быть достигнуто изменением формы данных и слиянием:

 library(tidyverse)
#Code
newdf <- df %>% mutate(id=row_number()) %>%
  left_join(
    df %>% mutate(id=row_number()) %>%
      pivot_longer(-id) %>%
      group_by(id) %>% filter(value==max(value)[1]) %>%
      rename(max_col=name,max_val=value)
  ) %>% select(-id)
  

Вывод:

    a  b  c  d max_col max_val
1 22 18 25  9       c      25
2 12 24  6 18       b      24
3 37  8 22 25       a      37
4 24 19 12 27       d      27
  

Некоторые используемые данные:

 #Data
df <- structure(list(a = c(22L, 12L, 37L, 24L), b = c(18L, 24L, 8L, 
19L), c = c(25L, 6L, 22L, 12L), d = c(9L, 18L, 25L, 27L)), class = "data.frame", row.names = c(NA, 
-4L))
  

Ответ №3:

Мы можем сделать это эффективным векторизованным способом с max.col помощью from base R — получает индекс позиции максимального значения в строке, который используется для извлечения соответствующего имени столбца [ и pmax возврата max значения для каждой строки

 mcol <- names(df)[max.col(df, 'first')]
mval <- do.call(pmax, df)
df[c('max_col', 'max_val')] <- list(mcol, mval)
  

-вывод

 df
#   a  b  c  d max_col max_val
#1 22 18 25  9       c      25
#2 12 24  6 18       b      24
#3 37  8 22 25       a      37
#4 24 19 12 27       d      27
  

Или используя tidyverse , мы можем использовать то же max.col самое и pmax для получения имен столбцов с максимальным значением в строке и максимальным значением строки

 library(dplyr)
library(purrr)
df %>%
    mutate(max_col = names(cur_data())[max.col(cur_data(), 'first')],
    max_val = invoke(pmax, select(cur_data(), where(is.numeric))))
  

-вывод

 #     a  b  c  d max_col max_val 
# 1 22 18 25  9       c      25
# 2 12 24  6 18       b      24
# 3 37  8 22 25       a      37
# 4 24 19 12 27       d      27
  

данные

 df <- structure(list(a = c(22L, 12L, 37L, 24L), b = c(18L, 24L, 8L, 
19L), c = c(25L, 6L, 22L, 12L), d = c(9L, 18L, 25L, 27L)), 
class = "data.frame", row.names = c(NA, 
-4L))
  

Ответ №4:

Вот еще один базовый параметр R

 inds <- max.col(df)
df <- cbind(df,
  max_col = names(df)[inds],
  max_val = df[cbind(seq_along(inds), inds)]
)
  

что дает

    a  b  c  d max_col max_val
1 22 18 25  9       c      25
2 12 24  6 18       b      24
3 37  8 22 25       a      37
4 24 19 12 27       d      27