2013-04-15 40 views
11

Tôi có 3 khung dữ liệu (hàng: trang web, cột: tên loài) của các loài phong phú trong các trang web. Số hàng giống nhau, nhưng số cột khác nhau vì không phải tất cả các loài đều nằm trong cả ba khung dữ liệu. Tôi muốn kết hợp chúng thành một khung dữ liệu với nhiều loại giống hệt nhau được tổng kết lại. Ví dụ:Kết hợp dữ liệu.frames tổng hợp các giá trị của các cột giống hệt nhau trong R

data.frame1

 Sp1 Sp2 Sp3 Sp4 
site1 1 2 3 1 
site2 0 2 0 1 
site3 1 1 1 1 

data.frame2

 Sp1 Sp2 Sp4 
site1 0 1 2 
site2 1 2 0 
site3 1 1 1 

data.frame3

 Sp1 Sp2 Sp5 Sp6 
site1 0 1 1 1  
site2 1 1 1 5 
site3 2 0 0 0 

Những gì tôi muốn có một cái gì đó như:

 Sp1 Sp2 Sp3 Sp4 Sp5 Sp6 
site1 1 4 3 3 1 1 
site2 2 5 0 1 1 5 
site3 4 2 1 2 0 0 

Tôi đoán tôi sẽ phải làm việc với hợp nhất, nhưng cho đến nay nỗ lực của tôi đã thất bại để có được những gì tôi muốn.

Mọi trợ giúp đều được đánh giá cao.

+0

Có thể 'tổng hợp' tốt hơn' hợp nhất'? –

Trả lời

18

Tôi muốn sử dụng plyr 's rbind.fill như thế này:

pp <- cbind(names=c(rownames(df1), rownames(df2), rownames(df3)), 
         rbind.fill(list(df1, df2, df3))) 

# names Sp1 Sp2 Sp3 Sp4 Sp5 Sp6 
# 1 site1 1 2 3 1 NA NA 
# 2 site2 0 2 0 1 NA NA 
# 3 site3 1 1 1 1 NA NA 
# 4 site1 0 1 NA 2 NA NA 
# 5 site2 1 2 NA 0 NA NA 
# 6 site3 1 1 NA 1 NA NA 
# 7 site1 0 1 NA NA 1 1 
# 8 site2 1 1 NA NA 1 5 
# 9 site3 2 0 NA NA 0 0 

Sau đó, tổng hợp với plyr'sddply như sau:

ddply(pp, .(names), function(x) colSums(x[,-1], na.rm = TRUE)) 
# names Sp1 Sp2 Sp3 Sp4 Sp5 Sp6 
# 1 site1 1 4 3 3 1 1 
# 2 site2 2 5 0 1 1 5 
# 3 site3 4 2 1 2 0 0 
+3

Tôi đã có một giải pháp trong tâm trí và tôi hứa nó không phải là thanh lịch này. +1 –

+0

