在 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
这里有一个
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"
另一种迭代方式可能是:
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")
具有
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