2016-10-27 2 views
3

J'ai le paramètre suivant (un exemple de jouet si mon vrai problème):Comment puis-je trouver les indices de l'intersetion des trames de données dans R efficacement?

data1 = data.frame(cbind(1:8,1:8+3,1:8+5)) 
data2 = data.frame(rbind(c(4,7,9),c(7,10,12))) 

ainsi

> data1 
    X1 X2 X3 
1 1 4 6 
2 2 5 7 
3 3 6 8 
4 4 7 9 
5 5 8 10 
6 6 9 11 
7 7 10 12 
8 8 11 13 

et

> data2 
    X1 X2 X3 
1 4 7 9 
2 7 10 12 

Comment puis-je trouver les indices si les lignes de data2 dans data1 efficacement? Le résultat dans l'exemple ci-dessus doit être c(4,7). J'ai essayé de faire une boucle mais c'est trop inefficace. Merci pour toute aide!

+2

Voici une comparaison entre l'ensemble des approches différentes. Vous pouvez facilement les ajuster pour trouver les mêmes lignes et non les différences. https://www.r-bloggers.com/identifying-records-in-data-frame-a-that-are-not-contained-in-data-frame-b-%E2%80%93-a-comparison/ –

Répondre

4

Nous pouvons utiliser which avec %in%

which(do.call(paste, data1) %in% do.call(paste, data2)) 
#[1] 4 7 

Ou une jointure

library(data.table) 
setDT(data1, keep.rownames = TRUE)[data2, on = names(data2)]$rn 
#[1] "4" "7" 
+3

Juste une précision. pour 'setDT' vous devez charger le paquetage' data.table'. Ce ne sont pas des fonctions de base – cderv

3

Une autre approche de base de R serait ceci:

x <- rbind(data1, data2) 
which(duplicated(x, fromLast=TRUE)) 

#[1] 4 7 

Et un non-base-R approche, qui vous donne le bon résultat (pas le nombre de lignes, mais les valeurs de lignes)

library(compare) 
comparison <- compare(data1,data2,allowAll=TRUE) 
comparison$tM 
#  X1 X2 X3 
# 1 1 4 6 
# 2 2 5 7 
+4

La méthode 'duplicated' pour' data.frame's utilise 'paste' de façon similaire à la réponse de @ akrun. De plus, votre ligne pourrait apporter des faux positifs si 'data1' contient des lignes dupliquées non présentes dans' data2'. – nicola

3

Avec dplyr

data1 = data.frame(cbind(1:8,1:8+3,1:8+5)) 
data2 = data.frame(rbind(c(4,7,9),c(7,10,12))) 
library(dplyr) 
data1 %>% 
    # add a row id 
    mutate(rowID = row_number()) %>% 
    # keep only rows of data1 that are in data2 
    semi_join(data2) %>% 
    # keep one row ID 
    select(rowID) 
#> Joining, by = c("X1", "X2", "X3") 
#> rowID 
#> 1  4 
#> 2  7