将函数应用于data.frame中的特定对象,并将结果添加到

时间:2017-11-05 02:17:38

标签: r latitude-longitude xlsx

我有一张包含船只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文件?

2 个答案:

答案 0 :(得分:1)

如果您刚开始使用R,我建议您查看dplyr和tidyr软件包以进行数据操作。我将使用dplyr来帮助回答您的问题。我将使用一个更简单的例子来说明我认为你问题的核心:

如何根据data.frame中的两个连续数据行计算值?

我使用了以下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)

这是tidyversegeosphere驱动版本。如果您是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")