Поиск индекса для 2-го минимального значения во фрейме данных

#r

#r

Вопрос:

У меня есть фрейм данных df1. Я хотел бы найти индекс для второго наименьшего значения из этого фрейма данных. С помощью функции which.min я смог получить индекс строки для наименьшего значения, но есть ли способ получить индекс для второго наименьшего значения?

 > df1
structure(list(x = c(1, 2, 3, 4, 3), y = c(2, 3, 2, 4, 6), z = c(1, 
4, 2, 3, 11)), row.names = c(NA, -5L), class = c("tbl_df", "tbl", 
"data.frame"))


 >df1
 x    y    z
 1    2    1
 2    3    4
 3    2    2
 4    4    3
 3    6   11
 

Это мой желаемый результат. Например, в x значение 2 в строке 2 является вторым наименьшим значением. Спасибо.

 >df2
x    2
y    2
z    3
 

Комментарии:

1. Проверьте свой вывод на y предмет — похоже, что это должно быть 1 или 3 (или оба?), Нет 2 .

Ответ №1:

Обновленный ответ

Вы можете написать функцию, подобную следующей, используя factor :

 which_min <- function(x, pos) {
  sapply(x, function(y) {
    which(as.numeric(factor(y, sort(unique(y)))) == pos)[1]
  })
}

which_min(df1, 2)
# x y z 
# 2 2 3 
 

Тестирование с другими данными:

 df2 <- df1
df2$new <- c(1, 1, 1, 2, 3)
which_min(df2, 2)
#   x   y   z new 
#   2   2   3   4 
 

Оригинальный ответ

Вместо sort этого вы можете использовать order :

 sapply(df1, function(x) order(unique(x))[2])
# x y z 
# 2 2 3
 

Или вы можете использовать index.return аргумент в sort :

 sapply(df1, function(x) sort(unique(x), index.return = TRUE)$ix[2])
# x y z 
# 2 2 3
 

Комментарии:

1. Если мой x будет равен c (1,1,1,2,3), в то время как y и z остаются неизменными, возможно ли получить результат 2-го наименьшего значения для x равным 4?

Ответ №2:

Вы можете сделать :

 sapply(df1, function(x) which.max(x == sort(unique(x))[2]))

#x y z 
#2 2 3 
 

Или с dplyr :

 library(dplyr)
df1 %>%
  summarise(across(.fns = ~which.max(. == sort(unique(.))[2])))

#      x     y     z
#  <int> <int> <int>
#1     2     2     3
 

Ответ №3:

Другая базовая версия R с использованием rank

 > sapply(df1, function(x) which(rank(unique(x)) == 2))
x y z
2 2 3
 

Ответ №4:

Вы могли бы попробовать что-то вроде:

 sort(unique(unlist(df1)))[2]