使用 nngeo 获取下一个邻居的 ID (nn_st)
Getting ID of next neigbour using nngeo (nn_st)
我需要计算物体(学校)之间的最近距离。我有两个 sf-data-frames(sf_special 和 sf_no_special)。我使用了 nngeo 包和 nn_st 命令,效果很好! nn_st 的输出是 a) 最近的两所学校之间的距离和 b) 最近学校的索引。最近学校的索引无法帮助我识别学校。我想要的是学号(id)。如何使用最近邻居的索引检索此信息?这是我的代码和相同的数据示例:
ata01 <- read.delim2('0708.txt',header = TRUE, sep = ";", dec = ".")
data01$sps[is.na(data01$sps)]<-0
special <- subset(data01, sps == 1,
select=c(id, geo, sps, lon, lat))
no_special <- subset(data01, sps == 0,
select=c(id, geo, sps, lon, lat))
sf_special <- st_as_sf(special,
coords = c("lon", "lat"), # x, y (order matters)
crs = 4326)
sf_no_special <- st_as_sf(no_special,
coords = c("lon", "lat"), # x, y (order matters)
crs = 4326)
nearest <- st_nn(sf_special,sf_no_special, k = 1, returnDist = T, progress = FALSE)
special$dist = nn_dist$dist
special$n = nn_dist$nn
现在输出如下所示:
id geo sps lon lat dist n
8 23880 Blankartstr. 13;53474;Bad Neuenahr-Ahrweiler 1 7.102950 50.54219 2088.908 6
32 14176 Siegener Str. 26;57610;Altenkirchen 1 7.651246 50.68972 918.4893 30
35 26147 Johannes-Krell-Str. 17;57518;Betzdorf 1 7.851260 50.79092 589.7386 52
45 13408 Schulstr.;57580;Gebhardshain 1 7.823415 50.74588 3302.691 48
46 10435 Martin-Luther-Str. 4;57577;Hamm 1 7.669567 50.76203 2005.314 38
62 23954 Schulstr. 10;67577;Alsheim 1 8.335559 49.76163 3584.156 68
两个问题:
我想要最近学校的ID,而不是n(从“最近”开始的下一所学校的索引)!我如何使用索引来检索学校 ID 等信息?学校ID存储在sf_no_special中,但最近的索引和sf_no_special不匹配!
我还想创建一个包含 1.5 公里半径内学校数量的变量。我可以使用 nn_st 命令获取到最近的 j 所学校的距离,然后我需要对 dist < 1.500 的学校求和。有什么建议么?我试过了:
num.1500 <- apply(nearest$dist, 1, function(x) {
sum(x < 1500)
})
但我确实得到了错误:
Error in apply(nearest$dist, 1, function(x) { :
dim(X) muss positive Länge haben
这是我的数据示例:
> dput(droplevels(data01[1:10, ]))
structure(list(typ = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L,
1L, 1L, 1L), .Label = "Grundschule", class = "factor"), id = c(11725L,
11739L, 26883L, 11863L, 11996L, 12060L, 22062L, 23880L, 12237L,
12630L), str = structure(c(7L, 4L, 8L, 3L, 5L, 10L, 9L, 2L, 1L,
6L), .Label = c("Ahrstr. 87", "Blankartstr. 13", "Eichenbacher Weg 26",
"Kesslinger Str. 1", "Koblenzer Str.", "Quellenstr. 15", "Schulstr.",
"Schulstr. 5", "Vehner Weg 31", "Weststr. 27"), class = "factor"),
plz = c(53518L, 53506L, 53505L, 53533L, 53498L, 53474L, 53474L,
53474L, 53505L, 56656L), ort = structure(c(1L, 2L, 3L, 4L,
5L, 6L, 6L, 6L, 7L, 8L), .Label = c("Adenau", "Ahrbrück",
"Altenahr", "Antweiler", "Bad Breisig", "Bad Neuenahr-Ahrweiler",
"Berg", "Brohl-Lützing"), class = "factor"), geo = structure(c(8L,
4L, 7L, 3L, 5L, 10L, 9L, 2L, 1L, 6L), .Label = c("Ahrstr. 87;53505;Berg",
"Blankartstr. 13;53474;Bad Neuenahr-Ahrweiler", "Eichenbacher Weg 26;53533;Antweiler",
"Kesslinger Str. 1;53506;Ahrbrück", "Koblenzer Str.;53498;Bad Breisig",
"Quellenstr. 15;56656;Brohl-Lützing", "Schulstr. 5;53505;Altenahr",
"Schulstr.;53518;Adenau", "Vehner Weg 31;53474;Bad Neuenahr-Ahrweiler",
"Weststr. 27;53474;Bad Neuenahr-Ahrweiler"), class = "factor"),
jahr = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L
), .Label = "2007/08", class = "factor"), name = structure(c(NA,
NA, NA, NA, NA, NA, NA, 1L, NA, NA), .Label = "GS Ahrweiler", class = "factor"),
start = structure(c(NA, NA, NA, NA, NA, NA, NA, 1L, NA, NA
), .Label = "2001/02", class = "factor"), sps = c(0, 0, 0,
0, 0, 0, 0, 1, 0, 0), lon = c(6.9325459, 6.97516, 6.9875745,
6.825407, 7.3035599, 7.1322642, 7.1809, 7.10295, 6.93609,
7.32739), lat = c(50.382685, 50.48649, 50.5085722, 50.406783,
50.5055535, 50.5441126, 50.54013, 50.54219, 50.52239, 50.48599
), dist = list(2088.90766536052, 918.489268082922, 589.738579014495,
3302.69115170858, 2005.31411895232, 3584.15570982643,
366.260782140767, 2694.12065272956, 5257.32234958339,
1700.27776226661), n = list(6L, 30L, 52L, 48L, 38L, 68L,
58L, 84L, 142L, 138L)), row.names = c(NA, 10L), class = "data.frame")
>
> dput(droplevels(special[1:10, ]))
structure(list(id = c(23880L, 14176L, 26147L, 13408L, 10435L,
23954L, 20647L, 26447L, 15617L, 23173L), geo = structure(c(2L,
9L, 4L, 8L, 5L, 6L, 3L, 10L, 1L, 7L), .Label = c("Beindestr.;55569;Monzingen",
"Blankartstr. 13;53474;Bad Neuenahr-Ahrweiler", "Donnersbergstr. 32;55232;Alzey",
"Johannes-Krell-Str. 17;57518;Betzdorf", "Martin-Luther-Str. 4;57577;Hamm",
"Schulstr. 10;67577;Alsheim", "Schulstr.;55593;Rüdesheim", "Schulstr.;57580;Gebhardshain",
"Siegener Str. 26;57610;Altenkirchen", "Weinstr. 79;67169;Kallstadt"
), class = "factor"), sps = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
lon = c(7.10295, 7.6512462, 7.85126, 7.8234146, 7.6695674,
8.3355588, 8.1119607, 8.17405, 7.5906339, 7.8107492), lat = c(50.54219,
50.6897185, 50.79092, 50.7458834, 50.7620283, 49.7616261,
49.7408171, 49.49098, 49.7968555, 49.8468627), dist = list(
2088.90766536052, 918.489268082922, 589.738579014495,
3302.69115170858, 2005.31411895232, 3584.15570982643,
366.260782140767, 2694.12065272956, 5257.32234958339,
1700.27776226661), n = list(6L, 30L, 52L, 48L, 38L, 68L,
58L, 84L, 142L, 138L)), row.names = c(8L, 32L, 35L, 45L,
46L, 62L, 63L, 109L, 143L, 148L), class = "data.frame")
> dput(droplevels(no_special[1:10, ]))
structure(list(id = c(11725L, 11739L, 26883L, 11863L, 11996L,
12060L, 22062L, 12237L, 12630L, 26537L), geo = structure(c(8L,
4L, 7L, 2L, 5L, 10L, 9L, 1L, 6L, 3L), .Label = c("Ahrstr. 87;53505;Berg",
"Eichenbacher Weg 26;53533;Antweiler", "Greimerstalweg 19;56659;Burgbrohl",
"Kesslinger Str. 1;53506;Ahrbrück", "Koblenzer Str.;53498;Bad Breisig",
"Quellenstr. 15;56656;Brohl-Lützing", "Schulstr. 5;53505;Altenahr",
"Schulstr.;53518;Adenau", "Vehner Weg 31;53474;Bad Neuenahr-Ahrweiler",
"Weststr. 27;53474;Bad Neuenahr-Ahrweiler"), class = "factor"),
sps = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0), lon = c(6.9325459,
6.97516, 6.9875745, 6.825407, 7.3035599, 7.1322642, 7.1809,
6.93609, 7.32739, 7.27089), lat = c(50.382685, 50.48649,
50.5085722, 50.406783, 50.5055535, 50.5441126, 50.54013,
50.52239, 50.48599, 50.45707)), row.names = c(1L, 2L, 3L,
4L, 5L, 6L, 7L, 9L, 10L, 11L), class = "data.frame")
感谢您的帮助!
edit2:(预期输出)
head(special)
id geo sps lon lat dist n ID Radius-1500
8 23880 Blankartstr. 13;53474;Bad Neuenahr-Ahrweiler 1 7.102950 50.54219 2088.908 6
32 14176 Siegener Str. 26;57610;Altenkirchen 1 7.651246 50.68972 918.4893 30
35 26147 Johannes-Krell-Str. 17;57518;Betzdorf 1 7.851260 50.79092 589.7386 52
45 13408 Schulstr.;57580;Gebhardshain 1 7.823415 50.74588 3302.691 48
46 10435 Martin-Luther-Str. 4;57577;Hamm 1 7.669567 50.76203 2005.314 38
62 23954 Schulstr. 10;67577;Alsheim 1 8.335559 49.76163 3584.156 68
请检查以下代码,因为我仍然不能 100% 确定我理解您的问题。首先我需要加载一些包:
library(sf)
#> Linking to GEOS 3.8.0, GDAL 3.0.4, PROJ 6.3.1
library(nngeo)
library(tmap) # for the final map
和数据
special <- structure(
list(
id = c(
23880L, 14176L, 26147L, 13408L, 10435L, 23954L, 20647L, 26447L, 15617L, 23173L
),
geo = structure(
c(
2L, 9L, 4L, 8L, 5L, 6L, 3L, 10L, 1L, 7L
),
.Label = c(
"Beindestr.;55569;Monzingen", "Blankartstr. 13;53474;Bad Neuenahr-Ahrweiler",
"Donnersbergstr. 32;55232;Alzey", "Johannes-Krell-Str. 17;57518;Betzdorf",
"Martin-Luther-Str. 4;57577;Hamm", "Schulstr. 10;67577;Alsheim",
"Schulstr.;55593;Rudesheim", "Schulstr.;57580;Gebhardshain",
"Siegener Str. 26;57610;Altenkirchen", "Weinstr. 79;67169;Kallstadt"
),
class = "factor"
),
sps = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
lon = c(
7.10295, 7.6512462, 7.85126, 7.8234146, 7.6695674, 8.3355588, 8.1119607,
8.17405, 7.5906339, 7.8107492
),
lat = c(
50.54219, 50.6897185, 50.79092, 50.7458834, 50.7620283, 49.7616261,
49.7408171, 49.49098, 49.7968555, 49.8468627
),
dist = list(
2088.90766536052, 918.489268082922, 589.738579014495, 3302.69115170858,
2005.31411895232, 3584.15570982643, 366.260782140767, 2694.12065272956,
5257.32234958339, 1700.27776226661
),
n = list(6L, 30L, 52L, 48L, 38L, 68L, 58L, 84L, 142L, 138L)
),
row.names = c(8L, 32L, 35L, 45L, 46L, 62L, 63L, 109L, 143L, 148L),
class = "data.frame"
)
# input data for "no-special"
no_special <- structure(
list(
id = c(
11725L, 11739L, 26883L, 11863L, 11996L, 12060L, 22062L, 12237L, 12630L, 26537L
),
geo = structure(
c(8L, 4L, 7L, 2L, 5L, 10L, 9L, 1L, 6L, 3L),
.Label = c(
"Ahrstr. 87;53505;Berg", "Eichenbacher Weg 26;53533;Antweiler",
"Greimerstalweg 19;56659;Burgbrohl", "Kesslinger Str. 1;53506;Ahrbruck",
"Koblenzer Str.;53498;Bad Breisig", "Quellenstr. 15;56656;Brohl-Lutzing",
"Schulstr. 5;53505;Altenahr", "Schulstr.;53518;Adenau",
"Vehner Weg 31;53474;Bad Neuenahr-Ahrweiler", "Weststr. 27;53474;Bad Neuenahr Ahrweiler"
),
class = "factor"
),
sps = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
lon = c(
6.9325459, 6.97516, 6.9875745, 6.825407, 7.3035599, 7.1322642, 7.1809,
6.93609, 7.32739, 7.27089
),
lat = c(
50.382685, 50.48649, 50.5085722, 50.406783, 50.5055535, 50.5441126,
50.54013, 50.52239, 50.48599, 50.45707
)
),
row.names = c(1L, 2L, 3L, 4L, 5L, 6L, 7L, 9L, 10L, 11L),
class = "data.frame"
)
然后我需要将数据转换成sf
个对象:
sf_special <- st_as_sf(
special,
coords = c("lon", "lat"), # x, y (order matters)
crs = 4326
)
sf_no_special <- st_as_sf(
no_special,
coords = c("lon", "lat"), # x, y (order matters)
crs = 4326
)
找到所有特殊和所有非特殊之间的最近邻居
nearest <- st_nn(sf_special, sf_no_special, k = 1, returnDist = FALSE, progress = FALSE)
#> lon-lat points
检查结果
nearest
#> [[1]]
#> [1] 6
#>
#> [[2]]
#> [1] 5
#>
#> [[3]]
#> [1] 5
#>
#> [[4]]
#> [1] 5
#>
#> [[5]]
#> [1] 5
#>
#> [[6]]
#> [1] 9
#>
#> [[7]]
#> [1] 10
#>
#> [[8]]
#> [1] 10
#>
#> [[9]]
#> [1] 10
#>
#> [[10]]
#> [1] 10
该输出表示 sf_special
中的第一所学校与 sf_no_special
中的学校之间最近的邻居是 sf_no_special
中的第 6 所学校。同样的想法适用于所有其他指数。我们可以提取 sf_no_special
个 ID,如下所示:
sf_no_special[unlist(nearest), "id", drop = TRUE]
#> [1] 12060 11996 11996 11996 11996 12630 26537 26537 26537 26537
#> attr(,"class")
#> [1] "integer"
并将该信息附加到 sf_special
sf_special$ID <- sf_no_special[unlist(nearest), "id", drop = TRUE]
检查结果
sf_special
#> Simple feature collection with 10 features and 6 fields
#> geometry type: POINT
#> dimension: XY
#> bbox: xmin: 7.10295 ymin: 49.49098 xmax: 8.335559 ymax: 50.79092
#> geographic CRS: WGS 84
#> id geo sps dist n
#> 8 23880 Blankartstr. 13;53474;Bad Neuenahr-Ahrweiler 1 2088.908 6
#> 32 14176 Siegener Str. 26;57610;Altenkirchen 1 918.4893 30
#> 35 26147 Johannes-Krell-Str. 17;57518;Betzdorf 1 589.7386 52
#> 45 13408 Schulstr.;57580;Gebhardshain 1 3302.691 48
#> 46 10435 Martin-Luther-Str. 4;57577;Hamm 1 2005.314 38
#> 62 23954 Schulstr. 10;67577;Alsheim 1 3584.156 68
#> 63 20647 Donnersbergstr. 32;55232;Alzey 1 366.2608 58
#> 109 26447 Weinstr. 79;67169;Kallstadt 1 2694.121 84
#> 143 15617 Beindestr.;55569;Monzingen 1 5257.322 142
#> 148 23173 Schulstr.;55593;Rudesheim 1 1700.278 138
#> geometry ID
#> 8 POINT (7.10295 50.54219) 12060
#> 32 POINT (7.651246 50.68972) 11996
#> 35 POINT (7.85126 50.79092) 11996
#> 45 POINT (7.823415 50.74588) 11996
#> 46 POINT (7.669567 50.76203) 11996
#> 62 POINT (8.335559 49.76163) 12630
#> 63 POINT (8.111961 49.74082) 26537
#> 109 POINT (8.17405 49.49098) 26537
#> 143 POINT (7.590634 49.79686) 26537
#> 148 POINT (7.810749 49.84686) 26537
如果你想查看每所特殊学校15公里范围内有多少所非特殊学校,我们可以使用st_is_within_distance
no_special_within_radius <- st_is_within_distance(
x = sf_special,
y = sf_no_special,
dist = units::set_units(15, "km")
)
no_special_within_radius
#> Sparse geometry binary predicate list of length 10, where the predicate was `is_within_distance'
#> 1: 2, 3, 5, 6, 7, 8
#> 2: (empty)
#> 3: (empty)
#> 4: (empty)
#> 5: (empty)
#> 6: (empty)
#> 7: (empty)
#> 8: (empty)
#> 9: (empty)
#> 10: (empty)
输出表示sf_no_special
的学校2、3、5、6、7、8距离sf_special
的第一所学校在15km以内。其他学校离他们的邻居太远了。我们可以使用函数长度计算学校数量,并将该信息添加到 sf_special
:
sf_special$within_radius <- lengths(no_special_within_radius)
查看结果:
sf_special
#> Simple feature collection with 10 features and 7 fields
#> geometry type: POINT
#> dimension: XY
#> bbox: xmin: 7.10295 ymin: 49.49098 xmax: 8.335559 ymax: 50.79092
#> geographic CRS: WGS 84
#> id geo sps dist n
#> 8 23880 Blankartstr. 13;53474;Bad Neuenahr-Ahrweiler 1 2088.908 6
#> 32 14176 Siegener Str. 26;57610;Altenkirchen 1 918.4893 30
#> 35 26147 Johannes-Krell-Str. 17;57518;Betzdorf 1 589.7386 52
#> 45 13408 Schulstr.;57580;Gebhardshain 1 3302.691 48
#> 46 10435 Martin-Luther-Str. 4;57577;Hamm 1 2005.314 38
#> 62 23954 Schulstr. 10;67577;Alsheim 1 3584.156 68
#> 63 20647 Donnersbergstr. 32;55232;Alzey 1 366.2608 58
#> 109 26447 Weinstr. 79;67169;Kallstadt 1 2694.121 84
#> 143 15617 Beindestr.;55569;Monzingen 1 5257.322 142
#> 148 23173 Schulstr.;55593;Rudesheim 1 1700.278 138
#> geometry ID within_radius
#> 8 POINT (7.10295 50.54219) 12060 6
#> 32 POINT (7.651246 50.68972) 11996 0
#> 35 POINT (7.85126 50.79092) 11996 0
#> 45 POINT (7.823415 50.74588) 11996 0
#> 46 POINT (7.669567 50.76203) 11996 0
#> 62 POINT (8.335559 49.76163) 12630 0
#> 63 POINT (8.111961 49.74082) 26537 0
#> 109 POINT (8.17405 49.49098) 26537 0
#> 143 POINT (7.590634 49.79686) 26537 0
#> 148 POINT (7.810749 49.84686) 26537 0
我们还可以绘制学校并以图形方式检查结果:
tmap_mode("view")
#> tmap mode set to interactive viewing
tm_shape(sf_special) +
tm_dots() +
tm_shape(sf_no_special) +
tm_dots(col = "red")
由 reprex package (v0.3.0)
于 2020-06-29 创建
我需要计算物体(学校)之间的最近距离。我有两个 sf-data-frames(sf_special 和 sf_no_special)。我使用了 nngeo 包和 nn_st 命令,效果很好! nn_st 的输出是 a) 最近的两所学校之间的距离和 b) 最近学校的索引。最近学校的索引无法帮助我识别学校。我想要的是学号(id)。如何使用最近邻居的索引检索此信息?这是我的代码和相同的数据示例:
ata01 <- read.delim2('0708.txt',header = TRUE, sep = ";", dec = ".")
data01$sps[is.na(data01$sps)]<-0
special <- subset(data01, sps == 1,
select=c(id, geo, sps, lon, lat))
no_special <- subset(data01, sps == 0,
select=c(id, geo, sps, lon, lat))
sf_special <- st_as_sf(special,
coords = c("lon", "lat"), # x, y (order matters)
crs = 4326)
sf_no_special <- st_as_sf(no_special,
coords = c("lon", "lat"), # x, y (order matters)
crs = 4326)
nearest <- st_nn(sf_special,sf_no_special, k = 1, returnDist = T, progress = FALSE)
special$dist = nn_dist$dist
special$n = nn_dist$nn
现在输出如下所示:
id geo sps lon lat dist n
8 23880 Blankartstr. 13;53474;Bad Neuenahr-Ahrweiler 1 7.102950 50.54219 2088.908 6
32 14176 Siegener Str. 26;57610;Altenkirchen 1 7.651246 50.68972 918.4893 30
35 26147 Johannes-Krell-Str. 17;57518;Betzdorf 1 7.851260 50.79092 589.7386 52
45 13408 Schulstr.;57580;Gebhardshain 1 7.823415 50.74588 3302.691 48
46 10435 Martin-Luther-Str. 4;57577;Hamm 1 7.669567 50.76203 2005.314 38
62 23954 Schulstr. 10;67577;Alsheim 1 8.335559 49.76163 3584.156 68
两个问题:
我想要最近学校的ID,而不是n(从“最近”开始的下一所学校的索引)!我如何使用索引来检索学校 ID 等信息?学校ID存储在sf_no_special中,但最近的索引和sf_no_special不匹配!
我还想创建一个包含 1.5 公里半径内学校数量的变量。我可以使用 nn_st 命令获取到最近的 j 所学校的距离,然后我需要对 dist < 1.500 的学校求和。有什么建议么?我试过了:
num.1500 <- apply(nearest$dist, 1, function(x) {
sum(x < 1500)
})
但我确实得到了错误:
Error in apply(nearest$dist, 1, function(x) { :
dim(X) muss positive Länge haben
这是我的数据示例:
> dput(droplevels(data01[1:10, ]))
structure(list(typ = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L,
1L, 1L, 1L), .Label = "Grundschule", class = "factor"), id = c(11725L,
11739L, 26883L, 11863L, 11996L, 12060L, 22062L, 23880L, 12237L,
12630L), str = structure(c(7L, 4L, 8L, 3L, 5L, 10L, 9L, 2L, 1L,
6L), .Label = c("Ahrstr. 87", "Blankartstr. 13", "Eichenbacher Weg 26",
"Kesslinger Str. 1", "Koblenzer Str.", "Quellenstr. 15", "Schulstr.",
"Schulstr. 5", "Vehner Weg 31", "Weststr. 27"), class = "factor"),
plz = c(53518L, 53506L, 53505L, 53533L, 53498L, 53474L, 53474L,
53474L, 53505L, 56656L), ort = structure(c(1L, 2L, 3L, 4L,
5L, 6L, 6L, 6L, 7L, 8L), .Label = c("Adenau", "Ahrbrück",
"Altenahr", "Antweiler", "Bad Breisig", "Bad Neuenahr-Ahrweiler",
"Berg", "Brohl-Lützing"), class = "factor"), geo = structure(c(8L,
4L, 7L, 3L, 5L, 10L, 9L, 2L, 1L, 6L), .Label = c("Ahrstr. 87;53505;Berg",
"Blankartstr. 13;53474;Bad Neuenahr-Ahrweiler", "Eichenbacher Weg 26;53533;Antweiler",
"Kesslinger Str. 1;53506;Ahrbrück", "Koblenzer Str.;53498;Bad Breisig",
"Quellenstr. 15;56656;Brohl-Lützing", "Schulstr. 5;53505;Altenahr",
"Schulstr.;53518;Adenau", "Vehner Weg 31;53474;Bad Neuenahr-Ahrweiler",
"Weststr. 27;53474;Bad Neuenahr-Ahrweiler"), class = "factor"),
jahr = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L
), .Label = "2007/08", class = "factor"), name = structure(c(NA,
NA, NA, NA, NA, NA, NA, 1L, NA, NA), .Label = "GS Ahrweiler", class = "factor"),
start = structure(c(NA, NA, NA, NA, NA, NA, NA, 1L, NA, NA
), .Label = "2001/02", class = "factor"), sps = c(0, 0, 0,
0, 0, 0, 0, 1, 0, 0), lon = c(6.9325459, 6.97516, 6.9875745,
6.825407, 7.3035599, 7.1322642, 7.1809, 7.10295, 6.93609,
7.32739), lat = c(50.382685, 50.48649, 50.5085722, 50.406783,
50.5055535, 50.5441126, 50.54013, 50.54219, 50.52239, 50.48599
), dist = list(2088.90766536052, 918.489268082922, 589.738579014495,
3302.69115170858, 2005.31411895232, 3584.15570982643,
366.260782140767, 2694.12065272956, 5257.32234958339,
1700.27776226661), n = list(6L, 30L, 52L, 48L, 38L, 68L,
58L, 84L, 142L, 138L)), row.names = c(NA, 10L), class = "data.frame")
>
> dput(droplevels(special[1:10, ]))
structure(list(id = c(23880L, 14176L, 26147L, 13408L, 10435L,
23954L, 20647L, 26447L, 15617L, 23173L), geo = structure(c(2L,
9L, 4L, 8L, 5L, 6L, 3L, 10L, 1L, 7L), .Label = c("Beindestr.;55569;Monzingen",
"Blankartstr. 13;53474;Bad Neuenahr-Ahrweiler", "Donnersbergstr. 32;55232;Alzey",
"Johannes-Krell-Str. 17;57518;Betzdorf", "Martin-Luther-Str. 4;57577;Hamm",
"Schulstr. 10;67577;Alsheim", "Schulstr.;55593;Rüdesheim", "Schulstr.;57580;Gebhardshain",
"Siegener Str. 26;57610;Altenkirchen", "Weinstr. 79;67169;Kallstadt"
), class = "factor"), sps = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
lon = c(7.10295, 7.6512462, 7.85126, 7.8234146, 7.6695674,
8.3355588, 8.1119607, 8.17405, 7.5906339, 7.8107492), lat = c(50.54219,
50.6897185, 50.79092, 50.7458834, 50.7620283, 49.7616261,
49.7408171, 49.49098, 49.7968555, 49.8468627), dist = list(
2088.90766536052, 918.489268082922, 589.738579014495,
3302.69115170858, 2005.31411895232, 3584.15570982643,
366.260782140767, 2694.12065272956, 5257.32234958339,
1700.27776226661), n = list(6L, 30L, 52L, 48L, 38L, 68L,
58L, 84L, 142L, 138L)), row.names = c(8L, 32L, 35L, 45L,
46L, 62L, 63L, 109L, 143L, 148L), class = "data.frame")
> dput(droplevels(no_special[1:10, ]))
structure(list(id = c(11725L, 11739L, 26883L, 11863L, 11996L,
12060L, 22062L, 12237L, 12630L, 26537L), geo = structure(c(8L,
4L, 7L, 2L, 5L, 10L, 9L, 1L, 6L, 3L), .Label = c("Ahrstr. 87;53505;Berg",
"Eichenbacher Weg 26;53533;Antweiler", "Greimerstalweg 19;56659;Burgbrohl",
"Kesslinger Str. 1;53506;Ahrbrück", "Koblenzer Str.;53498;Bad Breisig",
"Quellenstr. 15;56656;Brohl-Lützing", "Schulstr. 5;53505;Altenahr",
"Schulstr.;53518;Adenau", "Vehner Weg 31;53474;Bad Neuenahr-Ahrweiler",
"Weststr. 27;53474;Bad Neuenahr-Ahrweiler"), class = "factor"),
sps = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0), lon = c(6.9325459,
6.97516, 6.9875745, 6.825407, 7.3035599, 7.1322642, 7.1809,
6.93609, 7.32739, 7.27089), lat = c(50.382685, 50.48649,
50.5085722, 50.406783, 50.5055535, 50.5441126, 50.54013,
50.52239, 50.48599, 50.45707)), row.names = c(1L, 2L, 3L,
4L, 5L, 6L, 7L, 9L, 10L, 11L), class = "data.frame")
感谢您的帮助!
edit2:(预期输出)
head(special)
id geo sps lon lat dist n ID Radius-1500
8 23880 Blankartstr. 13;53474;Bad Neuenahr-Ahrweiler 1 7.102950 50.54219 2088.908 6
32 14176 Siegener Str. 26;57610;Altenkirchen 1 7.651246 50.68972 918.4893 30
35 26147 Johannes-Krell-Str. 17;57518;Betzdorf 1 7.851260 50.79092 589.7386 52
45 13408 Schulstr.;57580;Gebhardshain 1 7.823415 50.74588 3302.691 48
46 10435 Martin-Luther-Str. 4;57577;Hamm 1 7.669567 50.76203 2005.314 38
62 23954 Schulstr. 10;67577;Alsheim 1 8.335559 49.76163 3584.156 68
请检查以下代码,因为我仍然不能 100% 确定我理解您的问题。首先我需要加载一些包:
library(sf)
#> Linking to GEOS 3.8.0, GDAL 3.0.4, PROJ 6.3.1
library(nngeo)
library(tmap) # for the final map
和数据
special <- structure(
list(
id = c(
23880L, 14176L, 26147L, 13408L, 10435L, 23954L, 20647L, 26447L, 15617L, 23173L
),
geo = structure(
c(
2L, 9L, 4L, 8L, 5L, 6L, 3L, 10L, 1L, 7L
),
.Label = c(
"Beindestr.;55569;Monzingen", "Blankartstr. 13;53474;Bad Neuenahr-Ahrweiler",
"Donnersbergstr. 32;55232;Alzey", "Johannes-Krell-Str. 17;57518;Betzdorf",
"Martin-Luther-Str. 4;57577;Hamm", "Schulstr. 10;67577;Alsheim",
"Schulstr.;55593;Rudesheim", "Schulstr.;57580;Gebhardshain",
"Siegener Str. 26;57610;Altenkirchen", "Weinstr. 79;67169;Kallstadt"
),
class = "factor"
),
sps = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
lon = c(
7.10295, 7.6512462, 7.85126, 7.8234146, 7.6695674, 8.3355588, 8.1119607,
8.17405, 7.5906339, 7.8107492
),
lat = c(
50.54219, 50.6897185, 50.79092, 50.7458834, 50.7620283, 49.7616261,
49.7408171, 49.49098, 49.7968555, 49.8468627
),
dist = list(
2088.90766536052, 918.489268082922, 589.738579014495, 3302.69115170858,
2005.31411895232, 3584.15570982643, 366.260782140767, 2694.12065272956,
5257.32234958339, 1700.27776226661
),
n = list(6L, 30L, 52L, 48L, 38L, 68L, 58L, 84L, 142L, 138L)
),
row.names = c(8L, 32L, 35L, 45L, 46L, 62L, 63L, 109L, 143L, 148L),
class = "data.frame"
)
# input data for "no-special"
no_special <- structure(
list(
id = c(
11725L, 11739L, 26883L, 11863L, 11996L, 12060L, 22062L, 12237L, 12630L, 26537L
),
geo = structure(
c(8L, 4L, 7L, 2L, 5L, 10L, 9L, 1L, 6L, 3L),
.Label = c(
"Ahrstr. 87;53505;Berg", "Eichenbacher Weg 26;53533;Antweiler",
"Greimerstalweg 19;56659;Burgbrohl", "Kesslinger Str. 1;53506;Ahrbruck",
"Koblenzer Str.;53498;Bad Breisig", "Quellenstr. 15;56656;Brohl-Lutzing",
"Schulstr. 5;53505;Altenahr", "Schulstr.;53518;Adenau",
"Vehner Weg 31;53474;Bad Neuenahr-Ahrweiler", "Weststr. 27;53474;Bad Neuenahr Ahrweiler"
),
class = "factor"
),
sps = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
lon = c(
6.9325459, 6.97516, 6.9875745, 6.825407, 7.3035599, 7.1322642, 7.1809,
6.93609, 7.32739, 7.27089
),
lat = c(
50.382685, 50.48649, 50.5085722, 50.406783, 50.5055535, 50.5441126,
50.54013, 50.52239, 50.48599, 50.45707
)
),
row.names = c(1L, 2L, 3L, 4L, 5L, 6L, 7L, 9L, 10L, 11L),
class = "data.frame"
)
然后我需要将数据转换成sf
个对象:
sf_special <- st_as_sf(
special,
coords = c("lon", "lat"), # x, y (order matters)
crs = 4326
)
sf_no_special <- st_as_sf(
no_special,
coords = c("lon", "lat"), # x, y (order matters)
crs = 4326
)
找到所有特殊和所有非特殊之间的最近邻居
nearest <- st_nn(sf_special, sf_no_special, k = 1, returnDist = FALSE, progress = FALSE)
#> lon-lat points
检查结果
nearest
#> [[1]]
#> [1] 6
#>
#> [[2]]
#> [1] 5
#>
#> [[3]]
#> [1] 5
#>
#> [[4]]
#> [1] 5
#>
#> [[5]]
#> [1] 5
#>
#> [[6]]
#> [1] 9
#>
#> [[7]]
#> [1] 10
#>
#> [[8]]
#> [1] 10
#>
#> [[9]]
#> [1] 10
#>
#> [[10]]
#> [1] 10
该输出表示 sf_special
中的第一所学校与 sf_no_special
中的学校之间最近的邻居是 sf_no_special
中的第 6 所学校。同样的想法适用于所有其他指数。我们可以提取 sf_no_special
个 ID,如下所示:
sf_no_special[unlist(nearest), "id", drop = TRUE]
#> [1] 12060 11996 11996 11996 11996 12630 26537 26537 26537 26537
#> attr(,"class")
#> [1] "integer"
并将该信息附加到 sf_special
sf_special$ID <- sf_no_special[unlist(nearest), "id", drop = TRUE]
检查结果
sf_special
#> Simple feature collection with 10 features and 6 fields
#> geometry type: POINT
#> dimension: XY
#> bbox: xmin: 7.10295 ymin: 49.49098 xmax: 8.335559 ymax: 50.79092
#> geographic CRS: WGS 84
#> id geo sps dist n
#> 8 23880 Blankartstr. 13;53474;Bad Neuenahr-Ahrweiler 1 2088.908 6
#> 32 14176 Siegener Str. 26;57610;Altenkirchen 1 918.4893 30
#> 35 26147 Johannes-Krell-Str. 17;57518;Betzdorf 1 589.7386 52
#> 45 13408 Schulstr.;57580;Gebhardshain 1 3302.691 48
#> 46 10435 Martin-Luther-Str. 4;57577;Hamm 1 2005.314 38
#> 62 23954 Schulstr. 10;67577;Alsheim 1 3584.156 68
#> 63 20647 Donnersbergstr. 32;55232;Alzey 1 366.2608 58
#> 109 26447 Weinstr. 79;67169;Kallstadt 1 2694.121 84
#> 143 15617 Beindestr.;55569;Monzingen 1 5257.322 142
#> 148 23173 Schulstr.;55593;Rudesheim 1 1700.278 138
#> geometry ID
#> 8 POINT (7.10295 50.54219) 12060
#> 32 POINT (7.651246 50.68972) 11996
#> 35 POINT (7.85126 50.79092) 11996
#> 45 POINT (7.823415 50.74588) 11996
#> 46 POINT (7.669567 50.76203) 11996
#> 62 POINT (8.335559 49.76163) 12630
#> 63 POINT (8.111961 49.74082) 26537
#> 109 POINT (8.17405 49.49098) 26537
#> 143 POINT (7.590634 49.79686) 26537
#> 148 POINT (7.810749 49.84686) 26537
如果你想查看每所特殊学校15公里范围内有多少所非特殊学校,我们可以使用st_is_within_distance
no_special_within_radius <- st_is_within_distance(
x = sf_special,
y = sf_no_special,
dist = units::set_units(15, "km")
)
no_special_within_radius
#> Sparse geometry binary predicate list of length 10, where the predicate was `is_within_distance'
#> 1: 2, 3, 5, 6, 7, 8
#> 2: (empty)
#> 3: (empty)
#> 4: (empty)
#> 5: (empty)
#> 6: (empty)
#> 7: (empty)
#> 8: (empty)
#> 9: (empty)
#> 10: (empty)
输出表示sf_no_special
的学校2、3、5、6、7、8距离sf_special
的第一所学校在15km以内。其他学校离他们的邻居太远了。我们可以使用函数长度计算学校数量,并将该信息添加到 sf_special
:
sf_special$within_radius <- lengths(no_special_within_radius)
查看结果:
sf_special
#> Simple feature collection with 10 features and 7 fields
#> geometry type: POINT
#> dimension: XY
#> bbox: xmin: 7.10295 ymin: 49.49098 xmax: 8.335559 ymax: 50.79092
#> geographic CRS: WGS 84
#> id geo sps dist n
#> 8 23880 Blankartstr. 13;53474;Bad Neuenahr-Ahrweiler 1 2088.908 6
#> 32 14176 Siegener Str. 26;57610;Altenkirchen 1 918.4893 30
#> 35 26147 Johannes-Krell-Str. 17;57518;Betzdorf 1 589.7386 52
#> 45 13408 Schulstr.;57580;Gebhardshain 1 3302.691 48
#> 46 10435 Martin-Luther-Str. 4;57577;Hamm 1 2005.314 38
#> 62 23954 Schulstr. 10;67577;Alsheim 1 3584.156 68
#> 63 20647 Donnersbergstr. 32;55232;Alzey 1 366.2608 58
#> 109 26447 Weinstr. 79;67169;Kallstadt 1 2694.121 84
#> 143 15617 Beindestr.;55569;Monzingen 1 5257.322 142
#> 148 23173 Schulstr.;55593;Rudesheim 1 1700.278 138
#> geometry ID within_radius
#> 8 POINT (7.10295 50.54219) 12060 6
#> 32 POINT (7.651246 50.68972) 11996 0
#> 35 POINT (7.85126 50.79092) 11996 0
#> 45 POINT (7.823415 50.74588) 11996 0
#> 46 POINT (7.669567 50.76203) 11996 0
#> 62 POINT (8.335559 49.76163) 12630 0
#> 63 POINT (8.111961 49.74082) 26537 0
#> 109 POINT (8.17405 49.49098) 26537 0
#> 143 POINT (7.590634 49.79686) 26537 0
#> 148 POINT (7.810749 49.84686) 26537 0
我们还可以绘制学校并以图形方式检查结果:
tmap_mode("view")
#> tmap mode set to interactive viewing
tm_shape(sf_special) +
tm_dots() +
tm_shape(sf_no_special) +
tm_dots(col = "red")
由 reprex package (v0.3.0)
于 2020-06-29 创建