2013-03-24 25 views
5

Tôi đang cố gắng điền một vector nhị phân dựa trên giao điểm của hai dữ liệu.frames trên nhiều tiêu chí.R cắt giao dữ liệu.trên nhiều tiêu chí

Tôi có mã làm việc nhưng tôi cảm thấy rằng nó là bộ nhớ quá mức chỉ để có được vector nhị phân.

Khi tôi áp dụng mã của mình cho toàn bộ dữ liệu của tôi (40mm + hàng). Tôi bắt đầu có vấn đề về trí nhớ.

Có cách nào đơn giản hơn để tạo vectơ không?

Dưới đây là một số dữ liệu mẫu (ví dụ, mẫu phụ sẽ chỉ bao gồm obs trong mẫu đầy đủ.):

ob1_1 <- as.data.frame(cbind(c(1999),c("111","222","666","777")),stringsAsFactors=FALSE) 
ob2_1 <- as.data.frame(cbind(c(2000),c("111","333","555","777")),stringsAsFactors=FALSE) 
ob3_1 <- as.data.frame(cbind(c(2001),c("111","222","333","777")),stringsAsFactors=FALSE) 
ob4_1 <- as.data.frame(cbind(c(2002),c("111","444","555","777")),stringsAsFactors=FALSE) 

full_sample <- rbind(ob1_1,ob2_1,ob3_1,ob4_1) 
colnames(full_sample) <- c("yr","ID") 

ob1_2 <- as.data.frame(cbind(c(1999),c("111","222","777")),stringsAsFactors=FALSE) 
ob2_2 <- as.data.frame(cbind(c(2000),c("333")),stringsAsFactors=FALSE) 
ob3_2 <- as.data.frame(cbind(c(2001),c("888")),stringsAsFactors=FALSE) 
ob4_2 <- as.data.frame(cbind(c(2002),c("111","444","555","777")),stringsAsFactors=FALSE) 

sub_sample <- rbind(ob1_2,ob2_2,ob3_2,ob4_2) 
colnames(sub_sample) <- c("yr","ID") 

Đây là mã làm việc của tôi:

q_intersect <- "" 
q_intersect <- paste(q_intersect , "select  a.yr, a.ID  ", sep=" ") 
q_intersect <- paste(q_intersect , "from   full_sample a ", sep=" ") 
q_intersect <- paste(q_intersect , "intersect      ", sep=" ") 
q_intersect <- paste(q_intersect , "select  b.yr, b.ID  ", sep=" ") 
q_intersect <- paste(q_intersect , "from   sub_sample b ", sep=" ") 
q_intersect <- trim(gsub(" {2,}", " ", q_intersect)) 

intersect_temp <- cbind(sqldf(q_intersect),1) 
colnames(intersect_temp) <- c("yr","ID","in_both") 

q_expand <- "" 
q_expand <- paste(q_expand , "select  in_both   ", sep=" ") 
q_expand <- paste(q_expand , "from   full_sample a  ", sep=" ") 
q_expand <- paste(q_expand , "left join intersect_temp b ", sep=" ") 
q_expand <- paste(q_expand , "on   a.yr=b.yr   ", sep=" ") 
q_expand <- paste(q_expand , "and   a.ID=b.ID   ", sep=" ") 
q_expand <- trim(gsub(" {2,}", " ", q_expand)) 

solution <- as.integer(sqldf(q_expand)[,1]) 
solution [is.na(solution)] <- 0 

Cảm ơn trước thời hạn đối với bất kỳ Cứu giúp!

+1

Bạn nên giải thích những gì bạn muốn trong ngôn ngữ tự nhiên. (Mã bạn nói là làm việc chỉ bị khóa phiên R của tôi, có thể vì không có chức năng 'trim'?) Không, lệnh gọi' sqldf' đầu tiên sẽ khóa nó. –

+0

@Dwin, tôi vừa gặp vấn đề về khóa. Nhưng chỉ trong 4 dòng đầu tiên của phần 'q_intersect'. Ngẫu nhiên, Brad, trong câu hỏi trước của bạn, bạn đang sử dụng 'data.table' và ở đây bạn đang sử dụng' data.frame'. Đây có phải là cố ý không? –

+0

