代码之家  ›  专栏  ›  技术社区  ›  Lisarv

按组列出的所有可能坐标对之间的最大距离

  •  1
  • Lisarv  · 技术社区  · 7 年前

    我需要找到单个ID移动到Lambert坐标的最大距离(绝对距离,而不是累积距离)。

    我有以下数据集:

             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)来查找行对之间的距离。我一直坚持的是,我需要对每个单独的个体的所有行进行两两比较,以找到最大距离,同时进行此计算。一、 e.比较第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 回复  |  直到 7 年前
        1
  •  0
  •   Pierre Lapointe    7 年前

    以下是如何使用 dplyr . 基本上,我先 group_by ID,然后使用删除rownum和years列 select . 然后在ID usinf上将数据与自身合并 full_join . 这将创建坐标对。它还创建了从第1年到第2年的坐标变化,反之亦然,但这不是问题,因为我们只保留 max . 然后,我使用 mutate 最后,我只保留 最大值 使用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
    

    如果你只想使用每年的第一个位置进行锻炼,你必须使用 filter 具有 row_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上。然后我使用 := 最后,我只保留 最大值

    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
  •  0
  •   Parfait    7 年前

    考虑一个 自连接 (SQL speak)你在哪里 merge 通过ID将所有可能的组合进行交叉连接(即笛卡尔积),然后根据公式计算距离 aggregate 对于 max 按ID:

    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
  •  0
  •   Jake    4 年前

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