2014-10-01 12 views
5

Xin chào!R - Tối ưu hóa tốc độ và xếp hạng cờ vua

Tôi đang cố gắng tính toán xếp hạng cờ vua của người chơi cho một số người chơi trong 6 kỹ năng khác nhau (C1, C2, ... C6). Tôi có một dataframe rất lớn (dữ liệu) của trò chơi được chơi mà trông giống như thế này (đầu (dữ liệu)). Trong trò chơi này một người (người dùng) chọn giữa hai người khác (p1/p2) để giành chiến thắng.

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 

Trong bảng khác (old_users) Tôi theo dõi tất cả người chơi cờ vua-điểm trong 6 kỹ năng (đầu (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          

Thuật toán Thuật toán chạy qua một dữ liệu hàng tại một thời điểm trong một vòng lặp, mọi lúc nhìn vào hàng thứ i. Thuật toán sẽ tra cứu dữ liệu điểm số của p1 và p2, lấy lại điểm số của hai người chơi cho kỹ năng đã chơi. Sau đó, tính toán điểm số mới của họ dựa trên những người thắng hoặc thua và sau đó cập nhật ô old_users với thứ hạng mới tương ứng.

Những gì tôi cần làm Tôi cần thực hiện điều này càng nhanh càng tốt và với dữ liệu dataframe hiện có 6000 dòng cho 24 người chơi cần một thời gian để chạy.

Tôi đã cố gắng thời gian cho vòng lặp hiện tại của tôi, cung cấp cho các lần sau đây là quá nhiều.

user system elapsed 
104.72  0.28 118.02 

Câu hỏi

  1. Tại sao thuật toán này mất thời gian quá lâu để chạy qua? Có bất kỳ lệnh nào là xấu để có trong vòng-vòng vv vv?
  2. Làm thế nào tôi có thể đạt được những gì tôi muốn một cách nhanh hơn?

hiện tại cho vòng

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 
     } 

dữ liệu để chơi với

https://drive.google.com/file/d/0BxE_CHLUGoS0WlczUkxLM3VtVjQ/edit?usp=sharing

Bất kỳ sự giúp đỡ rất nhiều đánh giá cao

Cảm ơn bạn!

// HK

+0

"người thua cuộc" không "thua". Dù sao, bạn không cần 'cái', chỉ là câu lệnh so sánh. Điều này trông giống như một công việc cho SQL, vì vậy bạn có thể muốn xem các gói 'sqldf' và các gói tương tự. –

+1

Vấn đề là bạn cho mỗi trò chơi mới chơi cần phải biết số điểm hiện tại của người chơi phù hợp. Đây là vấn đề cờ vua. Vì vậy, nếu trong trò chơi số X một chơi với một số điểm hiện tại thấp nhịp đập một chơi với một số điểm hiện tại cao. Sau đó, người được đánh giá thấp sẽ đạt được nhiều điểm hơn để đánh bại số điểm cao hơn. – user4098307

+1

Trong trường hợp đó, bạn chỉ cần chạy hai bản ghi tìm kiếm (một cho mỗi người chơi), và đó là những gì phần mềm cơ sở dữ liệu cho. –

Trả lời

2

Dữ liệu bạn đăng là rất nhỏ! Để nghĩ rằng tôi đã phải cài đặt một cái gì đó để unrar nó ...! Nếu bạn có thể xin vui lòng gửi một dữ liệu lớn hơn nhiều, tôi sẽ có thể kiểm tra đề nghị của tôi hữu ích như thế nào.

Tôi khuyên bạn nên chuyển dữ liệu người dùng thành ma trận có id là tên và kỹ năng làm tên. Tại sao?

  1. Bạn có thể nhận được cải thiện tốc độ nhỏ bằng cách truy cập dữ liệu qua lập chỉ mục bình thường thay vì sử dụng which(==) ở mọi nơi. Hoặc ít nhất nó sẽ làm cho mã của bạn dễ đọc hơn nhiều.

  2. Quan trọng hơn, thay đổi giá trị trong ma trận được thực hiện tại chỗ một cách khôn ngoan; trong khi với một data.frame, tôi nghĩ rằng mã của bạn tiếp tục tạo ra toàn bộ đối tượng mới mỗi lần, mà phải tốn thời gian.


# 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 
} 

Không phải là nó dễ dàng hơn nhiều để đọc? Hy vọng rằng nó sẽ được một chút nhanh hơn là tốt, xin vui lòng kiểm tra và cho tôi biết. Hoặc cung cấp một tập dữ liệu lớn hơn chúng tôi có thể chơi cùng. Cảm ơn.

+1

Lần đầu tiên tôi nhìn thấy bất cứ ai sử dụng 'data.matrix' Tôi nghĩ rằng nó không bao giờ rời khỏi tập tin trợ giúp. Tôi đã tự hỏi nó có thể hữu ích ở đâu. –

Các vấn đề liên quan