问题描述
我有以下 df:
id city uf home money work
34 LA RJ 10 2 2
33 BA TY 7 3 65
32 NY BN 4 5 4
12 SP SD 3 9 7
14 FR DE 1 8 9
17 BL DE 5 10 8
期望的 DF:
id city uf home rank_home money rank_money work rank_work
34 LA RJ 10 1 2 6 2 6
33 BA TY 7 2 3 5 65 1
32 NY BN 4 4 5 4 4 5
12 SP SD 3 5 9 2 7 4
14 FR DE 1 6 8 3 9 2
17 BL DE 5 3 10 1 8 3
我知道这是可能的:
dat$rank_home <- rank(dat$home)
谢谢!!
解决方法
我们可以循环 across
列 'home' 到 'work',应用 rank
,同时通过在 .names
中添加前缀来创建新列,可能还有 select
保持秩序
library(dplyr)
df1 <- df %>%
mutate(across(home:work,~ rank(-.),.names = "rank_{.col}"))
或者可以在循环中执行此操作,通过指定 .after
或 .before
可以更灵活地将列放置在特定位置。请注意,我们使用复合赋值运算符(%<>%
中的 magrittr
)来进行就地赋值
library(magrittr)
library(stringr)
for(nm in names(df)[4:6]) df %<>%
mutate(!!str_c("rank_",nm) := rank(-.data[[nm]]),.after = all_of(nm))
-输出
df
id city uf home rank_home money rank_money work rank_work
1 34 LA RJ 10 1 2 6 2 6
2 33 BA TY 7 2 3 5 65 1
3 32 NY BN 4 4 5 4 4 5
4 12 SP SD 3 5 9 2 7 4
5 14 FR DE 1 6 8 3 9 2
6 17 BL DE 5 3 10 1 8 3
注意:如果列有联系,则默认使用的方法是 "average"
。因此,ties.method
也可以是 rank
中存在联系的参数。
数据
df <- structure(list(id = c(34L,33L,32L,12L,14L,17L),city = c("LA","BA","NY","SP","FR","BL"),uf = c("RJ","TY","BN","SD","DE","DE"),home = c(10L,7L,4L,3L,1L,5L),money = c(2L,5L,9L,8L,10L),work = c(2L,65L,8L)),class = "data.frame",row.names = c(NA,-6L))
,
基本的 R 选项
cbind(
df,setNames(
lapply(-df[-(1:3)],rank),paste0("rank_",names(df)[-(1:3)])
)
)
给予
id city uf home money work rank_home rank_money rank_work
1 34 LA RJ 10 2 2 1 6 6
2 33 BA TY 7 3 65 2 5 1
3 32 NY BN 4 5 4 4 4 5
4 12 SP SD 3 9 7 5 2 4
5 14 FR DE 1 8 9 6 3 2
6 17 BL DE 5 10 8 3 1 3
,
data.table
中的一个可选方法
library(data.table)
new <- paste0("rank_",names(dt[,4:6]))
dt[,(new):=lapply(-.SD,frankv),.SDcols=4:6]