Retrieve row indices in a data frame whose records match rows in another data frame

I fought for a while, and I can’t find a way out. Here is my problem.

I have 2 data frames:

    df1 <- data.frame(replicate(3,sample(1:10,20,rep=TRUE)))
    df1
      X1 X2 X3
   1  10  1  9
   2   3  4  2
   3   7  6  8
   4   8 10  7
   5   5  7  5
   6   8  5  9
   7   9  8  4
   8   6  2  7
   9   2  9  6
   10  5  2  9

  df2 <- data.frame(df1[sample(nrow(df1),4), ])
  df2
     X1 X2 X3
  8   6  2  7
  3   7  6  8
  10  5  2  9
  7   9  8  4

I would like to create a vector x of length (x) = length (df1) containing for each row df1 the row index of the corresponding row in df2 (the same exact value for each column between df1 and df2).

Consider that:

    dim(df1)
    [1] 1096188  3 

    dim(df2)
    [1] 256  3

and that df1 has several rows with the same values ​​(i.e. the corresponding row index will be the same), and that, in principle, all rows in df1 should find a match with the row in df2.

Expected Result:

    x
   [1] 0 0 2 0 0 0 4 1 0 3

Hope this was clear enough ...

You can help?

Thank,

Piera

+4
source share
4 answers

I would just try:

 x <- rownames(df2)[match(do.call(paste, df1), do.call(paste, df2))]
 x[is.na(x)] <- 0

, ; @CathG :

 match(do.call(paste, df1), do.call(paste, df2),nomatch=0)
+3

data.table:

require(data.table)

# first set the original orders (data.frame will be sorted when doing setkey)
setDT(df1)[, ori := .I]
setDT(df2)[, ind_df2 := .I]

# define keys
setkey(df1, X1, X2, X3)
setkey(df2, X1, X2, X3)

# compute the indices of the df1 line in df2
x <- df2[df1, ind_df2]
# put the nomatch to 0
x[is.na(x)] <- 0

# Finally, put the original orders back and delete the variable ori
x <- x[order(df1$ori)]
df2 <- df2[order(df2$ind_df2)]
df1[, ori:=NULL]
df2[, ind_df2:=NULL]

x ( ):

x
#[1] 0 0 2 0 0 0 4 1 0 3

, , @Frank:

setkeyv(setDT(df2)[,ii:=.I],setdiff(names(df2),"ii"))
x <- df2[df1]$ii
x[is.na(x)] <- 0

@nicola, @Frank 100000 df1 200 df2, nicola ( , as.numeric nicola's):

:

set.seed(17)
df1 <- data.frame(replicate(3,sample(1:100,100000,rep=TRUE)))
df2 <- data.frame(df1[sample(nrow(df1),200), ])

nicola <- function(){x<-match(do.call(paste,df1),do.call(paste,df2), nomatch=0)}

cath <- function(){
          dt1 <-data.table(df1); dt1[, ori:=.I]
          dt2 <- data.table(df2); dt2[, ind_df2:=.I]
          setkey(dt1, X1, X2, X3)
          setkey(dt2, X1, X2, X3)
          x <- dt2[dt1, ind_df2]
          x[is.na(x)] <- 0
          x <- x[order(dt1$ori)]
          x
        }

Frank <- function(){dt1 <-data.table(df1);dt2 <- data.table(df2); setkey(setDT(dt2)[,ii:=.I],X1,X2,X3); x <- dt2[dt1]$ii;x[is.na(x)] <- 0}

require(microbenchmark)
microbenchmark(cath(), Frank(), nicola(), unit="relative", times=100)
    #Unit: relative
    # expr       min        lq     mean    median       uq      max neval cld
  #Frank()  1.000000  1.000000 1.000000  1.000000 1.000000 1.000000   100 a  
  # cath()  3.238195  3.099896 2.438342  2.767165 2.177365 1.447397   100  b 
 #nicola() 13.127820 12.476996 8.761549 10.899191 7.292086 2.783436   100   c
+6

df1 df2 (, 1). , , (, df1, ), :

x <- rep(0, length(df1[, 1]) #initialise
for(r1 in 1:length(df1[, 1])){
  for(r2 in 1:length(df2[, 1])){
    if(identical(df1[r1,], df2[r2,])){
      x[r1] <- r2
      break
    }
  }
}

Any lines in df1 that are not actually in df2 will remain at 0. Perhaps this is not the fastest solution - how many times do you need to repeat the process?

0
source

I understand that this is a new answer to a very old question, but what is wrong with

match(data.frame(t(df1)), data.frame(t(df2))) 

??

Output signal

[1] NA NA  2 NA NA NA  4  1 NA  3

Thus, NAinstead of 0there NA, but otherwise I think it is single-line, and there is no need for do.call()or something else.

0
source

All Articles