因素有不同的水平,但我不明白为什么

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

我正在使用 Bradley-Terry 模型对网球比赛的结果进行建模,但遇到了以下错误。当我跑步时:

library(BradleyTerry2)

matches <- read.csv("data/matches.csv")
model <- BTm(cbind(wins1,
                   wins2),
             player1, player2, data=matches)
model

我收到错误消息:

Error in Diff(player1, player2, formula, id, data, separate.ability, refcat,  : 
  'player1$..' and 'player2$..' must be factors with the same levels

数据框“匹配”具有这种格式(可重现的小示例)。

玩家1 玩家2 胜1 赢2
阿加西 费德勒 0 6
阿加西 休伊特 1 0
阿加西 罗迪克 1 0
费德勒 亨曼 3 1
费德勒 休伊特 9 0
费德勒 罗迪克 5 0
亨曼 休伊特 0 2
亨曼 罗迪克 1 1
休伊特 罗迪克 3 2

...等等。任何出现在player1中的名字都会出现在player2中。

我不明白为什么player1和player2的因子有不同的级别?我尝试使用

as.factor
将它们设置为因子,但这不起作用。我还尝试删除
data=matches
并使用
matches$wins1
等作为
BTm
函数的参数,但这也不起作用。现在我有点卡住了,所以欢迎任何想法!谢谢你:)

r r-factor
2个回答
0
投票

看看第一列和第二列中有什么。
因子在内部编码为从 1 开始的连续整数。下面我

unclass
每个因子都是为了获得它们的内部表示。

  • player1
    有两个值,1 和 2;
  • player2
    有两个值,1 和 2;
  • player1
    中,级别
    "Rafael Nadal"
    为第1级,其值为1
  • 但是在
    player2
    中,级别
    "Rafael Nadal"
    是第二个,其值为 2

这是因为每一列都是独立的因素,与其他列没有关系。

lapply(matches[1:2], unclass)
#> $player1
#> [1] 2 2 1
#> attr(,"levels")
#> [1] "Rafael Nadal"  "Roger Federer"
#> 
#> $player2
#> [1] 2 1 1
#> attr(,"levels")
#> [1] "Andy Murray"  "Rafael Nadal"

创建于2023年11月14日

解决方案是获取所有列的所有唯一值,并在创建因子时使用这些唯一值作为级别

在第一条指令后面的代码中,将所有唯一值作为字符串获取。然后使用这些字符串作为其级别创建因子列。

lvls <- matches[1:2] |> unlist() |> as.character() |> unique() matches[1:2] <- lapply(matches[1:2], factor, levels = lvls) # check that now "Rafael Nadal" is always value 2 lapply(matches[1:2], unclass) #> $player1 #> [1] 1 1 2 #> attr(,"levels") #> [1] "Roger Federer" "Rafael Nadal" "Andy Murray" #> #> $player2 #> [1] 2 3 3 #> attr(,"levels") #> [1] "Roger Federer" "Rafael Nadal" "Andy Murray"

创建于2023年11月14日


数据

matches <- structure(list( player1 = structure(c(2L, 2L, 1L), levels = c("Rafael Nadal", "Roger Federer"), class = "factor"), player2 = structure(c(2L, 1L, 1L), levels = c("Andy Murray", "Rafael Nadal"), class = "factor"), wins1 = c(3L, 5L, 4L), wins2 = c(2L, 2L, 3L)), class = "data.frame", row.names = c(NA, -3L))

创建于2023年11月14日


编辑

与此同时,问题中的示例数据集已更改。除了对玩家姓名的引用之外,上面的代码仍然有效并解决了问题。


0
投票
在原始帖子评论的大力帮助下,现在已经解决了......只需确保players1和players2列仅包含相同的玩家(这可能意味着在数据文件中切换一些回合),然后在

as.factor()

player1
 周围使用 
player2

© www.soinside.com 2019 - 2024. All rights reserved.