2017-10-10 21 views
6

Hãy xem xét hai data.frames sau:Di hàng chính xác và tần số của hàng của một data.frame có trong data.frame khác trong r

a1 <- data.frame(A = c(1:5, 2, 4, 2), B = letters[c(1:5, 2, 4, 2)]) 
a2 <- data.frame(A = c(1:3,2), B = letters[c(1:3,2)]) 

Tôi muốn loại bỏ các hàng chính xác của a1 rằng là trong a2 để kết quả nên là:

A B 
4 d 
5 e 
4 d 
2 b 

Lưu ý rằng một hàng với 2 b trong a1 được giữ lại trong kết quả cuối cùng. Hiện tại, tôi sử dụng câu lệnh lặp, điều này trở nên cực kỳ chậm vì tôi có nhiều biến và hàng nghìn hàng trong data.frames của tôi. Có chức năng tích hợp nào để nhận kết quả này không?

+0

Nó không rõ ràng đầu ra của bạn là chính xác, '2b' là cả hai để bắt đầu, tôi thiếu cái gì? – steveb

+0

@steveb '2b' là hai lần trong 'a1', vì vậy chỉ có một bị hủy và một vẫn ở đầu ra. –

+0

Ahh, đó là những gì tôi nhận được để đọc quá nhanh. – steveb

Trả lời

1

Tôi đoán đây là tương tự như DWal's solution nhưng trong cơ sở R

a1_temp = Reduce(paste, a1) 
a1_temp = paste(a1_temp, ave(seq_along(a1_temp), a1_temp, FUN = seq_along)) 

a2_temp = Reduce(paste, a2) 
a2_temp = paste(a2_temp, ave(seq_along(a2_temp), a2_temp, FUN = seq_along)) 

a1[!a1_temp %in% a2_temp,] 
# A B 
#4 4 d 
#5 5 e 
#7 4 d 
#8 2 b 
2

Bạn có thể sử dụng dplyr để làm điều này. Tôi đặt stringsAsFactors = FALSE để loại bỏ cảnh báo về các yếu tố không khớp.

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

Đây là một giải pháp tương tự đó là ngắn hơn một chút. Điều này thực hiện như sau: (1) thêm cột cho số hàng để tham gia cả hai data.frame mục (2) cột tạm thời trong a2 (2nd data.frame) sẽ hiển thị dưới dạng null trong tham gia a1 (nghĩa là chỉ có duy nhất 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 

Tôi nghĩ giải pháp này đơn giản hơn một chút (có lẽ rất ít) so với phiên bản đầu tiên.

+0

Vâng, có, Steveb; cảm kích điều đó. – RBL

+0

Tuyệt vời! Rất nhỏ gọn! Cảm kích điều đó! – RBL

2

Ý tưởng là thêm một bộ đếm cho các bản sao cho mỗi tệp để bạn có thể nhận được kết quả trùng khớp duy nhất cho mỗi lần xuất hiện của một hàng. Bảng dữ liệu là tốt đẹp bởi vì nó rất dễ dàng để đếm các bản sao (với .N), và nó cũng cung cấp cho các chức năng cần thiết (fsetdiff) cho các hoạt động thiết lập.

library(data.table) 

a1 <- data.table(A = c(1:5, 2, 4, 2), B = letters[c(1:5, 2, 4, 2)]) 
a2 <- data.table(A = c(1:3,2), B = letters[c(1:3,2)]) 

# add counter for duplicates 
a1[, i := 1:.N, .(A,B)] 
a2[, i := 1:.N, .(A,B)] 

# setdiff gets the exception 
# "all = T" allows duplicate rows to be returned 
fsetdiff(a1, a2, all = T) 

# A B i 
# 1: 4 d 1 
# 2: 5 e 1 
# 3: 4 d 2 
# 4: 2 b 3 
+0

Điều này cũng hoạt động tốt! Cảm kích điều đó. – RBL

1

Đây là một giải pháp với dplyr:

library(dplyr) 
a1 %>% 
    arrange(A) %>% 
    group_by(A) %>% 
    filter(!(paste0(1:n(), A, B) %in% with(arrange(a2, A), paste0(1:n(), A, B)))) 

Kết quả:

# A tibble: 4 x 2 
# Groups: A [3] 
     A  B 
    <dbl> <fctr> 
1  2  b 
2  4  d 
3  4  d 
4  5  e 

Bằng cách này lọc tránh tạo ra các cột không cần thiết bổ sung mà bạn có để sau đó loại bỏ trong đầu ra cuối cùng . Phương pháp này cũng sắp xếp đầu ra. Không chắc chắn nếu đó là những gì bạn muốn.

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