【发布时间】:2014-10-21 01:58:17
【问题描述】:
我想要一些关于如何最好地解决这个难题的建议。我有一些方法可以使用手动编写的长手代码来解决它。我觉得好像我需要使用递归函数,但我仍然不太擅长使用它们。我希望这个问题不会太长,我试图在提供足够信息的同时尽可能简洁。对不起,如果它太长了 - 虽然希望有人会感兴趣。
我有一个矩阵mat1
# A B C D E F G
# A 0 2 1 1 0 1 1
# B 0 0 0 1 2 2 1
# C 1 2 0 0 0 2 1
# D 1 1 2 0 1 2 1
# E 2 0 2 1 0 2 1
# F 1 0 0 0 0 0 1
# G 1 1 1 1 1 1 0
这表示行和列中个人之间的竞赛结果。数字是指行中的个人与列中的个人“获胜”的频率。
我希望使用以下标准从 1-7 对个人 A-G 进行排名:
-
对所有其他人的获胜次数(最多获胜应排名 1,最少获胜 7,第二多获胜 2,依此类推)
-
如果获胜次数相同,则排名应基于仅考虑获胜次数相同的个人之间的比赛时获得的获胜次数。
-
如果个人的获胜次数仍然相同,则应随机应用排名。
我意识到这不是一个很好的排名系统,但这不是这里的问题。根据上述方案,排名应该如下:
- 1 - D 或 E - D 和 E 获得并列最高的总冠军 (8),并且在他们之间的比赛中也获得相同的胜利。
- 2 - E 或 D - 随机选择 D 或 E 作为 1 级和 2 级
- 3 - A 或 C - 与 A、B、C、G 并列共 6 胜,在 ABCG 的内容中均获得 4 胜
- 4 - C 或 A - 考虑到 C&A 之间的比赛都有 1 胜,所以随机选择 rank3 和 rank4
- 5 - G - 与 A、B、C、G 并列 6 胜,在 A、B、C、G 之间的比赛中取得 3 胜
- 6 - B - 与 A、B、C、G 并列 6 胜,但在 A、B、C、G 之间的比赛中只有 1 胜
- 7 - F - 在整体获胜矩阵中获胜次数最少
我尝试过的:
storeresults <- vector("list") #use this to store results of the following
第 1 步:使用winsfun 函数(见下文)识别每个人的获胜次数以及获胜次数是否唯一(如 dupes 列所示):
w1 <- winsfun(mat1)
storeresults[[1]] <- w1 #store results
w1 只有“F”的获胜次数是唯一的,因此可以首先排名(第 7):
# wins ranks dupes
#A 6 4.5 TRUE
#B 6 4.5 TRUE
#C 6 4.5 TRUE
#D 8 1.5 TRUE
#E 8 1.5 TRUE
#F 2 7.0 FALSE
#G 6 4.5 TRUE
第 2 步:对于非唯一获胜(即重复排名)的个人,将其子集到矩阵中,仅考虑与其他获胜次数相同的人进行比赛,并在可能的情况下确定新排名。 p>
allSame(w1[,3]) #FALSE - this says that not all wins/ranks are unique so need to subset
s2 <- subsetties(w1) #this just splits the data into groups by number of wins (see below)
w2 <- lapply(s2, winsfun, m=mat1)
storeresults[[2]] <- w2 # store results
w2 可以看出,那些在Step1(“D”和“E”)中获得8胜(最多)的人(“D”和“E”)每个人都赢了一场。它们不能被戏弄分开,因此将随机排名第 1 和第 2。仅考虑彼此之间的比赛时,那些获得 6 场胜利(A、B、C、G)的人的获胜次数是不同的。 “B”和“G”可以分别排在总排名第6和总排名第5。我们需要重新考虑“A”和“C”在相互竞争的情况下:
$`6`
wins ranks dupes
A 4 1.5 TRUE
B 1 4.0 FALSE
C 4 1.5 TRUE
G 3 3.0 FALSE
$`8`
wins ranks dupes
D 1 1.5 TRUE
E 1 1.5 TRUE
第 3 步:在需要的地方重复第 2 步
allSame(w2[[1]][,3]) #FALSE - need to subset again as not everyone has same number of wins
allSame(w2[[2]][,3]) #TRUE - no more action required
s3 <- subsetties(w2[[1]])
w3 <- winsfun(s3[[1]], m=mat1)
storeresults[[3]] <- w3 #store results
w3当考虑“A”和“C”时,他们各有一场胜利,所以现在应该随机排名第二和第三名。它们不能被戏弄分开。
wins ranks dupes
A 1 1.5 TRUE
C 1 1.5 TRUE
allSame(w3[,3]) #TRUE - no more action required - both have same number of wins
第 4 步处理存储的结果
storeresults
# I can manually work out ranks from this, but have yet to work out how to do it in R
以下是上面用到的函数:
计算子集矩阵的获胜和排名的函数
winsfun <- function(m, out=NULL){
if (is.null(out)==F){
m1 <- m[rownames(out),rownames(out)]
wins <- apply(m1, 1, sum)
ranks <- rank(-wins)
dupes <- duplicated(wins)| duplicated(wins, fromLast = T)
df <- data.frame(wins, ranks,dupes)
return(df)
}
else
wins <- apply(m, 1, sum)
ranks <- rank(-wins)
dupes <- duplicated(wins)| duplicated(wins, fromLast = T)
df <- data.frame(wins, ranks,dupes)
return(df)
}
对具有重复等级的行进行子集化的功能
subsetties <- function(df){
df1 <- df[df[,3]==T,]
df1.sp <- split(df1, df1$wins)
return(df1.sp)
}
测试向量的所有元素是否相同的功能
allSame <- function(x) length(unique(x)) == 1
重新创建上述矩阵的代码:
structure(c(0, 0, 1, 1, 2, 1, 1, 2, 0, 2, 1, 0, 0, 1, 1, 0, 0,
2, 2, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 2, 0, 1, 0, 0, 1, 1, 2, 2,
2, 2, 0, 1, 1, 1, 1, 1, 1, 1, 0), .Dim = c(7L, 7L), .Dimnames = list(
c("A", "B", "C", "D", "E", "F", "G"), c("A", "B", "C", "D",
"E", "F", "G")))
我希望这个问题很清楚。我正在尝试找出如何迭代地执行这个算法。我不太确定如何实现这一点,但希望通过长期写出来并提供我一直在使用的功能,这对某人来说可能是显而易见的。额外的一件事是,建议的解决方案最好是普遍适用的(即适用于不同大小的矩阵)。
【问题讨论】:
-
为什么不使用
rowSums和rank?