Получите имя первого и второго самых низких значений в столбцах и их имена

Предположим, у меня есть data.table вот так:

testdt <- data.table(col1 = c(1, 2, 3), col2=c(1.1, 1.9, 3.1), col3=c(1, 2.2, 3))
testdt

A data.table: 3 × 3
col1    col2    col3
<dbl>   <dbl>   <dbl>
1   1.1 1.0
2   1.9 2.2
3   3.1 3.0

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

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

A data.table: 3 × 8
col1    col2    col3    min_col    min_value    second_col    second_value    diff 
<dbl>   <dbl>   <dbl>   <chr>      <dbl>        <chr>         <dbl>           <dbl>
1       1.1     1.0     col1       1            col2          1.1             0.1
2       1.9     2.2     col2       1.9          col1          2               0.1
3       3.1     3.0     col1       3            col2          3.1             0.1

Итак, я начал с получения минимального имени и значения столбца:

testdt[, min_col := colnames(.SD)[max.col(-.SD, ties.method = "first")], .SDcols=c("col1", "col2", "col3")]
testdt[, min_value := pmin(col1, col2, col3)]

Но я не знаю, есть ли какой-нибудь способ получить остальное, что мне нужно, то есть второе самое низкое имя столбца и значение.

Запуск PHP на IIS без использования программы установки веб-платформы
Запуск PHP на IIS без использования программы установки веб-платформы
Установщик веб-платформы, предлагаемый компанией Microsoft, перестанет работать 31 декабря 2022 года. Его закрытие привело к тому, что мы не можем...
Оптимизация React Context шаг за шагом в 4 примерах
Оптимизация React Context шаг за шагом в 4 примерах
При использовании компонентов React в сочетании с Context вы можете оптимизировать рендеринг, обернув ваш компонент React в React.memo сразу после...
Библиотека для работы с мороженым
Библиотека для работы с мороженым
Лично я попрощался с операторами print() в python. Без шуток.
Настройка шаблона Metronic с помощью Webpack и Gulp
Настройка шаблона Metronic с помощью Webpack и Gulp
Я пишу эту статью, чтобы поделиться тем, как настроить макет Metronic с помощью Sass, поскольку Metronic предоставляет так много документации, и они...
Уроки CSS 6
Уроки CSS 6
Здравствуйте дорогие читатели, я Ферди Сефа Дюзгюн, сегодня мы продолжим с вами уроки css. Сегодня мы снова продолжим с так называемых классов.
Что такое Css? Для чего он используется?
Что такое Css? Для чего он используется?
CSS, или "Каскадные таблицы стилей", - это язык стилей, используемый в веб-страницах. CSS является одним из основных инструментов веб-разработки...
1
0
54
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

С frankv:

library(data.table)
testdt[
  , min2_col := colnames(.SD)[apply(.SD, 1, \(x) which(frankv(x, ties.method = "dense") == 2)[1])],
       .SDcols=c("col1", "col2", "col3")
  ][
    , min2_value := unique(apply(.SD, 1, \(x) x[frankv(x, ties.method = "dense") == 2])),
       .SDcols=c("col1", "col2", "col3")
    ][
      , diff := min2_value - min_value
    ][]

   col1 col2 col3 min_col min_value min2_col min2_value diff
1:    1  1.1  1.0    col1       1.0     col2        1.1  0.1
2:    2  1.9  2.2    col2       1.9     col1        2.0  0.1
3:    3  3.1  3.0    col1       3.0     col2        3.1  0.1
Ответ принят как подходящий

Другой подход (не самый красивый, но выполняет свою работу)

# create q row_id
testdt[, id := .I]
# melt to long, order by id and value
dt.melt <- melt(testdt, id.vars = "id")[order(id, value), ]
# summarise by id
dt.melt <- dt.melt[, .(min_col = variable[1], 
            min_value = value[1],
            second_col = variable[!value == value[1]][1],
            second_val = value[!value == value[1]][1]), 
        by = .(id)]
# calcuate differences
dt.melt[, diff := second_val - min_value]
# merge
cbind(testdt, dt.melt[, -1])
#    col1 col2 col3 id min_col min_value second_col second_val diff
# 1:    1  1.1  1.0  1    col1       1.0       col2        1.1  0.1
# 2:    2  1.9  2.2  2    col2       1.9       col1        2.0  0.1
# 3:    3  3.1  3.0  3    col1       3.0       col2        3.1  0.1

Я начал с этого подхода, но он действительно казался немного «грязным». Тем не менее, спасибо за ответ!

abudis 13.02.2023 12:19

На самом деле это решение работает быстрее на очень большом наборе данных. Вместо этого я приму это.

abudis 13.02.2023 15:56

Другие вопросы по теме