hoạt động hoàn hảo! unfortunatelly không thể bỏ phiếu: ( – eugenego

+0

@eugenego Bạn có thể đánh dấu dấu kiểm bên cạnh giải pháp trả lời tốt nhất câu hỏi. –

2

Một thay thế cho Arun của câu trả lời: Tạo một 'mẫu' mảng với tất cả các cột bạn sẽ cần

Rgames> bbar<-data.frame('one'=rep(0,3),'two'=rep(0,3),'three'=rep(0,3)) 
Rgames> bbar 
    one two three 
1 0 0 0 
2 0 0 0 
3 0 0 0 

Sau đó, cho mỗi khung dữ liệu của bạn như

Rgames> bar1<-data.frame('one'=c(1,2,3),'two'=c(4,5,6)) 
Rgames> bar1 
    one two 
1 1 4 
2 2 5 
3 3 6 

Tạo một dataframe mở rộng:

Rgames> newbar1<-bbar 
Rgames> for (jj in names(bar)) newbar1[[jj]]<-bar[[jj]] 
Rgames> newbar1 
    one two three 
1 1 4 0 
2 2 5 0 
3 3 6 0 

Sau đó tổng hợp tất cả như khung dữ liệu mở rộng. Vụng về nhưng đơn giản.

6

Một cách khác là sử dụng melt/cast từ reshape2. Dưới đây là một ví dụ không phức tạp:

df1 <- read.table(header=T, text=" 
    Sp1 Sp2 Sp3 Sp4 
    site1 1 2 3 1 
    site2 0 2 0 1 
    site3 1 1 1 1") 

df2 <- read.table(header=T, text=" 
     Sp1 Sp2 Sp4 
site1 0 1 2 
site2 1 2 0 
site3 1 1 1") 

df3 <- read.table(header=T, text=" 
     Sp1 Sp2 Sp5 Sp6 
site1 0 1 1 1  
site2 1 1 1 5 
site3 2 0 0 0") 

df1$site <- rownames(df1) 
df2$site <- rownames(df2) 
df3$site <- rownames(df3) 

DF <- rbind(melt(df1,id="site"),melt(df2,id="site"),melt(df3,id="site")) 
dcast(data=DF,formula=site ~ variable,fun.aggregate=sum) 

    site Sp1 Sp2 Sp3 Sp4 Sp5 Sp6 
1 site1 1 4 3 3 1 1 
2 site2 2 5 0 1 1 5 
3 site3 4 2 1 2 0 0 

Nói tóm lại, chúng tôi sử dụng trang web chỉ định như là một biến bổ sung, và chuyển đổi từng dataframe sang định dạng dài, sau đó gia nhập chúng vào một dataframe duy nhất. Cái sau chứa tất cả các giá trị trong định dạng dài. Với dcast chúng tôi tạo dataframe mà bạn yêu cầu, các trang web nằm trong hàng (bên trái của công thức), các biến nằm trong cột (bên phải của công thức). Hàm tổng được sử dụng trên các biến mà nhiều ô được tạo ra.

Tất nhiên, mã có thể được mở rộng đến trường hợp chung hơn bằng vòng lặp hoặc * áp dụng các chức năng.

5

Thêm vào các tùy chọn có sẵn, dưới đây là hai tùy chọn khác với cơ sở R.

Đầu tiên lựa chọn: tập hợp rộng (loại)

temp <- cbind(df1, df2, df3) 
temp 
#  Sp1 Sp2 Sp3 Sp4 Sp1 Sp2 Sp4 Sp1 Sp2 Sp5 Sp6 
# site1 1 2 3 1 0 1 2 0 1 1 1 
# site2 0 2 0 1 1 2 0 1 1 1 5 
# site3 1 1 1 1 1 1 1 2 0 0 0 
sapply(unique(colnames(temp)), 
     function(x) rowSums(temp[, colnames(temp) == x, drop = FALSE])) 
#  Sp1 Sp2 Sp3 Sp4 Sp5 Sp6 
# site1 1 4 3 3 1 1 
# site2 2 5 0 1 1 5 
# site3 4 2 1 2 0 0 

tùy chọn thứ hai: bán rộng để dài để rộng

Về mặt lý thuyết, điều này cũng tương tự như Maxim. Câu trả lời của K: Lấy dữ liệu ở dạng dài và giúp việc thao tác mọi thứ trở nên dễ dàng hơn nhiều:

> temp1 <- t(cbind(df1, df2, df3)) 
> # You'll get a warning in the next step 
> # Safe to ignore though... 
> temp2 <- data.frame(var = rownames(temp), stack(data.frame(temp))) 
Warning message: 
In data.row.names(row.names, rowsi, i) : 
    some row.names duplicated: 5,6,7,8,9 --> row.names NOT used 
> xtabs(values ~ ind + var, temp2) 
     var 
ind  Sp1 Sp2 Sp3 Sp4 Sp5 Sp6 
    site1 1 4 3 3 1 1 
    site2 2 5 0 1 1 5 
    site3 4 2 1 2 0 0