2014-12-11 12 views
7

Tôi muốn so sánh hai tập dữ liệu và xác định các trường hợp cụ thể về sự khác biệt giữa chúng (tức là các biến khác nhau).Xác định sự khác biệt cụ thể giữa hai tập dữ liệu trong R

Trong khi tôi đã tìm ra cách để xác định hồ sơ không phải là giống hệt nhau giữa hai bộ dữ liệu (sử dụng chức năng trình bày chi tiết ở đây: http://www.cookbook-r.com/Manipulating_data/Comparing_data_frames/), tôi không chắc chắn làm thế nào để cờ mà biến là khác nhau.

Ví dụ:

dữ liệu thiết lập A:

id  name  dob  vaccinedate vaccinename dose 
100000 John Doe 1/1/2000 5/20/2012 MMR   4 
100001 Jane Doe 7/3/2011 3/14/2013 VARICELLA 1 

dữ liệu bộ B:

id  name  dob  vaccinedate vaccinename dose 
100000 John Doe 1/1/2000 5/20/2012 MMR   3 
100001 Jane Doee 7/3/2011 3/24/2013 VARICELLA 1 
100002 John Smith 2/5/2010 7/13/2013 HEPB   3 

Tôi muốn xác định các hồ sơ khác nhau, và đó biến cụ thể (s) có sự khác biệt. Ví dụ: bản ghi John Doe có 1 sự khác biệt trong dose và bản ghi Jane Doe có 2 sự khác biệt: trong namevaccinedate. Ngoài ra, tập dữ liệu B có một bản ghi bổ sung không có trong tập dữ liệu A và tôi cũng muốn xác định các trường hợp này.

Cuối cùng, mục tiêu là tìm tần suất của "loại" lỗi, ví dụ: bao nhiêu hồ sơ có sự khác biệt trong vaccinedate, vaccinename, dose, v.v.

Cảm ơn!

+0

Hãy thử [Khoảng cách Hamming] (https://en.wikipedia.org/wiki/Hamming_distance) – Gathide

Trả lời

1

Một khả năng. Đầu tiên, tìm ra id nào cả hai bộ dữ liệu có điểm chung. Cách đơn giản nhất để làm điều này là:

commonID<-intersect(A$id,B$id) 

Sau đó, bạn có thể xác định hàng đang thiếu từ A theo:

> B[!B$id %in% commonID,] 
#  id  name  dob vaccinedate vaccinename dose 
# 3 100002 John Smith 2/5/2010 7/13/2013  HEPB 3 

Tiếp theo, bạn có thể hạn chế cả hai tập hợp dữ liệu để id họ có điểm chung.

Acommon<-A[A$id %in% commonID,] 
Bcommon<-B[B$id %in% commonID,] 

Nếu bạn không thể giả định rằng id là theo thứ tự đúng, sau đó sắp xếp chúng cả:

Acommon<-Acommon[order(Acommon$id),] 
Bcommon<-Bcommon[order(Bcommon$id),] 

Bây giờ bạn có thể xem những gì các lĩnh vực khác nhau như thế này.

diffs<-Acommon != Bcommon 
diffs 
#  id name dob vaccinedate vaccinename dose 
# 1 FALSE FALSE FALSE  FALSE  FALSE TRUE 
# 2 FALSE TRUE FALSE  TRUE  FALSE FALSE 

Đây là ma trận hợp lý và bạn có thể làm bất cứ điều gì bạn muốn với nó. Ví dụ, để tìm ra tổng số sai sót trong mỗi cột:

colSums(diffs) 
#   id  name   dob vaccinedate vaccinename  dose 
#   0   1   0   1   0   1 

Để tìm tất cả id nơi tên là khác nhau:

Acommon$id[diffs[,"name"]] 
# [1] 100001 

Và vân vân.

+0

Cảm ơn! Tôi đã không chỉ định trong các ví dụ dataframes của tôi ở trên, nhưng dữ liệu thực tế của tôi có nhiều bản ghi cho mỗi id. Ví dụ: John Doe có thể có 5 loại vắc-xin và mỗi loại vắc-xin có thể có nhiều liều. Trong dòng mã đầu tiên của bạn, làm thế nào tôi có thể xác định những hàng nào cả hai bộ dữ liệu có điểm chung, không chỉ dựa trên nó trên id? Hy vọng điều này có ý nghĩa. – Lydia

+0

Không có câu trả lời cụ thể cho câu hỏi đó. Vấn đề là, nếu hai hàng không giống nhau, thì làm thế nào để bạn quyết định xem chúng có được "giả định" giống nhau hay không nhưng có sự khác biệt, hoặc liệu chúng có thực sự là các mục khác nhau hoàn toàn hay không. Bạn phải đưa ra một số tiêu chí để đưa ra quyết định đó. – mrip

+0

Đúng vậy. Một trong các bộ dữ liệu là 'tiêu chuẩn vàng' (từ hồ sơ tiêm chủng giấy) trong khi bộ dữ liệu khác được nhập riêng rẽ, vì vậy tập dữ liệu đầu tiên được cho là số 'chính xác'. Điều đó có giúp làm rõ mọi thứ không? Người trước đây đã thực hiện kiểm toán này đã xem xét sự khác biệt theo cách thủ công trong Excel, tìm kiếm> 1000 lỗi. Lý tưởng nhất là tôi muốn tránh công việc thủ công này! :) – Lydia

4

Điều này sẽ giúp bạn bắt đầu, nhưng có thể có nhiều giải pháp thanh lịch hơn.

Thứ nhất, thiết lập df1df2 để những người khác có thể tái tạo một cách nhanh chóng:

df1 <- structure(list(id = 100000:100001, name = structure(c(2L, 1L), .Label = c("Jane Doe","John Doe"), class = "factor"), dob = structure(1:2, .Label = c("1/1/2000", "7/3/2011"), class = "factor"), vaccinedate = structure(c(2L, 1L), .Label = c("3/14/2013", "5/20/2012"), class = "factor"), vaccinename = structure(1:2, .Label = c("MMR", "VARICELLA"), class = "factor"), dose = c(4L, 1L)), .Names = c("id", "name", "dob", "vaccinedate", "vaccinename", "dose"), class = "data.frame", row.names = c(NA, -2L)) 

df2 <- structure(list(id = 100000:100002, name = structure(c(2L, 1L, 3L), .Label = c("Jane Doee", "John Doe", "John Smith"), class = "factor"), dob = structure(c(1L, 3L, 2L), .Label = c("1/1/2000", "2/5/2010", "7/3/2011"), class = "factor"), vaccinedate = structure(c(2L, 1L, 3L), .Label = c("3/24/2013", "5/20/2012", "7/13/2013"), class = "factor"), vaccinename = structure(c(2L, 3L, 1L), .Label = c("HEPB", "MMR", "VARICELLA"), class = "factor"), dose = c(3L, 1L, 3L)), .Names = c("id", "name", "dob", "vaccinedate", "vaccinename", "dose"), class = "data.frame", row.names = c(NA, -3L)) 

Tiếp theo, có được sự khác biệt df1-df2 qua mapplysetdiff. Đó là, những gì trong một bộ mà không có trong bộ hai:

discrep <- mapply(setdiff, df1, df2) 
discrep 
# $id 
# integer(0) 
# 
# $name 
# [1] "Jane Doe" 
# 
# $dob 
# character(0) 
# 
# $vaccinedate 
# [1] "3/14/2013" 
# 
# $vaccinename 
# character(0) 
# 
# $dose 
# [1] 4 

Để đếm họ lên chúng ta có thể sử dụng sapply:

num.discrep <- sapply(discrep, length) 
num.discrep 
# id  name   dob vaccinedate vaccinename  dose 
# 0   1   0   1   0   1 

mỗi câu hỏi của bạn về việc thu thập của id trong đặt hai mà không phải là trong bộ một, bạn có thể đảo ngược quá trình với mapply(setdiff, df2, df1) hoặc nếu nó chỉ đơn giản là một bài tập của ids chỉ bạn có thể làm setdiff(df2$id, df1$id).

Để biết thêm về các chức năng chức năng của R (ví dụ: mapply, sapply, lapply, v.v.), hãy xem this post.

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