【问题标题】:Max distances between all possible pairs of coordinates by group组中所有可能的坐标对之间的最大距离
【发布时间】:2018-05-02 08:01:53
【问题描述】:

我需要找到从兰伯特坐标移动的单个 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) 来查找行对之间的距离。我坚持的是,我需要成对比较每个单独的个体的所有行,以找到最大距离,同时进行此计算。 IE。比较第 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 函数?

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

【问题讨论】:

    标签: r max grouping distance


    【解决方案1】:

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

    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 列,最后,我只保留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
    

    【讨论】:

      【解决方案2】:

      考虑一个 self-join(SQL 语言),其中您将 merge 数据框添加到自身上,以便按 ID 对所有可能的组合进行交叉连接(即笛卡尔积)。然后根据您的公式和aggregate 按 ID 计算 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
      

      在第一年,首先在原始数据帧上运行聚合以首先选择,即head(df)[1],然后使用自联接运行与上述相同的过程:

      year_df <- aggregate(.~ID + years, test, FUN=function(i) head(i)[1])
      
      merge_df <- merge(year_df, year_df, 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 178.1011
      # 2  2   0.0000
      # 3  3   0.0000
      

      【讨论】:

        【解决方案3】:

        使用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
        ]
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-10-31
          • 1970-01-01
          • 2023-03-08
          • 2021-01-08
          • 1970-01-01
          • 2021-10-11
          • 2021-04-05
          • 1970-01-01
          相关资源
          最近更新 更多