带条件循环 data.table 行

Kes*_*etE 3 r dataframe data.table

我有一个包含 ID 和位置的 data.table。例如,这是其中一行:(它有列名和行名,不知道这是否重要)

locations<-data.table(c(11,12),c(-159.58,0.2),c(21.901,22.221))
colnames(locations)<-c("id","location_lon","location_lat")
rownames(locations)<-c("1","2")
Run Code Online (Sandbox Code Playgroud)

然后我想迭代这些行并将它们与另一个点(经纬度)进行比较。在 for 循环中它的工作原理:

for (i in 1:nrow(locations)) {
    loc <- locations[i,]
    dist <- gdist(-159.5801, 21.901, loc$location_lon, loc$location_lat, units="m")
    if(dist <= 50) {
        return (loc)
    }
    return (NULL)
}
Run Code Online (Sandbox Code Playgroud)

并返回:

id 地点经度 地点纬度

1:11 -159.58 21.901

但我想使用应用。以下代码无法运行:

dists <- apply(locations,1,function(x) if (50 - gdist(-159.5801, 21.901, x$location_lon, x$location_lat, units="m")>=0) x else NULL)
Run Code Online (Sandbox Code Playgroud)

$ operator is invalid for atomic vectors错误。更改为按位置引用 ( x[2],x[3]) 不足以解决此问题,我明白

Error in if (radius - gdist(lon, lat, x[2], x[3], units = "m") >= 0) x else NULL : 
missing value where TRUE/FALSE needed 
Run Code Online (Sandbox Code Playgroud)

这是因为 data.table 被转换为矩阵,并且坐标被视为文本而不是数字。有办法克服这个问题吗?该解决方案需要高效(我想针对 >1,000,000 个不同的坐标运行此检查)。如果需要,可以更改位置表的数据结构。

Dav*_*urg 6

不需要循环,只需data.table按预期使用即可。如果您只想查看距所需位置 50 米以内的行,您只需

locations[, if (gdist(-159.58, 21.901, location_lon, location_lat, units="m") <= 50) .SD, id]
##    id location_lon location_lat
## 1: 11      -159.58       21.901
Run Code Online (Sandbox Code Playgroud)

id在这里,我们通过数据集中的列进行迭代locations,并检查每个列是否id距 50 米以内-159.58, 21.901。如果是这样,我们调用的.SD基本上是该特定 的数据集本身id


作为旁注,data.table没有row.names,因此无需指定它们,请参见此处,例如