2013-03-24 9 views
5

Próbuję wypełnić wektor binarny na podstawie przecięcia dwóch data.frames na wielu kryteriach.R przecinają dane.frame na wielu kryteriach

Mam kod działa, ale czuję, że jest to nadmierna pamięć tylko po to, aby uzyskać wektor binarny.

Po zastosowaniu kodu do pełnych danych (40 mm + wiersze). Zaczynam mieć problemy z pamięcią.

Czy istnieje prostszy sposób na uzyskanie wektora?

Oto kilka przykładowych danych (np sub próbka będzie zawierać tylko OB w pełnej próbie.):

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") 

Oto mój kod roboczych:

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 

Dzięki wyprzedzeniem dla każdego Wsparcie!

+1

Należy wyjaśnić, co chcesz w języku naturalnym. (Kod, o którym mówisz, działa właśnie zablokował moją sesję R, prawdopodobnie dlatego, że nie ma funkcji "trim"?) Nie, pierwsze wywołanie 'sqldf' blokuje ją. –

+0

@Dwin, właśnie miałem ten sam problem z blokowaniem. Ale tylko w pierwszych 4 liniach fragmentu 'q_intersect'. Nawiasem mówiąc, Brad, w poprzednim pytaniu używasz 'data.table' i tutaj używasz' data.frame'. Czy to jest celowe? –

+0

@RicardoSaporta Cześć. Właśnie odznaczone data.table. Zobacz wczoraj dyskusję na czacie, która mnie poprawiła. Może zrobić większy untagging sweep. Widok SO jest taki, że tagi są dla pytań, a nie odpowiedzi. Ze świeżymi oczami widzę i zgadzam się, że wyszukiwanie "[data.table] data.table to: pytanie" jest tym, co powinno wyglądać samo "[data.table]". Jednak wydaje się być ok (patrz czat), aby oznaczyć zaakceptowane odpowiedzi za pomocą 'data.table' gdzie również> 10 głosów. Aby wyszukać odpowiedzi za pomocą data.table, możemy użyć "[r] - [data.table] data.table is: answer". –

Odpowiedz

4

Nie jest całkiem jasne, co próbujesz osiągnąć, ale wierzę, że coś takiego byłoby znacznie prostsze.

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] 

Chodzi o to, że ustawisz key każdego data.table się kolumny, które chcesz przecinają. Gdy zadzwonisz pod numer full[sub], nomatch=0], otrzymasz połączenie wewnętrzne, a my ustawimy tylko te wartości na 1; wartości niezidentyfikowane w łączeniu wewnętrznym pozostawia się jako 0, jak ustawiono w poprzedniej linii.

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, to wygląda dobrze. Używałem data.frames do tworzenia przykładowych danych, ale wolę dane, jeśli to możliwe. – Brad

+2

Jest to zdecydowanie prostsze niż moje podejście. Jeszcze raz dziękuję! – Brad

+0

@Brad, żaden problem. Pytałem w moich komentarzach powyżej, po prostu dlatego, że sprawia, że ​​problem jest o wiele łatwiejsze. –

2

Prostsze SQL I gromadzić który chce utworzyć ramki danych jedna kolumna z taką samą liczbę wierszy w full_sample tak, że dany rząd na wyjściu zawiera 1 gdy odpowiadająca wiersz full_sample posiada pasujący sub_sample wiersz i 0 w przeciwnym razie.

W takim przypadku, wielokrotne instrukcje SQL można skondensować w jedną prostszą instrukcję SQL, jak pokazano poniżej. Lewe połączenie zapewnia uwzględnienie wszystkich wierszy full_sample, a naturalne łączenie powoduje, że łączenie występuje we wszystkich nazwach kolumn, które są wspólne dla dwóch wejściowych ramek danych.

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

(Przy okazji należy zauważyć, że literały ciągów znaków może płynąć na wielu liniach, jak to pokazuje więc jej nie jest konieczne, aby wkleić wiele wierszy razem).

Out of Memory Database sqldf domyślnie używa w bazie danych pamięci, ale możesz podać nazwę pliku (która nie musi być wcześniejsza) za pomocą argumentu dbname=, który ma być używany jako baza danych z pamięci. W takim przypadku nie będziesz ograniczany przez pamięć.

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

(również można poprawić wydajność w niektórych przypadkach przy użyciu indeksów Zobacz sqldf home page przykłady.).

UPDATE: Dodano prostsze rozwiązanie sql

Powiązane problemy