2014-12-11 2 views
7

Я хотел бы сравнить два набора данных и определить конкретные случаи несоответствий между ними (то есть, какие переменные были разными).Идентификация конкретных различий между двумя наборами данных в R

В то время как я выяснил, как определить, какие записи не тождественны между двумя наборами данных (с помощью функции подробно описана здесь: http://www.cookbook-r.com/Manipulating_data/Comparing_data_frames/), я не знаю, как флаг, который переменных различны.

E.g.

Набор данных 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 

данных 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 

Я хочу, чтобы определить, какие записи различны, и какие конкретные переменной (ы) имеют расхождения. Например, запись John Doe имеет 1 несоответствие в dose, а запись Jane Doe имеет 2 несоответствия: в name и vaccinedate. Кроме того, набор данных B имеет одну дополнительную запись, которая не была в наборе данных A, и я хотел бы также идентифицировать эти экземпляры.

В конце концов, цель состоит в том, чтобы найти частоту «типов» ошибок, например. сколько записей имеет несоответствие в вакцинации, вакцинальном имени, дозе и т. д.

Спасибо!

+0

Попробуйте [расстояние Хэмминга] (https://en.wikipedia.org/wiki/Hamming_distance) – Gathide

ответ

1

One возможность. Сначала выясните, какие идентификаторы имеют оба набора данных. Самый простой способ сделать это:

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

Затем вы можете определить, какие строки отсутствуют из А:

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

Далее, вы можете ограничить как наборы данных с идентификаторами, они имеют в общем.

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

Если вы не можете предположить, что идентификаторы находятся в правильном порядке, а затем отсортировать их обоих:

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

Теперь вы можете увидеть, что поля различны, как это.

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

Это логическая матрица, и вы можете делать с ней все, что хотите. Например, чтобы найти общее количество ошибок в каждом столбце:

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

Чтобы найти все идентификаторы, где имя отличается:

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

И так далее.

+0

Спасибо! Я не указал в моем примере dataframes выше, но мои фактические данные имеют несколько записей для каждого идентификатора. Например, Джон Доу мог иметь 5 типов вакцин, и каждая вакцина могла иметь несколько доз. В вашей первой строке кода, как я могу определить, какие строки имеют оба набора данных, а не только на основе идентификатора? Надеюсь, это имеет смысл. – Lydia

+0

Нет конкретного ответа на этот вопрос. Проблема в том, что если две строки не идентичны, то как вы определяете, являются ли они «предполагаемыми» одинаковыми, но есть расхождение или все они действительно разные. Вы должны придумать некоторые критерии, чтобы принять это решение. – mrip

+0

Это правда. Один из наборов данных - это «золотой стандарт» (из записей бумажной вакцинации), в то время как другой был введен электронным способом отдельно, поэтому первый набор данных должен быть «правильным». Это помогает прояснить ситуацию? Предыдущее лицо, которое провело этот аудит, просмотрело расхождения вручную в Excel, обнаружив> 1000 ошибок. В идеале я бы хотел избежать этой ручной работы! :) – Lydia

4

Это должно помочь вам, но могут быть более элегантные решения.

Во-первых, установить df1 и df2, чтобы другие могли быстро размножаются:

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

Далее, получить расхождения с df1 в df2 через mapply и setdiff. То есть, что в наборе тот, который не в комплекте два:

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 

Для того, чтобы подсчитать их можно использовать sapply:

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

За свой вопрос о получении идентификаторов в наборе двух, которые не находятся в наборе один, вы можете изменить процесс с помощью mapply(setdiff, df2, df1), или если это просто упражнение ids, вы можете сделать только setdiff(df2$id, df1$id).

Подробнее о функциональных функциях R (например, mapply, sapply, lapply и т. Д.) См. this post.

Смежные вопросы