提问人:Ollie 提问时间:11/14/2023 最后编辑:Ollie 更新时间:11/15/2023 访问量:43
因素有不同的层次,但我不明白为什么
Factors have different levels but I don't understand why
问:
我正在使用 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
数据帧“matches”具有此格式(小型可重现示例)。
玩家 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
答:
0赞
Rui Barradas
11/15/2023
#1
看看你在第一列和第二列中有什么。
因子在内部编码为从 1 开始的连续整数。下面我每个人为了得到他们的内部代表。unclass
player1
有两个值,1 和 2;player2
有两个值,1 和 2;- 在级别中为 1st,其值为 1
player1
"Rafael Nadal"
; - 但是在级别是 2 号,它的值是 2。
player2
"Rafael Nadal"
这是因为每一列都是一个单独的因子,与另一列无关。
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赞
Ollie
11/15/2023
#2
在原始帖子评论的大力帮助下,它现在已经解决了......只需要确保 players1 和 players2 列只包含相同的玩家(这可能意味着在数据文件中切换某个回合),然后使用 around 和 .as.factor()
player1
player2
评论
levels(df$player1)
levels(df$player2)
factor()
levels(matches$player1)
levels(matches$player2)