如何在 R 中通过数值对排名列表进行加权

问题描述 投票:0回答:3

在 R 中,我想根据人们的排名偏好以及他们的表现将项目分配给他们。假设我有 5 个项目和 3 个人。在这种情况下,三个人都想要项目 A,因为这是他们的首选,但 Anna 应该得到它,因为她的绩效得分最高。现在她不在等式中,James 和 Billy 都在争夺 Billy 应该得到的项目 B,因为他有更好的绩效衡量标准。我怎么能在 R 中做到这一点?我会在现实中有更多的项目和人。

Project Rank Person Performance 
A        1   Billy   95
B        2   Billy   95
C        3   Billy   95
D        4   Billy   95
E        5   Billy   95
A        1   Anna    97
B        2   Anna    97
C        3   Anna    97
D        5   Anna    97
E        4   Anna    97
A        1   James   92
B        2   James   92
C        4   James   92
D        3   James   92
E        5   James   92
r ranking weighted
3个回答
1
投票

这里有一个

for
循环的方法。首先,根据性能(和 Person,如果几个具有相同的性能)分组。第一个应该是性能最好的。

然后,在

for
循环中,迭代选择排名最低的项目,并为其他人移除那个。

library(dplyr)
l <- df %>% 
  mutate(perf_rank = dense_rank(-Performance)) %>% 
  group_split(perf_rank, Person)

choice = setNames(character(length(l)), unique(df$Person[order(-df$Performance)]))
for(i in seq_along(l)){
  tmp <- l[[i]]
  choice[i] <- tmp$Project[which.min(tmp$Rank)]
  l <- lapply(l, \(x) subset(x, x$Project != choice[i]))
}  
choice
# Anna Billy James 
#  "A"   "B"   "D" 

0
投票

另一种迭代方式可能是:

res <- data.frame(Person = unique(x$Person), Project = NA)

while(any(is.na(res$Project))) {
  i <- which(x$Person %in% res$Person[is.na(res$Project)]) #Person which have no Project
  i <- i[!x$Project[i] %in% res$Project[!is.na(res$Project)]] #Potential Projects of those Persons which are not assigned to a person
  i <- i[x$Rank[i] == min(x$Rank[i])] #What is the best rank
  i <- i[which.max(x$Performance[i])] #Who has the best rank
  res$Project[match(x$Person[i], res$Person)] <- x$Project[i] #Assign project to that person
}

res
#  Person Project
#1  Billy       B
#2   Anna       A
#3  James       D

数据:

x <- read.table(header=TRUE, text="Project Rank Person Performance 
A        1   Billy   95
B        2   Billy   95
C        3   Billy   95
D        4   Billy   95
E        5   Billy   95
A        1   Anna    97
B        2   Anna    97
C        3   Anna    97
D        5   Anna    97
E        4   Anna    97
A        1   James   92
B        2   James   92
C        4   James   92
D        3   James   92
E        5   James   92")

0
投票

具有

purrr::reduce
的迭代解决方案:

library(dplyr)
library(purrr)

df %>%
  arrange(desc(Performance), Person, Rank) %>%
  group_split(Person) %>%
  reduce(~ bind_rows(.x, slice_head(filter(.y, !Project %in% .x$Project), n = 1)),
         .init = tibble(Project = character(0)))

# # A tibble: 3 × 4
#   Project  Rank Person Performance
#   <chr>   <int> <chr>        <int>
# 1 A           1 Anna            97
# 2 B           2 Billy           95
# 3 D           3 James           92
© www.soinside.com 2019 - 2024. All rights reserved.