У меня есть вложенный список списков, который я хотел бы объединить в фрейм данных с переменными идентификатора, чтобы я знал, из каких элементов списка (и элементов подсписка) каждый пришел.
> str(gc_all)
List of 3
$ 1: num [1:102, 1:2] -74 -73.5 -73 -72.5 -71.9 ...
..- attr(*, "dimnames")=List of 2
.. ..$ : NULL
.. ..$ : chr [1:2] "lon" "lat"
$ 2: num [1:102, 1:2] -74 -73.3 -72.5 -71.8 -71 ...
..- attr(*, "dimnames")=List of 2
.. ..$ : NULL
.. ..$ : chr [1:2] "lon" "lat"
$ 3:List of 2
..$ : num [1:37, 1:2] -74 -74.4 -74.8 -75.3 -75.8 ...
.. ..- attr(*, "dimnames")=List of 2
.. .. ..$ : NULL
.. .. ..$ : chr [1:2] "lon" "lat"
..$ : num [1:65, 1:2] 180 169 163 158 154 ...
.. ..- attr(*, "dimnames")=List of 2
.. .. ..$ : NULL
.. .. ..$ : chr [1:2] "lon" "lat"
Раньше я использовал plyr::ldply(mylist, rbind)
для выравнивания списков, но, похоже, у меня возникли проблемы из-за переменной длины списка: некоторые элементы списка содержат только один фрейм данных, а другие содержат список из двух фреймов данных.
Я нашел неуклюжее решение с использованием двух lapply
и ifelse
, например:
# sample latitude-longitude data
df <- data.frame(source_lat = rep(40.7128, 3),
source_lon = rep(-74.0059, 3),
dest_lat = c(55.7982, 41.0082, -7.2575),
dest_lon = c(37.968, 28.9784, 112.7521),
id = 1:3)
# split into list
gc_list <- split(df, df$id)
# get great circles between lat-lon for each id; multiple list elements are outputted when the great circle crosses the dateline
gc_all <- lapply(gc_list, function(x) {
geosphere::gcIntermediate(x[, c("source_lon", "source_lat")],
x[, c("dest_lon", "dest_lat")],
n = 100, addStartEnd=TRUE, breakAtDateLine=TRUE)
})
gc_fortified <- lapply(1:length(gc_all), function(i) {
if(class(gc_all[[i]]) == "list") {
lapply(1:length(gc_all[[i]]), function(j) {
data.frame(gc_all[[i]][[j]], id = i, section = j)
}) %>%
plyr::rbind.fill()
} else {
data.frame(gc_all[[i]], id = i, section = 1)
}
}) %>%
plyr::rbind.fill()
Но я чувствую, что должно быть более элегантное решение, которое работает как однострочник, например. dput
, data.table
?
Вот как я ожидаю, что результат будет выглядеть так:
> gc_fortified %>%
group_by(id, section) %>%
slice(1)
lon lat id section
<dbl> <dbl> <int> <dbl>
1 -74.0059 40.71280 1 1
2 -74.0059 40.71280 2 1
3 -74.0059 40.71280 3 1
4 180.0000 79.70115 3 2
do.call("rbind.fill", lapply(gc_all, rbind.fill))
? Предполагая, что ваш список работает всего на два уровня в глубину. - person RolandASc   schedule 31.01.2018arguments imply differing number of rows
- person jogall   schedule 31.01.2018gc_fortified
содержит ожидаемый результат, но я все равно добавил его образец в вопрос. - person jogall   schedule 31.01.2018do.call("rbind.fill.matrix", lapply(gc_all, rbind.fill.matrix))
- person RolandASc   schedule 31.01.2018do.call(plyr::rbind.fill.matrix, lapply(gc_all, plyr::rbind.fill.matrix))
похоже работает, но вы не сохраняете идентификаторы элементов. - person Moody_Mudskipper   schedule 31.01.2018