@RicardoSaporta Xin chào. Có dữ liệu không được gắn thẻ. Xem cuộc thảo luận trong phòng chat ngày hôm qua đã sửa chữa tôi. Có thể thực hiện một quá trình quét không được vá lớn hơn. Khung nhìn SO là các thẻ dành cho các câu hỏi không phải là câu trả lời. Với đôi mắt mới, bây giờ tôi thấy và đồng ý rằng tìm kiếm "data.table data.table là: câu hỏi" là những gì "[data.table]" một mình nên như thế nào. Tuy nhiên, có vẻ như ok (xem trò chuyện) để gắn thẻ các câu trả lời được chấp nhận bằng cách sử dụng 'data.table' trong đó số phiếu> 10 là tốt. Để tìm kiếm câu trả lời bằng cách sử dụng data.table, chúng ta có thể sử dụng "[r] - [data.table] data.table là: answer". –

Trả lời

4

Nó không hoàn toàn rõ ràng những gì bạn đang cố gắng để thực hiện, nhưng tôi tin rằng một cái gì đó như thế này sẽ đơn giản hơn rất nhiều.

library(data.table) 
fullDT <- data.table(full_sample, key=c("yr", "ID")) 
subDT <- data.table(sub_sample, key=c("yr", "ID")) 

fullDT[ , intersect := 0L] 
fullDT[subDT, intersect := 1, nomatch=0] 

Ý tưởng là bạn thiết lập key của mỗi data.table là cột mà bạn muốn cắt. Khi bạn gọi full[sub], nomatch=0], bạn sẽ tham gia vào bên trong của mình và chúng tôi chỉ đặt các giá trị đó thành 1; các giá trị không được xác định trong phần nối bên trong được để lại dưới dạng 0, như được đặt trong dòng trước đó.

fullDT 
#  yr ID intersect 
# 1: 1999 111   1 
# 2: 1999 222   1 
# 3: 1999 666   0 
# 4: 1999 777   1 
# 5: 2000 111   0 
# 6: 2000 333   1 
# 7: 2000 555   0 
# 8: 2000 777   0 
# 9: 2001 111   0 
# 10: 2001 222   0 
# 11: 2001 333   0 
# 12: 2001 777   0 
# 13: 2002 111   1 
# 14: 2002 444   1 
# 15: 2002 555   1 
# 16: 2002 777   1 
+0

Ricardo, điều này có vẻ tốt. Tôi đã sử dụng data.frames để tạo dữ liệu mẫu, nhưng tôi thích data.tables hơn khi có thể. – Brad

+2

Điều này chắc chắn đơn giản hơn nhiều so với cách tiếp cận của tôi. Cảm ơn bạn một lần nữa! – Brad

+0

@Brad, không có gì cả. Tôi đã hỏi ý kiến ​​của tôi ở trên, đơn giản bởi vì nó làm cho vấn đề dễ dàng hơn rất nhiều. –

2

SQL đơn giản Tôi tập hợp mà bạn muốn tạo một khung dữ liệu một cột với cùng số hàng như full_sample như vậy mà một hàng được đưa ra trong đầu ra chứa 1 nếu hàng tương ứng trong full_sample có khớp sub_sample hàng và 0 cách khác.

Trong trường hợp đó, nhiều câu lệnh SQL có thể được cô đặc thành một câu lệnh SQL đơn giản hơn như hình dưới đây. Việc kết nối bên trái đảm bảo rằng tất cả các hàng của full_sample được bao gồm và tham gia tự nhiên làm cho sự tham gia xảy ra trên tất cả các tên cột phổ biến giữa hai khung dữ liệu đầu vào.

sqldf("select s.yr is not null as solution 
     from full_sample f natural left join sub_sample s") 

(Bằng cách này, lưu ý rằng xâu có thể chảy qua nhiều dòng như thế này cho thấy nên nó không cần thiết phải dán nhiều dòng với nhau.)

Out of Database Memory sqldf theo mặc định sử dụng một trong cơ sở dữ liệu bộ nhớ nhưng bạn có thể chỉ định tên tệp (không cần tồn tại trước thời hạn) qua đối số dbname= để sử dụng như trong cơ sở dữ liệu bộ nhớ. Trong trường hợp đó, bạn sẽ không bị giới hạn bởi bộ nhớ.

sqldf("select s.yr is not null as solution 
     from full_sample f natural left join sub_sample s", dbname = "mydb") 

(Bạn cũng có thể cải thiện hiệu suất trong một số trường hợp bằng cách sử dụng chỉ số Xem sqldf home page cho ví dụ..)

UPDATE: thêm đơn giản hơn giải pháp sql

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