2015-04-29 12 views
10

Nói rằng tôi có khung dữ liệu này:Làm thế nào để tổng hợp trên đường chéo của khung dữ liệu

 1 2 3 4  
100 8 12 5 14 
99 1 6 4 3 
98 2 5 4 11 
97 5 3 7 2 

Trong khung dữ liệu trên này, các giá trị chỉ đếm có bao nhiêu quan sát đảm nhận (100, 1), (99, 1) vv

Trong ngữ cảnh của tôi, các đường chéo có cùng ý nghĩa:

 1 2 3 4 
100 A B C D 
99 B C D E 
98 C D E F 
97 D E F G 

Làm cách nào để tổng hợp các đường chéo (tức là tổng các chữ cái tương tự) trong khung dữ liệu đầu tiên?

này sẽ tạo ra:

group sum 
A  8 
B  13 
C  13 
D  28 
E  10 
F  18 
G  2 

Ví dụ, D5+5+4+14

+0

Đây có phải là một ma trận hoặc một data.frame? (Ma trận là dễ dàng hơn để thực hiện điều này) –

+0

data.frame, nhưng chuyển đổi nó thành một ma trận và quay trở lại một data.frame như trong câu trả lời của @Ben Bolker làm các trick. – bill999

+0

Tương tự: http://stackoverflow.com/q/27935555/1191259 – Frank

Trả lời

17

Bạn có thể sử dụng row()col() để xác định các mối quan hệ hàng/cột.

m <- read.table(text=" 
    1 2 3 4  
100 8 12 5 14 
99 1 6 4 3 
98 2 5 4 11 
97 5 3 7 2") 

vals <- sapply(2:8, 
     function(j) sum(m[row(m)+col(m)==j])) 

hoặc (như đề xuất trong ý kiến ​​bằng? @thelatemail)

vals <- sapply(split(as.matrix(m), row(m) + col(m)), sum) 
data.frame(group=LETTERS[seq_along(vals)],sum=vals) 

hoặc (@Frank)

data.frame(vals = tapply(as.matrix(m), 
     (LETTERS[row(m) + col(m)-1]), sum)) 

as.matrix() là cần thiết để làm cho split() làm việc một cách chính xác ...

+0

Lý do tại sao người ta cần phải chuyển đổi nó thành ma trận (thay vì để nó trong data.frame) để làm điều này? – bill999

+2

@BenBolker - hàng và col hoạt động trên tất cả các đối tượng "giống ma trận" với 2 chiều bao gồm. ma trận, data.frames, bảng, vv – thelatemail

+0

oh, OK, tôi sai. –

5

Đây là giải pháp sử dụng stack() và.210, mặc dù nó đòi hỏi sự data.frame thứ hai chứa vectơ nhân vật, như trái ngược với các yếu tố (có thể bị buộc với lapply(df2,as.character)):

df1 <- data.frame(a=c(8,1,2,5), b=c(12,6,5,3), c=c(5,4,4,7), d=c(14,3,11,2)); 
df2 <- data.frame(a=c('A','B','C','D'), b=c('B','C','D','E'), c=c('C','D','E','F'), d=c('D','E','F','G'), stringsAsFactors=F); 
aggregate(sum~group,data.frame(sum=stack(df1)[,1],group=stack(df2)[,1]),sum); 
## group sum 
## 1  A 8 
## 2  B 13 
## 3  C 13 
## 4  D 28 
## 5  E 10 
## 6  F 18 
## 7  G 2 
6

Một giải pháp khác sử dụng định nghĩa bgoldst của df1df2

sapply(unique(c(as.matrix(df2))),function(x) sum(df1[df2==x])) 

Cung cấp

#A B C D E F G 
#8 13 13 28 10 18 2 

(Không hoàn toàn định dạng bạn muốn, nhưng có thể không sao ...)

+1

Quên đề cập đến rằng giải pháp giả định rằng bạn đã đặt 'options (stringsAsFactors = FALSE)'. – cryo111

6

Một aggregate biến, tránh giao diện công thức, mà thực sự làm phức tạp vấn đề trong trường hợp này:

aggregate(list(Sum=unlist(dat)), list(Group=LETTERS[c(row(dat) + col(dat))-1]), FUN=sum) 

# Group Sum 
#1  A 8 
#2  B 13 
#3  C 13 
#4  D 28 
#5  E 10 
#6  F 18 
#7  G 2 
Các vấn đề liên quan