#r #rank #dplyr
#r #рейтинг #dplyr
Вопрос:
У меня есть следующий фрейм данных:
dat <- data.frame(id = c("a", "b", "c", "d"),
x1 = c(1, 3, 5, 7),
x2 = c(4, 2, 6, 0),
x3 = c(2, 2, 5, 9))
Теперь я хочу вычислить рейтинг для каждой строки по моим трем x столбцам и хочу сохранить этот результат в моем dat
фрейме данных.
Таким образом, результат может быть сохранен двумя способами:
а) в идеале, должно быть 4 новых столбца с соответствующими рангами или
б) будет новый вложенный столбец, который мне, вероятно, нужно как-то отменить.
Я попробовал следующее, которое, по крайней мере, дает мне столбец списка.
dat %>%
rowwise() %>%
mutate(my_ranks = list(rank(c_across(starts_with("x")))))
Но когда я пытаюсь отменить проверку, это выдает мне ранги, но делает это путем создания новых строк (т. Е. Каждый исходный случай теперь появляется четыре раза). Хотя я предполагаю, что мог бы каким-то образом изменить этот результат с помощью pivot_wider
, мне кажется неправильным следовать этим маршрутом.
Есть идея получше / проще? Спасибо.
Ответ №1:
Мы можем использовать unnest_wider
library(dplyr)
library(tidyr)
library(stringr)
dat %>%
rowwise() %>%
mutate(my_ranks = list(rank(c_across(starts_with("x"))))) %>%
unnest_wider(c(my_ranks)) %>%
rename_at(vars(starts_with("...")), ~ str_replace(., fixed("..."), "rank_x"))
# A tibble: 4 x 7
# id x1 x2 x3 rank_x1 rank_x2 rank_x3
# <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#1 a 1 4 2 1 3 2
#2 b 3 2 2 3 1.5 1.5
#3 c 5 6 5 1.5 3 1.5
#4 d 7 0 9 2 1 3
Другой вариант pmap/as_tibble_row
library(tibble)
library(purrr)
dat %>%
mutate(my_ranks = pmap(select(., starts_with('x')), ~
as_tibble_row(rank(c(...)),
.name_repair = ~ str_c('rank', seq_along(.))))) %>%
unnest(c(my_ranks))
# A tibble: 4 x 7
# id x1 x2 x3 rank1 rank2 rank3
# <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#1 a 1 4 2 1 3 2
#2 b 3 2 2 3 1.5 1.5
#3 c 5 6 5 1.5 3 1.5
#4 d 7 0 9 2 1 3
Это можно сделать более просто с помощью rowRanks
из matrixStats
library(matrixStats)
nm1 <- names(dat)[-1]
dat[paste0('rank', nm1)] <- rowRanks(as.matrix(dat[nm1]), ties.method = 'average')
Комментарии:
1. Ах, конечно, unnest_wider. Спасибо! Это совершенно вылетело у меня из головы. Из любопытства… было бы также решение без этой повторяющейся штуковины со списком?
2. @deschen. Вам не нужен,
as.list
посколькуunnest_wider
он все еще может работать без этого3. @deschen Я добавил
pmap
подход. это могло бы быть быстрее
Ответ №2:
Я думаю, это своего рода tidyverse:
dat %>%
bind_cols(as_tibble(`colnames<-`(t(apply(dat[-1], 1, rank)), paste0("rank_x", 1:3))))
#> id x1 x2 x3 rank_x1 rank_x2 rank_x3
#> 1 a 1 4 2 1.0 3.0 2.0
#> 2 b 3 2 2 3.0 1.5 1.5
#> 3 c 5 6 5 1.5 3.0 1.5
#> 4 d 7 0 9 2.0 1.0 3.0