Как мне получить индекс определенного data.frame в списке data.frames?

#r

#r

Вопрос:

Допустим, у меня есть следующие data.frames и список

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

Я хочу найти позицию df1 в списке, и я попробовал это, но получил NA . Я тоже пытался == , но получаю ошибку.

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

Но когда я делаю это, я получаю результаты

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

Я считаю, что это как-то связано [] [[]] с обозначением vs в списке. В конечном итоге я хочу сделать что-то вроде

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

где indexPositionOf_list14_in_my.list находится позиция индекса соответствующего data.frame в list14 in my.list .

Ожидаемый результат из for цикла

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

Комментарии:

1. Вы можете сделать match(list(df1), my.list) , но если вы просто хотите добавить индекс к каждому элементу в списке, тогда вы можете сделать mapply(cbind, my.list, id=seq_along(my.list), SIMPLIFY = FALSE)

2. Ах, это было легко для одной вещи. Спасибо. Теперь предположим, что я хочу сделать то же самое для df2 or df3 , это дает мне только позицию 2, но должно давать 2 и 3, потому df2 = df3 что . Как с этим справиться?

3. match() возвращает только первое совпадение для каждого элемента, который вы пытаетесь сопоставить в таблице. Если вам нужно вернуть несколько значений, то эта функция не для вас. match()

4. Хорошо, like %in% дает вам все совпадения, есть ли что-нибудь подобное для списков, кроме match тех, о которых вы знаете?

5. Помогает ли это вообще? which(sapply(my.list,function(x) isTRUE(all.equal(x,df2))))

Ответ №1:

Вы можете использовать duplicated и 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
  

Тест

 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
  

Ответ №2:

может быть, что-то вроде этого?

 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