所有可能的坐标对之间的最大距离

时间:2017-11-18 18:05:36

标签: r max grouping distance

我需要找到兰伯特坐标移动的个人ID的最大(绝对,未累计)距离。

我有以下数据集:

         rownum <- c(1,2,3,4,5,6,7,8)
         ID <- c(1,1,1,1,2,3,3,3)
         years <- c(1994, 1994, 1995, 1995, 1994, 1998, 1999, 1999)
         coorx <- c(160501,160507,160507,160508,160638,160402,160402,160707)
         coory <- c(202549,202727,202727,202488,202701,202586,202586,202548)
         test <- as.data.frame(cbind(rownum, ID, years, coorx, coory))

这些点位于Lamberts 72坐标中,因此已经处于欧氏距离。因此我知道我需要使用sqrt((x2-x1)^ 2 +(y2-y1)^ 2)来查找行对之间的距离。我坚持的是,我需要为每个单独的个体成对地比较所有行,以找到最大距离,同时进行此计算。即比较行1-2,1-3,1-4,2-3,2-4等,并从中提取最大值。我需要将此结果添加到新列(每个人的所有行的最大值一个)。

如果只有一个坐标(ID 2),则可以添加0或NA。

我能找到的所有答案只能在连续的行之间进行,或者整个矢量不按组分割(例如Operate on pairs of rows of a data frame)。

为此适应combn,outer或dist函数的任何方法?

这个问题的扩展也是通过获取给定年份的第一个坐标并将其与任何其他年份的第一个坐标的坐标进行比较,找到仅在年份之间的最大距离。然而,最重要的是第一个问题。

3 个答案:

答案 0 :(得分:0)

以下是dplyr如何做到这一点。基本上,我首先使用group_by ID,然后使用select删除rownum和years列。然后我在ID usinf full_join上将数据与自身合并。这会创建坐标对。它还会创建从第1年到第2年的坐标更改,反之亦然,但这不是问题,因为我们只保留max。然后,我使用mutate创建一个新的dist列,最后,我只使用max按ID保持summarise距离。

test <- as.data.frame(cbind(rownum, ID, years, coorx, coory))
test %>% 
  group_by(ID) %>% 
  select(ID,coorx, coory) %>% 
  full_join(.,.,by="ID") %>% 
  mutate(dist=sqrt((coorx.x-coorx.y)^2+(coory.x-coory.y)^2)) %>% 
  summarise(max_dist=max(dist,na.rm=TRUE))
# A tibble: 3 x 2
     ID max_dist
  <dbl>    <dbl>
1     1 239.0021
2     2   0.0000
3     3 307.3581

如果您只想使用每年的第一个位置进行练习,则必须将filterrow_number()==1一起使用。

test <- as.data.frame(cbind(rownum, ID, years, coorx, coory))
test %>% 
  group_by(ID,years) %>% 
  dplyr::filter(row_number()==1) %>% 
  group_by(ID) %>% 
  select(ID,coorx, coory) %>% 
  full_join(.,.,by="ID") %>% 
  mutate(dist=sqrt((coorx.x-coorx.y)^2+(coory.x-coory.y)^2)) %>% 
  summarise(max_dist=max(dist,na.rm=TRUE))

# A tibble: 3 x 2
     ID max_dist
  <dbl>    <dbl>
1     1 178.1011
2     2   0.0000
3     3   0.0000

最后,这里有data.table如何做同样的事情。我首先merge数据本身就是ID。然后我使用:=运算符创建一个新的dist列,最后,我只按ID保持max距离。

test <- as.data.table(cbind(ID, coorx, coory))
merged <- merge(test,test,by=c("ID"),allow.cartesian=TRUE)
merged[,dist:=sqrt((coorx.x-coorx.y)^2+(coory.x-coory.y)^2) ]
merged[,.(max_dist=max(dist,na.rm=TRUE)),by=ID]

   ID max_dist
1:  1 239.0021
2:  2   0.0000
3:  3 307.3581

答案 1 :(得分:0)

考虑一个自联接(SQL说话),其中public <T extends HttpRequestBase> CloseableHttpResponse sendRequestWithHeaders(Class<T> clazz, String url, Map<String, String> headers) throws IOException { CloseableHttpResponse response = null; try { HttpRequestBase request = clazz.getConstructor(String.class).newInstance(url); if (headers != null) { for (Map.Entry<String, String> header : headers.entrySet()) { request.setHeader(header.getKey(), header.getValue()); } } response = client.execute(request); } catch (Exception ex) { // handle exception } return response; } 数据帧自身为ID,所有可能组合的交叉连接(即笛卡尔积)。然后按ID计算每个公式的距离和merge的{​​{1}}:

aggregate

第一年,在原始数据框架上运行聚合以首先选择,即max,然后使用自联接运行与上面相同的过程:

merge_df <- merge(test, test, by="ID", suffixes=c("1", "2"))    
merge_df$dist <- with(merge_df, sqrt((coorx2-coorx1)^2+(coory2-coory1)^2))

max_dist <- aggregate(dist~ID, merge_df, FUN=max)
max_dist
#   ID     dist
# 1  1 239.0021
# 2  2   0.0000
# 3  3 307.3581

答案 2 :(得分:0)

使用data.table.SD

rownum <- c(1,2,3,4,5,6,7,8)
ID <- c(1,1,1,1,2,3,3,3)
years <- c(1994, 1994, 1995, 1995, 1994, 1998, 1999, 1999)
coorx <- c(160501,160507,160507,160508,160638,160402,160402,160707)
coory <- c(202549,202727,202727,202488,202701,202586,202586,202548)
test <- as.data.frame(cbind(rownum, ID, years, coorx, coory))

library(data.table)
setDT(test)

test[,
  max(
    dist(
      .SD[1:.N, .(coorx, coory)]
    )
  ),
  by = ID
]