Преобразование матрицы, включающее первое и второе по величине значения построчно - PullRequest
0 голосов
/ 27 августа 2018

У меня есть матрица mat:

#sample data
set.seed(123)
mat <- t(sapply(1:5, function(x) round(sample(10:30, 6))))

mat
16   25   17   29   27   10
21   27   20   18   26   17
24   21   11   26   14   10
16   29   26   22   20   25
23   24   20   28   14   12

Я хочу заменить каждую строку максимумом этой строки (это легко), но я также хочу заменить максимальное значение строки на секунду этой строкинаибольшее значение (это не так просто).Мой желаемый результат будет:

res
29   29   29   27   29   29
27   26   27   27   27   27 
26   26   26   24   26   26
29   26   29   29   29   29
28   28   28   24   28   28

Например, 29 - самое большое значение в строке 1, и оно происходит в позиции 4;второе по величине значение - 27. Итак, я хочу строку 29 с 27 в позиции 4. И затем, конечно, сделать это для всех строк.

Моя попытка:

# the easy part
res <- matrix(apply(mat, 1, max), nrow=nrow(mat), ncol=ncol(mat))

# my attempt at the hard part
to_replace <- apply(mat, 1, which.max)
whos_2nd <- apply(mat, 1, function(x) which(order(x, decreasing = TRUE) == 2))

res[cbind(1:nrow(mat), to_replace)] <- mat[cbind(1:nrow(mat), whos_2nd)]

Что-то не так с apply в строке "whos_2nd", и я не могу понять это.

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

Спасибо за помощь!

Ответы [ 2 ]

0 голосов
/ 27 августа 2018

Другая базовая возможность R с использованием apply с ifelse

t(apply(mat, 1, function(x) ifelse(x == max(x), sort(unique(x), decr = T)[2], max(x))))
#     [,1] [,2] [,3] [,4] [,5] [,6]
#[1,]   29   29   29   27   29   29
#[2,]   27   26   27   27   27   27
#[3,]   26   26   26   24   26   26
#[4,]   29   26   29   29   29   29
#[5,]   28   28   28   24   28   28
0 голосов
/ 27 августа 2018

Вы можете сделать это за один звонок apply:

t(apply(mat, MAR = 1, function(x){
  max_index <- which.max(x)
  max_value <- max(x)
  sec_value <- sort(unique(x), decreasing = TRUE)[2]
  x <- replace(x, TRUE, max_value)
  x[max_index] <- sec_value
  x
}))
#      [,1] [,2] [,3] [,4] [,5] [,6]
# [1,]   29   29   29   27   29   29
# [2,]   27   26   27   27   27   27
# [3,]   26   26   26   24   26   26
# [4,]   29   26   29   29   29   29
# [5,]   28   28   28   24   28   28
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...