Można użyć dplyr
to zrobić. Ustawię stringsAsFactors = FALSE
, aby pozbyć się ostrzeżeń o niedopasowaniu czynników.
library(dplyr)
a1 <- data.frame(A = c(1:5, 2, 4, 2), B = letters[c(1:5, 2, 4, 2)], stringsAsFactors = FALSE)
a2 <- data.frame(A = c(1:3,2), B = letters[c(1:3,2)], stringsAsFactors = FALSE)
## Make temp variables to join on then delete later.
# Create a row number
a1_tmp <-
a1 %>%
group_by(A, B) %>%
mutate(tmp_id = row_number()) %>%
ungroup()
# Create a count
a2_tmp <-
a2 %>%
group_by(A, B) %>%
summarise(count = n()) %>%
ungroup()
## Keep all that have no entry int a2 or the id > the count (i.e. used up a2 entries).
left_join(a1_tmp, a2_tmp, by = c('A', 'B')) %>%
ungroup() %>% filter(is.na(count) | tmp_id > count) %>%
select(-tmp_id, -count)
## # A tibble: 4 x 2
## A B
## <dbl> <chr>
## 1 4 d
## 2 5 e
## 3 4 d
## 4 2 b
EDIT
Oto podobne rozwiązanie, które jest trochę krótszy. Wykonuje następujące czynności: (1) dodaj kolumnę dla numeru wiersza, aby połączyć oba elementy data.frame
(2) tymczasową kolumnę w a2
(2. data.frame
), która będzie wyświetlana jako null w połączeniu z a1
(tj. Wskazuje, że jest unikalna dla a1
) .
library(dplyr)
left_join(a1 %>% group_by(A,B) %>% mutate(rn = row_number()) %>% ungroup(),
a2 %>% group_by(A,B) %>% mutate(rn = row_number(), tmpcol = 0) %>% ungroup(),
by = c('A', 'B', 'rn')) %>%
filter(is.na(tmpcol)) %>%
select(-tmpcol, -rn)
## # A tibble: 4 x 2
## A B
## <dbl> <chr>
## 1 4 d
## 2 5 e
## 3 4 d
## 4 2 b
Myślę, że to rozwiązanie jest trochę prostsze (może bardzo mało) niż pierwsze.
Nie jest jasne, czy twoje dane wyjściowe są poprawne, "2b" jest na początku, czy coś mi brakuje? – steveb
@steveb '2b' jest dwa razy w' a1', więc tylko jeden zostaje anulowany, a jeden pozostaje na wyjściu. –
Ahh, to jest to, co dostaję za czytanie zbyt szybko. – steveb