对数据框中选定的多个列进行排名,然后将排名数据添加为新列
Rank selected multiple columns in a dataframe and then add rank data as new columns
示例数据如下所示:
players <- seq(1:10)
mean_K <- round(runif(10,1,10),2)
mean_D <- round(runif(10,0,10),2)
mean_A <- round(runif(10,0,10),2)
d <- cbind(players, mean_K, mean_A, mean_D)
d <- as_tibble(d)
d
输出:
# A tibble: 10 x 4
players mean_K mean_A mean_D
<dbl> <dbl> <dbl> <dbl>
1 1 3.58 9.21 3.4
2 2 3.8 0.49 1.33
3 3 2.47 2.29 1.72
4 4 1.52 7.25 6.11
5 5 8.73 3.98 8.08
6 6 8.08 9.77 3.88
7 7 3.97 4.52 9.93
8 8 2.84 6.83 9.57
9 9 3.87 0.35 5.32
10 10 2.82 3.8 3.09
我想做的是同时对选定的列进行排名,我尝试使用 apply :
apply(d[,2:4], 2, rank)
输出:
mean_K mean_A mean_D
[1,] 5 9 4
[2,] 6 2 1
[3,] 2 3 2
[4,] 1 8 7
[5,] 10 5 8
[6,] 9 10 5
[7,] 8 6 10
[8,] 4 7 9
[9,] 7 1 6
[10,] 3 4 3
但后来我被卡住了,我怎样才能将所有新的排名列添加到数据框 d?我想知道是否可以使用 dplyr 管道 %>%?
我想要的输出可能如下所示:
players mean_K mean_K_ranking mean_D mean_D_ranking mean_A mean_A_ranking
1 1 3.58 5 3.40 4 9.21 9
2 2 3.80 6 1.33 1 0.49 2
3 3 2.47 2 1.72 2 2.29 3
4 4 1.52 1 6.11 7 7.25 8
5 5 8.73 10 8.08 8 3.98 5
6 6 8.08 9 3.88 5 9.77 10
7 7 3.97 8 9.93 10 4.52 6
8 8 2.84 4 9.57 9 6.83 7
9 9 3.87 7 5.32 6 0.35 1
10 10 2.82 3 3.09 3 3.80 4
我们可以分配。在这里,我们使用 lapply
遍历列(如果 type
中存在一些差异,则 lapply
保留它,而 apply
转换为 matrix
和那些只有一种类型)
lst1 <- lapply(d[2:4], rank)
d[paste0(names(lst1), "_ranking")] <- lst1
或使用tidyverse
library(dplyr)
d <- d %>%
mutate(across(starts_with('mean'), rank, .names = "{.col}_ranking"))
或者可以使用 purrr
中的 imap
来按预期
对列进行排序
library(purrr)
library(stringr)
d %>%
select(starts_with('mean_')) %>%
imap_dfc(~ tibble(!! .y := .x,
!!str_c(.y, '_ranking') := rank(.x))) %>%
bind_cols(d %>%
select(players), .)
示例数据如下所示:
players <- seq(1:10)
mean_K <- round(runif(10,1,10),2)
mean_D <- round(runif(10,0,10),2)
mean_A <- round(runif(10,0,10),2)
d <- cbind(players, mean_K, mean_A, mean_D)
d <- as_tibble(d)
d
输出:
# A tibble: 10 x 4
players mean_K mean_A mean_D
<dbl> <dbl> <dbl> <dbl>
1 1 3.58 9.21 3.4
2 2 3.8 0.49 1.33
3 3 2.47 2.29 1.72
4 4 1.52 7.25 6.11
5 5 8.73 3.98 8.08
6 6 8.08 9.77 3.88
7 7 3.97 4.52 9.93
8 8 2.84 6.83 9.57
9 9 3.87 0.35 5.32
10 10 2.82 3.8 3.09
我想做的是同时对选定的列进行排名,我尝试使用 apply :
apply(d[,2:4], 2, rank)
输出:
mean_K mean_A mean_D
[1,] 5 9 4
[2,] 6 2 1
[3,] 2 3 2
[4,] 1 8 7
[5,] 10 5 8
[6,] 9 10 5
[7,] 8 6 10
[8,] 4 7 9
[9,] 7 1 6
[10,] 3 4 3
但后来我被卡住了,我怎样才能将所有新的排名列添加到数据框 d?我想知道是否可以使用 dplyr 管道 %>%?
我想要的输出可能如下所示:
players mean_K mean_K_ranking mean_D mean_D_ranking mean_A mean_A_ranking
1 1 3.58 5 3.40 4 9.21 9
2 2 3.80 6 1.33 1 0.49 2
3 3 2.47 2 1.72 2 2.29 3
4 4 1.52 1 6.11 7 7.25 8
5 5 8.73 10 8.08 8 3.98 5
6 6 8.08 9 3.88 5 9.77 10
7 7 3.97 8 9.93 10 4.52 6
8 8 2.84 4 9.57 9 6.83 7
9 9 3.87 7 5.32 6 0.35 1
10 10 2.82 3 3.09 3 3.80 4
我们可以分配。在这里,我们使用 lapply
遍历列(如果 type
中存在一些差异,则 lapply
保留它,而 apply
转换为 matrix
和那些只有一种类型)
lst1 <- lapply(d[2:4], rank)
d[paste0(names(lst1), "_ranking")] <- lst1
或使用tidyverse
library(dplyr)
d <- d %>%
mutate(across(starts_with('mean'), rank, .names = "{.col}_ranking"))
或者可以使用 purrr
中的 imap
来按预期
library(purrr)
library(stringr)
d %>%
select(starts_with('mean_')) %>%
imap_dfc(~ tibble(!! .y := .x,
!!str_c(.y, '_ranking') := rank(.x))) %>%
bind_cols(d %>%
select(players), .)