2014-09-30 12 views
6

Ho un data.frame dat che memorizza i miei dati normali ei gruppi sono definiti da ID.R: Filtra due data.frames per valori duplicati in due colonne e per gruppi

data <- structure(list(NAME = structure(c(1L, 1L, 2L), .Label = c("NAME1", "NAME2"), class = "factor"), ID = c(23L, 23L, 57L), REF_YEAR = c(1920L, 1938L, 1869L), SURV_YEAR = c(1938L, 1962L, 1872L), VALUE = c(20L, 40L, 34L)), .Names = c("NAME", "ID", "REF_YEAR", "SURV_YEAR","VALUE"), class = "data.frame", row.names = c(NA, -3L)) 

    NAME ID REF_YEAR SURV_YEAR VALUE 
1 NAME1 23  1920  1938 20 
2 NAME1 23  1938  1962 40 
3 NAME2 57  1869  1872 34 

E ho una seconda data.frame, dat_q che vorrei confrontare dat

dat_q <- structure(list(NAME = structure(1:2, .Label = c("NAME1", "NAME2"), class = "factor"), ID = c(23L, 57L), REF_YEAR = c(1934L, 1866L), SURV_YEAR = c(1938L, 1868L), VALUE = structure(1:2, .Label = c("A", "B"), class = "factor")), .Names = c("NAME", "ID", "REF_YEAR", "SURV_YEAR", "VALUE"), class = "data.frame", row.names = c(NA, -2L)) 

    NAME ID REF_YEAR SURV_YEAR VALUE 
1 NAME1 23  1934  1938  A 
2 NAME2 57  1866  1868  B 

La mia domanda: come avrei potuto eliminare tutte le righe in dat_q che contengono un valore uguale nelle colonne REF_YEAR o SURV_YEAR rispetto alle stesse colonne di dat (nei dati di esempio 1938)? Questo dovrebbe essere applicato per gruppo (come definito dalla ID) e non su tutta data.frame

Alla fine, usando i miei dati di esempio sarebbe il risultato proveniente dalla filtrazione dat_q

NAME ID REF_YEAR SURV_YEAR VALUE 
2 NAME2 57  1866  1868  B 

EDIT

Ecco alcuni dati di esempio con i quali il codice fornito da @thelatemail non funzionerà. E non riesco a capire perché, dat_q deve essere filtrato, perché contiene esattamente lo stesso valore di dat.

data <- structure(list(NAME = structure(c(1L, 1L, 1L), .Label = "NAME1", class = "factor"), ID = c(226L, 226L, 226L), SURV_YEAR = c(2009L, 2010L, 2012L), REF_YEAR = c(2008L, 2009L, 2011L), VALUE = c(-7L, -37L, -51L)), .Names = c("NAME", "ID", "SURV_YEAR", "REF_YEAR", "VALUE"), class = "data.frame", row.names = c(NA, -3L)) 

    NAME ID SURV_YEAR REF_YEAR VALUE 
1 NAME1 226  2009  2008 -7 
2 NAME1 226  2010  2009 -37 
3 NAME1 226  2012  2011 -51 

dat_q <- structure(list(NAME = structure(1L, .Label = "NAME1", class = "factor"), ID = 226L, REF_YEAR = 2010L, SURV_YEAR = 2011L, VALUE = structure(1L, .Label = "-X", class = "factor")), .Names = c("NAME", "ID", "REF_YEAR", "SURV_YEAR", "VALUE"), class = "data.frame", row.names = c(NA, -1L)) 

    NAME ID REF_YEAR SURV_YEAR VALUE 
1 NAME1 226  2010  2011 -X 

risposta

5

mi piace by a base di R per capire la logica di questo tipo di problema. Questo funziona, ma può essere un po 'lento:

do.call(rbind,by(
    dat_q, 
    dat_q$ID, 
    function(x) { 
    subdata <- data[data$ID==x$ID,] 
    x[!(x$REF_YEAR %in% subdata$REF_YEAR | x$SURV_YEAR %in% subdata$SURV_YEAR),] 
    } 
)) 

# NAME ID REF_YEAR SURV_YEAR VALUE 
#57 NAME2 57  1866  1868  B 

Una soluzione data.table seguendo la stessa logica può essere più veloce:

library(data.table) 
setDT(dat_q) 
setDT(data) 
dat_q[ 
    , 
    .SD[!(REF_YEAR %in% data$REF_YEAR[data[,ID==.BY]] | 
      SURV_YEAR %in% data$SURV_YEAR[data[,ID==.BY]])], 
    by=ID 
] 

# ID NAME REF_YEAR SURV_YEAR VALUE 
#1: 57 NAME2  1866  1868  B 

Con data.table, penso anche che si può fare in questo modo . Dopo la conversione di data.tables,

# using 1.9.3+, just remove `by=.EACHI` if you're using <= 1.9.2 
setkey(data, ID) 
setkey(dat_q, ID) 

idx = data[dat_q, any(c(i.REF_YEAR, i.SURV_YEAR) %in% c(REF_YEAR, SURV_YEAR)), by=.EACHI]$V1 
dat_q[!idx] 
#  NAME ID REF_YEAR SURV_YEAR VALUE 
# 1: NAME2 57  1866  1868  B 

eseguiamo una join, e su ogni righe corrispondenti di data corrispondenti a dat_q, sulle colonne chiave, calcoliamo l'espressione in j. Questo ci dà il valore logico di cui abbiamo bisogno per indicizzare/sottoinsieme dat_q in seguito.

+0

Non penso che tu abbia bisogno della parte '[data [, ID ==. BY]]' –

+0

@DavidArenburg - Devo sicuramente limitare le parti rispetto agli id ​​corrispondenti? I riferimenti a 'data' non saranno automaticamente assegnati ai gruppi' by'. – thelatemail

+0

Grazie @thelatemail! mentre questo funziona per alcuni dei miei dati, non riesco a capire perché non lo fa per tutto nei miei dati. Ho pubblicato una modifica e aggiunto nuovi dati di esempio con i quali non funzionerà. Dovrebbe filtrare 'dat_q', perché il 2011 appare in entrambi gli esempi di dati. – kurdtc

Problemi correlati