Mam następujące 2 data.frames:
a1 <- data.frame(a = 1:5, b=letters[1:5])
a2 <- data.frame(a = 1:3, b=letters[1:3])
Chcę znaleźć wiersz a1, w którym a2 nie.
Czy istnieje wbudowana funkcja dla tego typu operacji?
(ps: napisałem rozwiązanie na to, jestem po prostu ciekawy, czy ktoś już zrobił bardziej spreparowany kod)
Oto moje rozwiązanie:
a1 <- data.frame(a = 1:5, b=letters[1:5])
a2 <- data.frame(a = 1:3, b=letters[1:3])
rows.in.a1.that.are.not.in.a2 <- function(a1,a2)
{
a1.vec <- apply(a1, 1, paste, collapse = "")
a2.vec <- apply(a2, 1, paste, collapse = "")
a1.without.a2.rows <- a1[!a1.vec %in% a2.vec,]
return(a1.without.a2.rows)
}
rows.in.a1.that.are.not.in.a2(a1,a2)
a2 <- data.frame(a = c(1:3, 1), b = c(letters[1:3], "c"))
. Zostawa1
to samo. Teraz spróbuj porównania. Nawet po przeczytaniu opcji nie jest dla mnie jasne, jak należy podać tylko wspólne elementy.SQLDF
zapewnia ładne rozwiązanieOraz wiersze, które znajdują się w obu ramkach danych:
Nowa wersja
dplyr
ma funkcjęanti_join
, dla dokładnie tego rodzaju porównańI
semi_join
filtrować wierszea1
, które również znajdują się wa2
źródło
anti_join
isemi_join
!W dplyr :
Zasadniczo
setdiff(bigFrame, smallFrame)
dostajesz dodatkowe rekordy w pierwszej tabeli.W SQLverse nazywa się to
Aby uzyskać dobry opis wszystkich opcji dołączania i ustalonych tematów, jest to jedno z najlepszych podsumowań, jakie do tej pory widziałem: http://www.vertabelo.com/blog/technical-articles/sql-joins
Ale wracając do tego pytania - oto wyniki dla
setdiff()
kodu podczas korzystania z danych PO:Albo nawet
anti_join(a1,a2)
przyniesie Ci takie same wyniki.Więcej informacji: https://www.rstudio.com/wp-content/uploads/2015/02/data-wrangling-cheatsheet.pdf
źródło
a1
, których nie ma wa2
środku, nie chcesz użyć czegoś takiego jaksemi_join(a1, a2, by = c('a','b'))
? W odpowiedzi „Rickarda” widzę, żesemi_join
zostało to zasugerowane.setdiff()
funkcji bazowej, która działa na dwóch wektorach: stat.ethz.ch/R-manual/R-devel/library/base/html/sets.html . Może załadowałeś bibliotekę lubridate po dplyr i sugeruje to jako źródło w liście tabcomplete?Z pewnością nie jest to skuteczne w tym konkretnym celu, ale często w takich sytuacjach wstawiam zmienne wskaźnikowe do każdej ramki data.frame, a następnie łączę:
brakujące wartości w include_a1 będą wskazywać, których wierszy brakuje w a1. podobnie dla a2.
Jednym z problemów z rozwiązaniem jest to, że kolejność kolumn musi być zgodna. Innym problemem jest to, że łatwo wyobrazić sobie sytuacje, w których wiersze są kodowane tak samo, podczas gdy w rzeczywistości są różne. Zaletą korzystania z funkcji scalania jest to, że otrzymujesz bezpłatnie wszystkie funkcje sprawdzania błędów, które są niezbędne do dobrego rozwiązania.
źródło
included_a1
? : - /Napisałem pakiet ( https://github.com/alexsanjoseph/compareDF ), ponieważ miałem ten sam problem.
Bardziej skomplikowany przykład:
Pakiet zawiera również polecenie html_output do szybkiego sprawdzenia
źródło
The two data frames have different columns!
Możesz użyć
daff
pakietu (który otaczadaff.js
bibliotekę za pomocąV8
pakietu ):generuje następujący obiekt różnicy:
Format diff jest opisany w formacie różnic wyróżniających Coopy'ego dla tabel i powinien być dość oczywisty. Wiersze z
+++
w pierwszej kolumnie@@
to te, które są nowea1
i nieobecne wa2
.Obiekt różnicy może służyć do
patch_data()
przechowywania różnic w celach dokumentacyjnych przy użyciuwrite_diff()
lub do wizualizacji różnicy za pomocąrender_diff()
:generuje schludny wynik HTML:
źródło
Korzystanie z
diffobj
pakietu:źródło
Dostosowałem
merge
funkcję, aby uzyskać tę funkcjonalność. W przypadku większych ramek danych zużywa mniej pamięci niż rozwiązanie pełnego scalania. Mogę bawić się nazwami kluczowych kolumn.Innym rozwiązaniem jest skorzystanie z biblioteki
prob
.źródło
Twoje przykładowe dane nie mają żadnych duplikatów, ale Twoje rozwiązanie obsługuje je automatycznie. Oznacza to, że potencjalnie niektóre odpowiedzi nie będą pasować do wyników Twojej funkcji w przypadku duplikatów.
Oto moje rozwiązanie, w którym adres jest taki sam jak twój. Świetnie się skaluje!
Potrzebuje data.table 1.9.8+
źródło
Może jest to zbyt uproszczone, ale zastosowałem to rozwiązanie i uważam je za bardzo przydatne, gdy mam klucz podstawowy, którego mogę użyć do porównania zestawów danych. Mam nadzieję, że to pomoże.
źródło
Kolejne rozwiązanie oparte na match_df w plyr. Oto plik Plyr's match_df:
Możemy go zmodyfikować, aby zanegować:
Następnie:
źródło
Używając
subset
:źródło
Poniższy kod używa obu
data.table
ifastmatch
dla zwiększenia szybkości.źródło