Мы могли бы использовать apply
построчно и sort
кадр данных и принимать только первые три значения в каждой строке.
cbind(df[1], t(apply(df[-1], 1, sort, decreasing = TRUE)[1:3, ]))
# pt_id 1 2 3
#1 1 4 3 1
#2 2 5 3 3
#3 3 2 1 1
#4 4 2 1 0
#5 5 5 2 1
Поскольку некоторые значения могут содержать NA
, лучше нам apply
sort
с использованием анонимной функции, а затем принять верхние 3 значения с помощью head
.
cbind(df[1], t(apply(df[-1], 1, function(x) head(sort(x, decreasing = TRUE), 3))))
A tidyverse
- сначала gather
данные, arrange
этов порядке убывания и для каждой строки выберите только первые три значения.Затем мы заменяем столбец injury
на имена столбцов, которые нам нужны, и, наконец, spread
возвращаем данные в широкоформатный формат.
library(tidyverse)
df %>%
gather(injury, value, -pt_id) %>%
arrange(desc(value)) %>%
group_by(pt_id) %>%
slice(1:3) %>%
mutate(injury = 1:3) %>%
spread(injury, value)
# pt_id `1` `2` `3`
# <int> <int> <int> <int>
#1 1 4 3 1
#2 2 5 3 3
#3 3 2 1 1
#4 4 2 1 0
#5 5 5 2 1