【问题标题】:R: Apply function to nested listsR:将函数应用于嵌套列表
【发布时间】:2021-07-12 06:26:11
【问题描述】:

我有带有数字值的嵌套列表。就我而言,它们是按如下方式排序的经度和纬度:

list1 <- list(1:50, 1:25, 1:30)
list2 <- list(1:50, 1:25)
list3 <- list(1:30)
list4 <- list(1:50, 1:25, 1:30, 1:45)
nested_lons1 <- list(list1, list2, list3, list4) 
nested_lons2 <- list(list1, list2, list3, list4) 
nested_lats1 <- list(list1, list2, list3, list4) 
nested_lats2 <- list(list1, list2, list3, list4)

随机数仅用于说明目的。 我想使用 Haversine 公式计算每个嵌套列表(list1 到 list4)的两点之间的距离。我读到最好避免 for 循环,这就是我关注 lapply 的原因。

dist <- lapply(1:4, function(x) distHaversine(c(nested_lons1[x],nested_lats1[x]),
                                              c(nested_lons2[x],nested_lats2[x]), r = 6371)) 

这会产生类似“无法转换为双精度”的错误。我认为索引也是错误的,因为该函数应该遍历第一个列表的嵌套列表,然后转到第二个列表中的嵌套列表,依此类推,直到第四个。我怎样才能做到这一点?还有其他(更好的)方法吗?谢谢!

【问题讨论】:

  • 来自distHaversine 文档:“点的经度/纬度。可以是两个数字的向量、2 列的矩阵(第一列是经度,第二列是纬度)或 SpatialPoints * object" 而nested_lons1[x]nested_lats1[x] 是列表的列表。注意例如:nested_lons1[[1]][[1]]是实际的向量,1:50
  • @SteveM 你的意思是对于列表列表我必须使用像 [[x]] [[x]] 这样的实际向量吗?
  • 这个功能我没玩过。在nested_lons[1]nested_lons[[1]]nested_lons[[1]][1]nested_lons[[1]][[1]]] 上执行str 以比较列表列表的维护方式。建议您在lapply 之外尝试单个distHaversine 函数计算,看看哪个列表调用可能会起作用。
  • @SteveM 似乎nested_lons[[1]][[1]][1] 有效!它是唯一一个从嵌套列表中访问正确元素的方法。但是我怎样才能将它重新定义为一个循环呢?我需要三个索引 lapply 吗?如果是这样,我该如何编写函数?

标签: r list loops lapply haversine


【解决方案1】:

如果您的列表结构匹配,就像您在示例中所做的那样,unlist 然后relist 数据可能更简单。首先 unlist 经纬度数据和 cbind 制作 2 列矩阵:

library(geosphere)
p1 <- cbind(unlist(nested_lons1), unlist(nested_lats1))
p2 <- cbind(unlist(nested_lons2), unlist(nested_lats2))

现在计算距离并转换回相同结构的列表:

d12 <- distHaversine(p1, p2)
d12.lst <- relist(d12, nested_lons1)
str(d12.lst)
# List of 4
#  $ :List of 3
#   ..$ : num [1:50] 0 0 0 0 0 0 0 0 0 0 ...
#   ..$ : num [1:25] 0 0 0 0 0 0 0 0 0 0 ...
#   ..$ : num [1:30] 0 0 0 0 0 0 0 0 0 0 ...
#  $ :List of 2
#   ..$ : num [1:50] 0 0 0 0 0 0 0 0 0 0 ...
#   ..$ : num [1:25] 0 0 0 0 0 0 0 0 0 0 ...
#  $ :List of 1
#   ..$ : num [1:30] 0 0 0 0 0 0 0 0 0 0 ...
#  $ :List of 4
#   ..$ : num [1:50] 0 0 0 0 0 0 0 0 0 0 ...
#   ..$ : num [1:25] 0 0 0 0 0 0 0 0 0 0 ...
#   ..$ : num [1:30] 0 0 0 0 0 0 0 0 0 0 ...
#   ..$ : num [1:45] 0 0 0 0 0 0 0 0 0 0 ...

当然,这仅适用于四个嵌套列表具有相同结构的情况。

【讨论】:

  • 谢谢!我尝试了你的方法,但是从 d12
  • 对不起。我已经更正了代码。我不小心包含了之前尝试中的一行。现在可以使用了。
  • 非常感谢!即使使用更多嵌套列表,它也能按预期工作。我对这一行只有一个问题: d12.lst
  • 是的。所有列表必须具有相同的结构,以便其中任何一个都可以工作。该函数只是复制列表的结构,而不是数据。
猜你喜欢
  • 1970-01-01
  • 2021-11-03
  • 1970-01-01
  • 2021-02-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-17
  • 1970-01-01
相关资源
最近更新 更多