use*_*307 5 algorithm optimization performance chess r
嗨,您好!
我正在尝试计算6种不同技能(C1,C2,... C6)中的一些玩家的玩家国际象棋排名.我有一个巨大的游戏数据框(数据)看起来像这样(头(数据)).在这个游戏中,一个人(用户)选择在另外两个人(p1/p2)之间获胜.
row.names user p1 p2 skill win looser time
---------------------------------------------------------
2 KE CL HK C1 CL HK 433508371
25 KE HK JT c1 HK JT 433508401
35 KE AB JT C1 AB JT 433508444
110 NF IP HE C1 HE IP 433508837
78 NF IP AS C1 AS IP 433508848
82 NF IT CV C1 CV IT 433508860
Run Code Online (Sandbox Code Playgroud)
在另一个表格(old_users)中,我跟踪所有玩家在6种技能中的国际象棋得分(head(old_users))
user C1 C2 C3 C4 C5 C6
1 BD 1200 1200 1200 1200 1200 1200
2 NF 1200 1200 1200 1200 1200 1200
3 CH 1200 1200 1200 1200 1200 1200
4 AR 1200 1200 1200 1200 1200 1200
5 AS 1200 1200 1200 1200 1200 1200
6 MS 1200 1200 1200 1200 1200 1200
Run Code Online (Sandbox Code Playgroud)
算法 该算法在for循环中一次一行地运行数据,每次查看第i行.该算法将查找p1和p2的得分数据,检索两个玩家得分的技能.然后根据谁获胜或失败来计算他们的新分数,然后用相应的新排名更新old_users单元格.
我需要做什么 我需要尽快做到这一点,并且数据帧数据现在只有24个玩家的6000多行,需要一段时间才能完成.
我试图计算我当前的for循环,这给出了以下几次太多的时间.
user system elapsed
104.72 0.28 118.02
Run Code Online (Sandbox Code Playgroud)
问题
当前for循环
for (i in 1:dim(data)[1]) {
tmp_data<-data[i,] #Take the i'th row in data
score_col<-which(colnames(old_users)==tmp_data$skill) #find old_user column which matched the skill played
winners_old_data<-old_users[which(old_users$user==tmp_data$win),] #Fetch winner's old scores
loosers_old_data<-old_users[which(old_users$user==tmp_data$looser),] #Fetch looser's old scores
winners_new_score=winners_old_data[score_col]+(32/2)*(1-0+(1/2)*((loosers_old_data[score_col]-winners_old_data[score_col])/200)) #Calculate the winner's new score
loosers_new_score=loosers_old_data[score_col]+(32/2)*(0-1+(1/2)*((winners_old_data[score_col]-loosers_old_data[score_col])/200)) #Calculate the looser's new score
old_users[old_users$user==winners_old_data[[1]],score_col]<-winners_new_score #update cell in old_users
old_users[old_users$user==loosers_old_data[[1]],score_col]<-loosers_new_score #update cell in old_users
}
Run Code Online (Sandbox Code Playgroud)
要播放的数据
https://drive.google.com/file/d/0BxE_CHLUGoS0WlczUkxLM3VtVjQ/edit?usp=sharing
很感谢任何形式的帮助
谢谢!
// HK
你发布的数据太小了!想想我必须安装一些东西才能解压它......!如果您可以发布更大的数据,我将能够测试我的建议有多有用。
我建议您将用户数据转换为一个矩阵,其中 ids 作为行名,技能作为列名。为什么?
通过正常索引访问数据而不是which( == )到处使用,您可能会获得小幅速度提升。或者至少它会让你的代码更具可读性。
更重要的是,矩阵内的值的改变是在内存中就地完成的;而使用 data.frame 时,我认为您的代码每次都会创建全新的对象,这一定很耗时。
# read and transform your data
data <- read.csv("data.txt", header = FALSE)
names(data) <- c("user", "p1", "p2", "skill", "win", "looser", "time")
users <- data.matrix(read.csv("users.txt", header = FALSE, row.names = 1))
colnames(users) <- paste("C", 1:6)
for (i in 1:nrow(data)) {
game <- data[i,]
winner.old <- users[game$win, game$skill]
looser.old <- users[game$looser, game$skill]
winner.new <- winner.old + 32/2 * (1 - 0 + (1/2) * (looser.old-winner.old) / 200)
looser.new <- looser.old + 32/2 * (0 - 1 + (1/2) * (winner.old-looser.old) / 200)
users[game$win, game$skill] <- winner.new
users[game$looser, game$skill] <- looser.new
}
Run Code Online (Sandbox Code Playgroud)
是不是更容易阅读呢?希望它也会快一点,请测试并告诉我。或者提供我们可以使用的更大的数据集。谢谢。