我有一张包含船只GPS数据的表格。 就像
ID POSTIME LON LAT SPEED AZIMUTH
1 2015-12-31 23:56:15 123.4003 32.39449 5.2 145
2 2015-12-31 23:56:53 123.3982 32.39487 5.2 138
3 2015-12-31 23:59:53 123.3884 32.39625 5.3 138
4 2016-01-01 00:01:19 123.3836 32.39702 5.2 146
5 2016-01-01 00:02:58 123.3788 32.39915 5.1 154
6 2016-01-01 00:06:41 123.3708 32.40391 5.1 157
我想计算每个采样点船舶的距离,时差和角度差。 我写了一个函数point.distance来计算不同点的lon和lat的距离,就像
一样point.distance <- function(lon1,lat1,lon2,lat2)
lon1 / 2和lat1 / 2代表不同的点
还有一个point.angle函数来计算角度差
point.angle <- function(lon1,lat1,lon2,lat2,lon3,lat3)
我知道如何在两个单独的点上使用函数,但是如何将函数应用于所有行并将结果添加到新列以进一步分析?
我希望我的结果可能像
ID POSTIME LON LAT SPEED AZIMUTH DISTANCE TD AD
1 2015-12-31 23:56:15 123.4003 32.39449 5.2 145 NA 00:00:38 -7
2 2015-12-31 23:56:53 123.3982 32.39487 5.2 138 201.873 00:03:00 0
3 2015-12-31 23:59:53 123.3884 32.39625 5.3 138 ... ... ...
4 2016-01-01 00:01:19 123.3836 32.39702 5.2 146 ... ... ...
是否有任何包或功能会这样? 或者我应该将结果保存在不同的向量中,然后最后写入xlsx文件?
答案 0 :(得分:1)
如果您刚开始使用R,我建议您查看dplyr和tidyr软件包以进行数据操作。我将使用dplyr来帮助回答您的问题。我将使用一个更简单的例子来说明我认为你问题的核心:
我使用了以下dplyr包中的两个函数:
mutate - 接受data.frame并通过添加列来转换它。注意我能够引用我在同一mutate命令中创建的新列。
lag - 此函数将向量作为参数,并返回向量的移位副本。例如,
lag(c(1, 2, 3))
# = NA, 1, 2
所以这是我的简单例子。我将在xy平面上制作一些坐标并计算连续点之间的欧几里德距离。我要在表格中添加列以将第i行的坐标带到第i + 1行,然后使用两组坐标计算距离。
#install.packages(dplyr)
library(dplyr)
d <- data.frame(x = c(-1, 2, 0, 0, 2), y = c(-3, -2, -1, 1, 3))
d
# x y
#1 -1 -3
#2 2 -2
#3 0 -1
#4 0 1
#5 -2 3
mydist <- function(x1, y1, x2, y2){
sqrt((x2 - x1)^2 + (y2 - y1)^2)
}
mutate(d, x0 = lag(x), y0 = lag(y), distance = mydist(x0, y0, x, y))
# x y x0 y0 distance
#1 -1 -3 NA NA NA
#2 2 -2 -1 -3 3.162278
#3 0 -1 2 -2 2.236068
#4 0 1 0 -1 2.000000
#5 -2 3 0 1 2.828427
答案 1 :(得分:0)
这是tidyverse
和geosphere
驱动版本。如果您是pandas
粉丝或熟悉SQL或只是R的新手,您可能会发现tidyverse
是一种非常舒适的语言。
对于距离计算,我使用了geosphere
中可用的最精确函数。如果您发现计算时间过长,请随时将复杂性降低到Haversine或更低:此处的选项详细说明:see Section 2 - Great Circle Distance (p.2)
我还将代码置于非常详细的状态。这样您就可以查看流程中的所有步骤。我只是想确保你和其他可能刚刚开始对数据纠缠的令人兴奋的运动感到兴奋的人能够获得这个答案。
使用的库:
library(tidyverse)
library(lubridate)
library(geosphere)
以上数据样本的OP视图的可复制数据集转换:
df_dat <-
read.table(text = " ID POSDATE POSTIME LON LAT SPEED AZIMUTH
1 2015-12-31 23:56:15 123.4003 32.39449 5.2 145
2 2015-12-31 23:56:53 123.3982 32.39487 5.2 138
3 2015-12-31 23:59:53 123.3884 32.39625 5.3 138
4 2016-01-01 00:01:19 123.3836 32.39702 5.2 146
5 2016-01-01 00:02:58 123.3788 32.39915 5.1 154
6 2016-01-01 00:06:41 123.3708 32.40391 5.1 157
", header = TRUE, stringsAsFactors = FALSE
)
df_dat
如下所示:
> df_dat ID POSDATE POSTIME LON LAT SPEED AZIMUTH 1 1 2015-12-31 23:56:15 123.4003 32.39449 5.2 145 2 2 2015-12-31 23:56:53 123.3982 32.39487 5.2 138 3 3 2015-12-31 23:59:53 123.3884 32.39625 5.3 138 4 4 2016-01-01 00:01:19 123.3836 32.39702 5.2 146 5 5 2016-01-01 00:02:58 123.3788 32.39915 5.1 154 6 6 2016-01-01 00:06:41 123.3708 32.40391 5.1 157
以下是将数据帧下移到所需形状的代码。我还在准备数据框中包含了一个名为TD_per
的列,您可能会发现它是一种有用的格式。
output <-
df_dat %>%
arrange(ID) %>%
mutate(DTM = ymd_hms(paste0(POSDATE, POSTIME)),
LON_prev = lag(LON),
LAT_prev = lag(LAT),
AZM_prev = lag(AZIMUTH),
DTM_prev = lag(DTM),
TD_sec = difftime(DTM, DTM_prev),
TD_per = as.period(TD_sec), # an alternative way to list the times
AD = AZIMUTH - AZM_prev) %>%
rowwise %>% # to keep geosphere on the straight and narrow
mutate(DISTANCE = distVincentyEllipsoid(c(LON_prev, LAT_prev), c(LON, LAT)),
TD = format(ymd(POSDATE, tz = "UTC") + TD_sec, "%H:%M:%S")
) %>%
select(ID, # getting dataframe all presentable
POSTIME = DTM,
LON,
LAT,
SPEED,
AZIMUTH,
DISTANCE,
TD,
AD)
output
output Source: local data frame [6 x 9] Groups: <by row> # A tibble: 6 x 9 ID POSTIME LON LAT SPEED AZIMUTH DISTANCE TD AD <int> <dttm> <dbl> <dbl> <dbl> <int> <dbl> <chr> <int> 1 1 2015-12-31 23:56:15 123.4003 32.39449 5.2 145 NA <NA> NA 2 2 2015-12-31 23:56:53 123.3982 32.39487 5.2 138 202.0246 00:00:38 -7 3 3 2015-12-31 23:59:53 123.3884 32.39625 5.3 138 934.6486 00:03:00 0 4 4 2016-01-01 00:01:19 123.3836 32.39702 5.2 146 459.6053 00:01:26 8 5 5 2016-01-01 00:02:58 123.3788 32.39915 5.1 154 509.6387 00:01:39 8 6 6 2016-01-01 00:06:41 123.3708 32.40391 5.1 157 919.2855 00:03:43 3
最后,您可以将输出数据框直接写入.csv.
write_excel_csv(output, "output.csv")