nsinghphd
nsinghphd

Reputation: 2022

How do I get the index of a specific data.frame in a list of data.frames?

Let's say I have the following data.frames and a list

# data frames
df1 = data.frame(y1 = c(1:5), y2 = c(8:12))
df2 = data.frame(y1 = c(5:8), y2 = c(9:12))
df3 = data.frame(y1 = c(5:8), y2 = c(9:12))
df4 = data.frame(y1 = c(11:15), y2 = c(16:20))

# list of data.frames
my.list <- list(df1, df2, df3, df4)

I want to find the position of df1 in the list, and I tried this but got NA. I also tried == but get an error.

match(df1, my.list)
# [1] NA NA

But when I do this, I get results

list14 = my.list[c(1,4)]
match(list14, my.list)
# [1] 1 4

I believe it has something to do the [] vs [[]] notation in the list. Ultimately I want do something like

for (i in list14) {
  cbind(list14, "indexPositionOf_list14_in_my.list")
}

where indexPositionOf_list14_in_my.list is the index position of respective data.frame in list14 in my.list.

Expected output from for loop

[[1]]
  y1 y2 id
1  1  8  1
2  2  9  1
3  3 10  1
4  4 11  1
5  5 12  1

[[2]]
  y1 y2 id
1 11 16  4
2 12 17  4
3 13 18  4
4 14 19  4
5 15 20  4

Upvotes: 1

Views: 62

Answers (2)

DJV
DJV

Reputation: 4863

You can use duplicated and mapply:

mapply(cbind, my.list, id=seq_along(my.list), SIMPLIFY = FALSE)[duplicated(my.list) | duplicated(my.list, fromLast = TRUE)]

[[1]]
  y1 y2 id
1  5  9  2
2  6 10  2
3  7 11  2
4  8 12  2

[[2]]
  y1 y2 id
1  5  9  3
2  6 10  3
3  7 11  3
4  8 12  3

Benchmark

library(rbenchmark)

benchmark("baseR" = {
  mapply(cbind, my.list, id=seq_along(my.list), SIMPLIFY = FALSE)[duplicated(my.list) | duplicated(my.list, fromLast = TRUE)]

},
"map" = {
  mapply(cbind, my.list, id=seq_along(my.list), SIMPLIFY = FALSE) %>% 
    map(., inner_join, df3) %>% 
    map(., compact) %>% 
    compact()
},
replications = 1000,
columns = c("test", "replications", "elapsed",
            "relative", "user.self", "sys.self"))


  test replications elapsed relative user.self
1 baseR         1000    0.37    1.000      0.38
2   map         1000    4.82   13.027      4.80
  sys.self
1     0.00
2     0.02

Upvotes: 1

zoowalk
zoowalk

Reputation: 2114

maybe something like this?

my.list<- mapply(cbind, my.list, id=seq_along(my.list), SIMPLIFY = FALSE)

my.list %>% 
  map(., inner_join, df3) %>% 
  map(., compact) %>% 
  compact()
#> Joining, by = c("y1", "y2")
#> Joining, by = c("y1", "y2")
#> Joining, by = c("y1", "y2")
#> Joining, by = c("y1", "y2")
#> [[1]]
#>   y1 y2 id
#> 1  5  9  2
#> 2  6 10  2
#> 3  7 11  2
#> 4  8 12  2
#> 
#> [[2]]
#>   y1 y2 id
#> 1  5  9  3
#> 2  6 10  3
#> 3  7 11  3
#> 4  8 12  3

Upvotes: 1

Related Questions