2014-12-11 17 views
7

Vorrei confrontare due serie di dati e identificare specifiche istanze di discrepanze tra di esse (ad esempio, quali variabili erano diverse).Identificazione delle differenze specifiche tra due serie di dati in R

Mentre ho trovato il modo di identificare quali record non sono identici tra i due insiemi di dati (utilizzando la funzione dettagliato qui: http://www.cookbook-r.com/Manipulating_data/Comparing_data_frames/), io non sono sicuro di come bandiera che variabili sono diversi.

E.g.

dati impostato A: insieme

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 

dati 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 

voglio identificare quali record sono diversi, e quale variabile specifico (s) hanno discrepanze. Ad esempio, il record di John Doe ha 1 discrepanza in dose e il record di Jane Doe ha 2 discrepanze: in name e vaccinedate. Inoltre, il set di dati B ha un record aggiuntivo che non era nel set di dati A, e vorrei anche identificare queste istanze.

Alla fine, l'obiettivo è trovare la frequenza dei "tipi" di errori, ad es. quanti record hanno una discrepanza in vaccinato, vaccinename, dose, ecc.

Grazie!

+0

Prova la [distanza di Hamming] (https://en.wikipedia.org/wiki/Hamming_distance) – Gathide

risposta

1

Una possibilità. Innanzitutto, scopri quali ID hanno in comune entrambi i set di dati. Il modo più semplice per farlo è:

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

Quindi è possibile determinare quali righe mancanti da A:

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

Avanti, è possibile limitare entrambe le serie di dati agli ID che hanno in comune.

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

Se non si può presumere che gli ID sono nel giusto ordine, poi ordinarli entrambi:

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

ora si può vedere ciò che i campi sono diversi, come questo.

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

Questa è una matrice logica e puoi fare tutto ciò che vuoi con esso. Ad esempio, per trovare il numero totale di errori in ogni colonna:

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

per trovare tutti gli ID in cui il nome è diverso:

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

E così via.

+0

Grazie! Non ho specificato nel mio esempio i dataframes sopra, ma i miei dati effettivi hanno più record per ogni id. Ad esempio, John Doe potrebbe avere 5 tipi di vaccini e ciascun vaccino potrebbe avere più dosi. Nella prima riga di codice, come è possibile determinare quali righe hanno in comune entrambi i set di dati, non solo basandole su id? Spero che questo abbia un senso. – Lydia

+0

Non c'è una risposta concreta a questa domanda. Il problema è che se due righe non sono identiche, come decidi se sono "supposte" uguali ma c'è una discrepanza o se sono in realtà voci completamente diverse. Devi trovare alcuni criteri per prendere questa decisione. – mrip

+0

È vero. Uno dei set di dati è il "gold standard" (dai record di vaccinazione cartacea) mentre l'altro è stato inserito elettronicamente separatamente, quindi il primo set di dati dovrebbe essere quello "corretto". Questo aiuta a chiarire le cose? La persona precedente che ha effettuato questo controllo ha esaminato le discrepanze manualmente in Excel, trovando> 1000 errori. Idealmente, vorrei evitare questo lavoro manuale! :) – Lydia

4

Questo dovrebbe iniziare, ma potrebbero esserci soluzioni più eleganti.

In primo luogo, stabilire df1 e df2 così gli altri possono riprodursi rapidamente:

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

Avanti, ottenere le discrepanze da df1 a df2 via mapply e setdiff. Cioè, cosa c'è in un set che non è nel set due:

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 

di contarli fino possiamo usare sapply:

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

Per la tua domanda su come ottenere id nel set due che non sono in set uno, è possibile invertire il processo con mapply(setdiff, df2, df1) o se è semplicemente un esercizio di ids solo si potrebbe fare setdiff(df2$id, df1$id).

Per ulteriori informazioni sulle funzioni funzionali di R (ad esempio, mapply, sapply, lapply, ecc.) Vedere this post.

Problemi correlati