2014-09-30 27 views
8

Giả sử tôi có một data.frame với một số cột dữ liệu phân loại và một cột dữ liệu định lượng. Dưới đây là một ví dụ:Tính toán ma trận các khoản tiền

my_data <- structure(list(A = c("f", "f", "f", "f", "t", "t", "t", "t"), 
          B = c("t", "t", "t", "t", "f", "f", "f", "f"), 
          C = c("f","f", "t", "t", "f", "f", "t", "t"), 
          D = c("f", "t", "f", "t", "f", "t", "f", "t")), 
        .Names = c("A", "B", "C", "D"), 
        row.names = 1:8, class = "data.frame") 
my_data$quantity <- 1:8 

Bây giờ my_data trông như thế này:

A B C D quantity 
1 f t f f  1 
2 f t f t  2 
3 f t t f  3 
4 f t t t  4 
5 t f f f  5 
6 t f f t  6 
7 t f t f  7 
8 t f t t  8 

cách thanh lịch nhất để có được một tab chéo/tổng quantity nơi cả hai giá trị =='t' là gì? Đó là, tôi đang tìm kiếm một đầu ra như thế này:

A B C D 
A "?" "?" "?" "?" 
B "?" "?" "?" "?" 
C "?" "?" "?" "?" 
D "?" "?" "?" "?" 

..where giao lộ của x/y là tổng của quantity nơi x=='t'y=='t'. (Tôi chỉ quan tâm đến một nửa bảng này, thực sự, kể từ nửa được nhân đôi)

Vì vậy, ví dụ như giá trị của A/C nên:

good_rows <- with(my_data, A=='t' & C=='t') 
sum(my_data$quantity[good_rows]) 

15 

* Chỉnh sửa: Những gì tôi đã có là:

nodes <- names(my_data)[-ncol(my_data)] 
sapply(nodes, function(rw) { 
    sapply(nodes, function(cl) { 
    good_rows <- which(my_data[, rw]=='t' & my_data[, cl]=='t') 
    sum(my_data[good_rows, 'quantity']) 
    }) 
}) 

Mà cho kết quả mong muốn:

A B C D 
A 26 0 15 14 
B 0 10 7 6 
C 15 7 22 12 
D 14 6 12 20 

tôi thích giải pháp này bởi vì, là rất 'đen', nó khá dễ đọc: hai áp dụng funcs (aka vòng) để đi qua các hàng * cột, tính toán mỗi tế bào, và sản xuất ma trận. Ngoài ra rất nhiều đủ nhanh trên dữ liệu thực tế của tôi (nhỏ: 192 hàng x 10 cột). Tôi không thích nó bởi vì nó có vẻ như rất nhiều dòng. Cảm ơn bạn đã trả lời cho đến nay! Tôi sẽ xem xét và hấp thụ.

+1

Vì bạn đang yêu cầu một cách "thanh lịch" hơn là "bất kỳ" cách nào, bạn sẽ nhớ đăng những gì bạn có bây giờ? Bằng cách đó, chúng tôi không kết thúc viết lại mã bạn đã viết. – shadowtalker

+1

Điểm tốt, chỉnh sửa để hiển thị những gì tôi đã có – arvi1000

Trả lời

6

Hãy thử sử dụng phép nhân ma trận

temp <- (my_data[1:4]=="t")*my_data$quantity 

t(temp) %*% (my_data[1:4]=="t") 

# A B C D 
#A 26 0 15 14 
#B 0 10 7 6 
#C 15 7 22 12 
#D 14 6 12 20 

(Mặc dù điều này có thể là một sự may mắn)

+0

Làm đẹp! Cảm ơn. Đây là một cách để làm cho nó thậm chí còn nhỏ hơn một chút trên trang: 'tf <- my_data [, 1: 4] == 't'; t (tf * my_data $ quantity)% *% tf' – arvi1000

3

Đối với mỗi tên hàng, bạn có thể tạo một vector dat chỉ là các hàng có giá trị bằng t. Sau đó, bạn có thể nhân các giá trị true/false trong tập hợp dữ liệu này với giá trị số lượng của hàng đó (vì vậy nó là 0 khi sai và giá trị số khi đúng), cuối cùng lấy tổng cột.

sapply(c("A", "B", "C", "D"), function(x) { 
    dat <- my_data[my_data[,x] == "t",] 
    colSums((dat[,-5] == "t") * dat[,5]) 
}) 
# A B C D 
# A 26 0 15 14 
# B 0 10 7 6 
# C 15 7 22 12 
# D 14 6 12 20 
+0

Cảm ơn! Cách tiếp cận tương tự như tôi đã có trong tâm trí (với bước 1 là lựa chọn hàng), nhưng bạn tránh thứ hai một cách dễ dàng. Được thăng hạng. – arvi1000

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