如何解决根据另一列中特定标记半径内纬度和经度列中的值省略行,并创建一个新的数据框
我有一个如下所示的excel工作表设置,并已作为df加载:
GPS_Lat GPS_Lon Location
50.70528 -120.44984 0
50.70528 -120.44984 0
50.70527 -120.44984 0
50.70527 -120.44984 0
50.70526 -120.44984 1
50.70526 -120.44984 1
50.70525 -120.44984 1
50.70525 -120.44984 0
50.70524 -120.44984 0
50.70524 -120.44984 0
50.70523 -120.44984 0
50.70523 -120.44984 0
50.70522 -120.44984 0
50.70522 -120.44984 0
50.70521 -120.44984 1
50.70521 -120.44984 1
50.7052 -120.44985 1
50.7052 -120.44985 1
50.70519 -120.44985 0
50.70519 -120.44986 0
50.70518 -120.44986 0
50.70518 -120.44986 0
50.70517 -120.44987 0
50.70517 -120.44987 0
我希望将值保留在向下定位列时遇到的第一个“ 1”以内1 m之内,并将这些值放入新的数据帧(名为df-n)中。如果还有其他具有1个值的部分,我想将其拆分为单独的数据帧(名称为:df-n + 1),同时也仅将这些点保持在第一个1m之内。我希望每个新数据帧都按顺序编号。我完全被这个困扰。
自动识别下面的点,并创建新的数据框,并在这些点的1 m以内(或任何其他定义的距离)的行中具有原始数据框名称和顺序后缀的行。因此,原始的“ df”第二个“ df-1”和“ df-2”
我最终将使用10 km的半径,并且我的数据集最多可包含2万行。
编辑:为输出提供清晰度。使用半径截止值为2 m的假设距离。
Row GPS_Lat GPS_Lon Location hypothetical_dist_1 hypothetical_dist_2
1 50.70528 -120.44984 0 4 14
2 50.70528 -120.44984 0 3 13
3 50.70527 -120.44984 0 2 12
4 50.70527 -120.44984 0 1 11
5 50.70526 -120.44984 1 0 10
6 50.70526 -120.44984 1 1 9
7 50.70525 -120.44984 1 2 8
8 50.70525 -120.44984 0 3 7
9 50.70524 -120.44984 0 4 6
10 50.70524 -120.44984 0 5 5
11 50.70523 -120.44984 0 6 4
12 50.70523 -120.44984 0 7 3
13 50.70522 -120.44984 0 8 2
14 50.70522 -120.44984 0 9 1
15 50.70521 -120.44984 1 10 0
16 50.70521 -120.44984 1 11 1
17 50.7052 -120.44985 1 12 2
18 50.7052 -120.44985 1 13 3
19 50.70519 -120.44985 0 14 4
20 50.70519 -120.44986 0 15 5
21 50.70518 -120.44986 0 16 6
22 50.70518 -120.44986 0 17 7
23 50.70517 -120.44987 0 18 8
24 50.70517 -120.44987 0 19 9
输出:
df-1
Row GPS_Lat GPS_Lon Location hypothetical_dist_1
3 50.70527 -120.44984 0 2
4 50.70527 -120.44984 0 1
5 50.70526 -120.44984 1 0
6 50.70526 -120.44984 1 1
7 50.70525 -120.44984 1 2
和
df-2
Row GPS_Lat GPS_Lon Location hypothetical_dist_2
13 50.70522 -120.44984 0 2
14 50.70522 -120.44984 0 1
15 50.70521 -120.44984 1 0
16 50.70521 -120.44984 1 1
17 50.7052 -120.44985 1 2
基本上,工作流程如下:将多个.csv文件批量加载到列表中,根据文件名命名列表项,使用所选的半径将每个列表项分开(分为filename-1,filename-2等)。 ),将其他列中的值相互绘制,然后导出所有图。
解决方法
在前面,如果计划以类似方式处理单个帧,通常建议将反对存储到单个帧中。 (有关“框架列表”的讨论,请参见https://stackoverflow.com/a/24376207/3358272。)
为演示使用/丢弃的行,我将在此处添加$row
。
此外,您还提到了与第一个“ 1”的距离,但对于前4行没有前置的“ 1”。由于我的其余处理都假定第一行是有意义的行,因此我将复制第一个“ 1”(在本例中为第5行)复制为第一行,以便随后的分组距离测量按预期方式进行。 / p>
在这里我将使用dplyr
进行分组。
library(dplyr)
if (dat$Location[1] != 1) {
prepended1 <- TRUE # in case we want to discard this copied row later
# bring the first "1" to the top
dat <- bind_rows(dat[which(dat$Location == 1)[1],drop = FALSE],dat)
dat$row[1] <- 0L
} else prepended1 <- FALSE
dat2 <- dat %>%
mutate(grp = cumsum(c(TRUE,diff(Location) > 0))) %>%
group_by(grp) %>%
mutate(dist = geosphere::distVincentyEllipsoid(cbind(GPS_Lon,GPS_Lat),cbind(cbind(GPS_Lon[1],GPS_Lat[1])))) %>%
ungroup()
dat2
# # A tibble: 25 x 6
# GPS_Lat GPS_Lon Location row grp dist
# <dbl> <dbl> <int> <int> <int> <dbl>
# 1 50.7 -120. 1 0 1 0
# 2 50.7 -120. 0 1 1 2.22
# 3 50.7 -120. 0 2 1 2.22
# 4 50.7 -120. 0 3 1 1.11
# 5 50.7 -120. 0 4 1 1.11
# 6 50.7 -120. 1 5 2 0
# 7 50.7 -120. 1 6 2 0
# 8 50.7 -120. 1 7 2 1.11
# 9 50.7 -120. 0 8 2 1.11
# 10 50.7 -120. 0 9 2 2.22
# # ... with 15 more rows
这提供了距“组中的第一个1”的距离(请注意grp
变量)。从这里开始,按dist
过滤并按grp
分割就很容易了。
根据后续流程的不同,最好使用dplyr::group_by
保持这种单帧格式,尽管改编看不见的代码是另一回事。
您的所有数据(第一行本身除外)都在1m以内,因此为了演示,我将使用“ 2m”。
dat2 %>%
filter(dist <= 2)
# # A tibble: 11 x 6
# GPS_Lat GPS_Lon Location row grp dist
# <dbl> <dbl> <int> <int> <int> <dbl>
# 1 50.7 -120. 1 0 1 0
# 2 50.7 -120. 0 3 1 1.11
# 3 50.7 -120. 0 4 1 1.11
# 4 50.7 -120. 1 5 2 0
# 5 50.7 -120. 1 6 2 0
# 6 50.7 -120. 1 7 2 1.11
# 7 50.7 -120. 0 8 2 1.11
# 8 50.7 -120. 1 15 3 0
# 9 50.7 -120. 1 16 3 0
# 10 50.7 -120. 1 17 3 1.32
# 11 50.7 -120. 1 18 3 1.32
同样,我将其保留为帧的list
,而不是分解成单个变量。
lst_of_frames <- dat2 %>%
filter(dist <= 2) %>%
split(.,.$grp)
lst_of_frames
# $`1`
# # A tibble: 3 x 6
# GPS_Lat GPS_Lon Location row grp dist
# <dbl> <dbl> <int> <int> <int> <dbl>
# 1 50.7 -120. 1 0 1 0
# 2 50.7 -120. 0 3 1 1.11
# 3 50.7 -120. 0 4 1 1.11
# $`2`
# # A tibble: 4 x 6
# GPS_Lat GPS_Lon Location row grp dist
# <dbl> <dbl> <int> <int> <int> <dbl>
# 1 50.7 -120. 1 5 2 0
# 2 50.7 -120. 1 6 2 0
# 3 50.7 -120. 1 7 2 1.11
# 4 50.7 -120. 0 8 2 1.11
# $`3`
# # A tibble: 4 x 6
# GPS_Lat GPS_Lon Location row grp dist
# <dbl> <dbl> <int> <int> <int> <dbl>
# 1 50.7 -120. 1 15 3 0
# 2 50.7 -120. 1 16 3 0
# 3 50.7 -120. 1 17 3 1.32
# 4 50.7 -120. 1 18 3 1.32
如果您需要对其进行细分,可以轻松手动进行分配(例如lst_of_frames[[2]]
)。
让我们尝试不同的逻辑:
比较 每个 点和 每个第一点-1
点 。在此数据中,有两个 first-1
点(第5行和第15行),因此我们将所有24行与这两个点进行比较。
compare_points <- filter(dat,Location == 1 & lag(Location) == 0)
compare_points
# GPS_Lat GPS_Lon Location row
# 1 50.70526 -120.4498 1 5
# 2 50.70521 -120.4498 1 15
一个比较:
lapply(seq_len(nrow(compare_points)),function(ind) {
dat %>%
mutate(dist = geosphere::distVincentyEllipsoid(compare_points[ind,2:1],cbind(GPS_Lon,GPS_Lat))) %>%
filter(dist <= 2)
})
# [[1]]
# GPS_Lat GPS_Lon Location row dist
# 1 50.70527 -120.4498 0 3 1.112426
# 2 50.70527 -120.4498 0 4 1.112426
# 3 50.70526 -120.4498 1 5 0.000000
# 4 50.70526 -120.4498 1 6 0.000000
# 5 50.70525 -120.4498 1 7 1.112426
# 6 50.70525 -120.4498 0 8 1.112426
# [[2]]
# GPS_Lat GPS_Lon Location row dist
# 1 50.70522 -120.4498 0 13 1.112426
# 2 50.70522 -120.4498 0 14 1.112426
# 3 50.70521 -120.4498 1 15 0.000000
# 4 50.70521 -120.4498 1 16 0.000000
# 5 50.70520 -120.4498 1 17 1.317768
# 6 50.70520 -120.4498 1 18 1.317768
,
您可以使用基数R的dist(...)函数获得所有点之间的距离。纬度分钟中的100m大约为0.009,因此您可以查看distance_matrix对象以确定哪些点相距
请注意,这使用的是欧氏距离,对于纬度/经度的短距离来说是可以的,但是如果将其用于几英里以上的长距离,则会遇到问题。
我为所有想尝试解决方案的人提供了reprex-随时将其添加到您的问题中。
latlong <- c(50.70528,50.70528,50.70527,50.70526,50.70525,50.70524,50.70523,50.70522,50.70521,50.7052,50.70519,50.70518,50.70517,-120.44984,-120.44985,-120.44986,-120.44987,1,0)
latlong <- matrix(latlong,nrow = 24)
distance_matrix <- as.matrix(dist(latlong[,c(1,2)],method = "euclidean"))
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。