2015-02-18 22 views
5

Đây là một ví dụ nhỏ. Trong tập dữ liệu lớn hơn của tôi, tôi có nhiều năm dữ liệu và số lượng quan sát cho mỗi nhóm (div) không phải lúc nào cũng bằng nhau.quan sát xếp hạng dplyr trên các biến

Ví dụ dữ liệu:

set.seed(1) 
df<-data.frame(
    year = 2014, 
    id = sample(LETTERS[1:26], 12), 
    div = rep(c("1", "2a", "2b"), each=4), 
    pts = c(9,7,9,3,7,5,3,7,2,7,7,1), 
    x = c(10,12,11,7,7,5,4,12,4,6,7,2) 
) 

df

# year id div pts x 
#1 2014 G 1 9 10 
#2 2014 J 1 7 12 
#3 2014 N 1 9 11 
#4 2014 U 1 3 7 
#5 2014 E 2a 7 7 
#6 2014 S 2a 5 5 
#7 2014 W 2a 3 4 
#8 2014 M 2a 7 12 
#9 2014 L 2b 2 4 
#10 2014 B 2b 7 6 
#11 2014 D 2b 7 7 
#12 2014 C 2b 1 2 

Tôi muốn để xếp hạng dữ liệu này mà cá nhân trong div 1 được xếp hạng cao hơn div 2a/2b, và trong vòng div 1 cá nhân được xếp hạng 1,2,3,4 dựa trên số 'pts' cao nhất theo sau là số 'x' cao nhất.

Cá nhân trong div 2a và div 2b nên được xếp hạng riêng lẻ cũng dựa trên cùng một tiêu chí. Điều này sẽ giống như sau:

df %>% 
    group_by(div) %>% 
    arrange(desc(pts), desc(x)) %>% 
    mutate(position = row_number(div)) 


# year id div pts x position 
#1 2014 N 1 9 11  1 
#2 2014 G 1 9 10  2 
#3 2014 J 1 7 12  3 
#4 2014 U 1 3 7  4 
#5 2014 M 2a 7 12  1 
#6 2014 E 2a 7 7  2 
#7 2014 S 2a 5 5  3 
#8 2014 W 2a 3 4  4 
#9 2014 D 2b 7 7  1 
#10 2014 B 2b 7 6  2 
#11 2014 L 2b 2 4  3 
#12 2014 C 2b 1 2  4 

Tuy nhiên, tôi muốn tạo cột/biến cuối cùng là một thứ hạng khác. Điều này sẽ xếp hạng tất cả các cá nhân trong div 1 cao hơn 2a/2b, nhưng 2a/2b là bằng nhau. tức là các cá nhân là 1 trong 2a/2b bây giờ sẽ nhận được 5,5, những cá nhân được xếp hạng 2 bây giờ sẽ nhận được 7,5. Luôn có số lượng cá nhân bằng nhau trong div2a và div2b trong suốt nhiều năm.

Nó sẽ giống như thế này:

# year id div pts x position final 
#1 2014 N 1 9 11  1 1.0 
#2 2014 G 1 9 10  2 2.0 
#3 2014 J 1 7 12  3 3.0 
#4 2014 U 1 3 7  4 4.0 
#5 2014 M 2a 7 12  1 5.5 
#6 2014 E 2a 7 7  2 7.5 
#7 2014 S 2a 5 5  3 9.5 
#8 2014 W 2a 3 4  4 11.5 
#9 2014 D 2b 7 7  1 5.5 
#10 2014 B 2b 7 6  2 7.5 
#11 2014 L 2b 2 4  3 9.5 
#12 2014 C 2b 1 2  4 11.5 

tôi cần phải tìm một giải pháp lý tưởng dplyr. Ngoài ra, nó cần phải khái quát đến năm mà số lượng cá nhân trong 'div1' có thể thay đổi và số lượng cá nhân trong div2a/div2b thay đổi (mặc dù chiều dài (div2a) == length (div2b) luôn).

Trả lời

7

Đây là cách tôi muốn làm điều đó:

library(data.table) 
dt = as.data.table(df) 

dt[order(-pts, -x), rank.init := 1:.N, by = div] 

dt[, div.clean := sub('(\\d+).*', '\\1', div)] 
setorder(dt, div.clean, rank.init) 

dt[, rank.final := mean(.I), by = .(div.clean, rank.init)] 
setorder(dt, div, rank.final) 
# year id div pts x rank.init div.clean rank.final 
# 1: 2014 N 1 9 11   1   1  1.0 
# 2: 2014 G 1 9 10   2   1  2.0 
# 3: 2014 J 1 7 12   3   1  3.0 
# 4: 2014 U 1 3 7   4   1  4.0 
# 5: 2014 M 2a 7 12   1   2  5.5 
# 6: 2014 E 2a 7 7   2   2  7.5 
# 7: 2014 S 2a 5 5   3   2  9.5 
# 8: 2014 W 2a 3 4   4   2  11.5 
# 9: 2014 D 2b 7 7   1   2  5.5 
#10: 2014 B 2b 7 6   2   2  7.5 
#11: 2014 L 2b 2 4   3   2  9.5 
#12: 2014 C 2b 1 2   4   2  11.5 
+0

Cảm ơn - cả hai câu trả lời đều tuyệt vời. Các vấn đề như thế này khuyến khích tôi làm quen với 'data.table' – jalapic

+0

nữa - chỉ cần làm rõ, nếu muốn thực hiện điều này trong nhiều năm đồng thời trong cùng một dt, thì' by = div' cần phải là 'by =. (div, năm) '? – jalapic

+0

@jalapic có, và bạn có thể cần phải sửa đổi 'có nghĩa là' cuối cùng, tùy thuộc vào chính xác bạn muốn làm gì trong nhiều năm – eddi

5

@ câu trả lời Eddi là đã rất tốt đẹp. Tôi chỉ muốn minh họa bằng cách sử dụng chức năng frank() từ phiên bản phát triển của data.table, v1.9.5, có thể tính toán xếp hạng trên vectơ, danh sách, dữ liệu.frames hoặc data.tables.

# from @eddi's 
setDT(df)[, div.clean := sub('(\\d+).*', '\\1', div)] 

df[, position := frank(.SD, -pts, -x, ties.method="first"), by=div] 
df[, final := frank(.SD, div.clean, position, ties.method="average")] 

Điều này cũng giữ nguyên thứ tự ban đầu, nếu điều đó quan trọng.

Tôi sẽ chuyển đổi thành dplyr cho bạn.

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