2013-03-29 17 views
15

Có cách nào tốt hơn để nối các bảng dữ liệu trong R trong đó các giá trị thời gian chính gần không, nhưng không chính xác giống nhau không? Ví dụ, giả sử tôi có một bảng dữ liệu kết quả được đưa ra cho khoảng thời gian khác nhau:Tham gia dữ liệu R.trong đó các giá trị khóa không chính xác bằng nhau - kết hợp các hàng với thời gian gần nhất

DT1 = data.table(x=rep(c("a","b","c"),each=3), time=c(10,30,60), v=1:9) 

Ở đây, chúng tôi có một số giá trị (v) đối với các loại khác nhau (x) thực hiện tại thời điểm khác nhau (thời gian). Bây giờ giả sử rằng tôi có dữ liệu từ một nguồn cung cấp một số giá trị thời gian cho các hạng mục khác nhau:

DT2=data.table(x=rep(c("a","b","c"),each=1),time=c(10,10,60)) 

tôi có thể quan tâm cố gắng để phù hợp với thời gian trong DT2 là chặt chẽ nhất có thể để dt1 để dự đoán một giá trị, v, cho các loại DT2 của tôi. Tôi muốn làm điều gì đó như

setkeyv(DT2,c("x","time")) 
merge(DT1,DT2,by=c("time","v") 

nào trả về:

time x v 
1: 10 a 1 
2: 10 b 4 
3: 60 c 9 

Nhưng nếu thời gian của tôi không có độ chính xác giống nhau không? Ví dụ:

DT2=data.table(x=rep(c("a","b","c"),each=1),time=c(17,54,3)) 

Có cách nào để thực hiện quá trình hợp nhất tương tự nhưng thời gian chọn của DT2 gần với DT1? Đó là 17 sẽ là gần 30, 54 gần 60, và 3 gần 10?

Nếu ví dụ đơn giản này không rõ ràng, tôi sẽ giải thích ngắn gọn vấn đề lớn hơn mà tôi đang gặp phải. Tôi có một bảng dữ liệu với các cột: thể loại, thời gian, output1, output2 ... Có hàng trăm loại với thời gian liên quan. Tôi có thể muốn rút đầu ra 1 cho tất cả các danh mục tại một thời điểm cụ thể. Kể từ khi thời gian được lấy mẫu không có logic rõ ràng, đôi khi thời gian được làm tròn đến giây gần nhất; trong các trường hợp khác, số lần được làm tròn đến phút gần nhất hoặc thậm chí 10 phút.

Tôi có thể viết một kịch bản để viết lại thời gian ở định dạng phổ biến hơn, nhưng tôi tò mò nếu có một giải pháp data.table slick mà tôi đã không nhìn thấy. Tôi đã khám phá sự hợp nhất lăn mà không thành công.

+0

Cố gắng hợp nhất (..., tất cả = TRUE) và tổng hợp các hàng như theo ý thích của bạn. – bfb

Trả lời

17

Tùy chọn khác có thể là roll='nearest' (mới trong v1.8.8 trên CRAN).

> setkey(DT1,x,time) 
> DT1 
    x time v 
1: a 10 1 
2: a 30 2 
3: a 60 3 
4: b 10 4 
5: b 30 5 
6: b 60 6 
7: c 10 7 
8: c 30 8 
9: c 60 9 
> DT2 
    x time 
1: a 17 
2: b 54 
3: c 3 
> DT1[DT2,roll="nearest"] 
    x time v 
1: a 17 1 
2: b 54 6 
3: c 3 7 

Lưu ý rằng 17 dường như gần hơn 10, do đó dẫn đến hàng đầu tiên.

Nếu bạn cần phải cuộn để quan sát tiếp theo (quan sát tiếp theo được thực ngược):

> DT1[DT2,roll=-Inf] 
    x time v 
1: a 17 2 
2: b 54 6 
3: c 3 7 
+1

thì cũng có thể thêm cột cho sự khác biệt về thời gian giữa dữ liệu. Ví dụ. 10-17 = -7 hoặc abs (10-17) = 7. Nếu một ví dụ muốn loại trừ các giá trị được kết hợp cách nhau hơn 5 bước hoặc muốn đánh giá hiệu quả của thời gian cách nhau. –

+0

@ EndreGrünerOfstad Giới hạn độ cứng được xây dựng trong 'roll': chuyển qua một số giới hạn độ cứng đến giá trị đó (do đó' Inf' không có giới hạn). Xem '? Data.table', bản trình bày và chương 10 của khóa Data.tamp data.table. Bạn cũng có thể sử dụng tiền tố 'x.' và' i.' để trích xuất sự khác biệt một cách rõ ràng trong j, ví dụ: 'x.time-i.time'. –

4

Bạn có thể sử dụng findInterval để thực hiện điều này:

setkey(DT2, time) 
DT1[, id := findInterval(DT1$time, DT2$time)] 
DT2[, id := 1:3] 

setkey(DT1, "x", "id") 
setkey(DT2, "x", "id") 
print(DT1[DT2][, id := NULL]) 
# x time v time.1 
# 1: a 30 2  17 
# 2: b 60 6  54 
# 3: c 10 7  3 

Ý tưởng: Đầu tiên sắp xếp các data.table theo thời gian bởi vì đối số thứ hai của findInterval đòi hỏi thứ tự tăng dần của các giá trị. Bây giờ, hãy sử dụng findInterval để tìm khoảng thời gian là 3, 17, 54 giá trị trong DT1$time rơi và lưu trữ trong id. Trong trường hợp cụ thể này, nó xảy ra trong khoảng từ 1 đến 3. Vì vậy, hãy đặt các giá trị này thành cột id cho DT2. Khi bạn tìm thấy các khoảng thời gian và nhận được id, thì điều đó đơn giản. Thay vì đặt xtime, hãy đặt xid làm khóa và thực hiện hợp nhất của bạn.

Lưu ý: Giả sử bạn DT1$time đã một giá trị từ 0, sau đó, khoảng thời gian cho điều đó có thể đã được 0. Vì vậy, bạn sẽ nhận được 4 giá trị duy nhất (0: 3). Trong trường hợp đó, có thể tốt hơn để có DT2 với giá trị time = 0. Tôi chỉ muốn lưu ý điểm này ở đây. Tôi sẽ để nó cho bạn.

+1

Câu trả lời hữu ích tuyệt vời. Cảm ơn bạn đã cung cấp giải pháp tuyệt vời cũng như giải thích hữu ích. – Docuemada

+1

+1! Phương pháp rực rỡ. Đề xuất nhỏ để cho phép khái quát hóa: có thể sử dụng 'DT2 [, id: = as.numeric (yếu tố (thời gian))]' thay vì id rõ ràng. hoặc 'DT2 [, id: = seq (nrow (DT2))]' nếu không cho phép giá trị thời gian trùng lặp –

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