【问题标题】:Computing minimum distance between observations within groups计算组内观测值之间的最小距离
【发布时间】:2020-10-30 16:11:30
【问题描述】:

在下面的数据集中,我如何创建一个新列 min.diff ,该列报告给定观察 xx 与其组内任何其他观察 y 之间的最小距离(由group 专栏)?我想用abs(x-y)来测量xy之间的距离。

    set.seed(1)

df <- data.frame(
  group = c('A', 'A', 'A', 'B', 'B', 'C', 'C', 'C'),
  value = sample(1:10, 8, replace = T)
)

预期输出:

  group value min.diff
1     A     9   2
2     A     4   3
3     A     7   2
4     B     1   1
5     B     2   1
6     C     7   4
7     C     2   1
8     C     3   1

我更喜欢使用dplyr 的解决方案。 我想到的唯一方法是通过添加更多行来扩展数据框,以获取组内的每个可能对,计算距离,然后过滤掉每个组中的最小值。有没有更紧凑的方式?

【问题讨论】:

  • 您能否展示共享示例的预期输出?
  • @RonakShah 请检查编辑

标签: r dplyr


【解决方案1】:

我们可以使用combn对'value'做两两差,得到absolute值的min

library(dplyr)
df1 <- df %>% 
          mutate(new = min(abs(combn(value, 2, FUN = function(x) x[1] - x[2]))))

如果我们想在给定元素之间获取minimum,即其余元素中的first

 df1 <- df %>%
            mutate(new = min(abs(value[-1] - first(value))))

【讨论】:

  • 谢谢,但我认为这并不能完全满足我的要求——这将采用每组内任意两个观察值之间的最小距离——因此new 在组内是恒定的。另一方面,我想要 GIVEN 元素与其组内任何其他元素之间的最小距离
  • @ArthurCarvalhoBrito 也许更新对你有用
  • 它仍然不起作用 - 如果您检查我更新的数据集,结果仍然是错误的。例如,在最后一行,我们应该有 value = 1,因为在 C 组中,我们有 |3-2| = 1
【解决方案2】:

我们可以使用map_dbl 将当前值与所有其他值相减,并从中为每个group 选择最小值。

library(dplyr)
library(purrr)

df %>%
  group_by(group) %>%
  mutate(min.diff = map_dbl(row_number(), ~min(abs(value[-.x] - value[.x]))))
       

#  group value min.diff
#  <chr> <int>    <dbl>
#1 A         9        2
#2 A         4        3
#3 A         7        2
#4 B         1        1
#5 B         2        1
#6 C         7        4
#7 C         2        1
#8 C         3        1

【讨论】:

    【解决方案3】:

    如果顺序无关紧要……

    library(dplyr)
    
    df %>% 
      arrange(group, value) %>% #Order ascending by value, within each group
      group_by(group) %>% 
      mutate(min.diff = case_when(lag(group) == group & lead(group) == group ~ min(c(abs(value - lag(value)), abs(value - lead(value))), na.rm = T), #If the "group" for the previous and next entry are the same as the current group, take the smallest of the two differences
                                  lag(group) == group ~ abs(value - lag(value)), #Otherwise, if only the previous entry's group is the same as the current one, take the difference from the previous
                                  lead(group) == group ~ abs(value - lead(value)) #Otherwise, if only the next entry's group is the same as the current one, take the difference from the next
                                  )
             ) %>%
      ungroup()
    
      #    group value min.diff
      #    <chr> <int>    <int>
      #  1 A         4        3
      #  2 A         7        2
      #  3 A         9        2
      #  4 B         1        1
      #  5 B         2        1
      #  6 C         2        1
      #  7 C         3        1
      #  8 C         7        4
    

    如果顺序很重要,您可以添加索引并在之后重新排列,如下所示:

    library(dplyr)
    
    df %>% 
      group_by(group) %>%
      mutate(index = row_number()) %>% #create the index
      arrange(group, value) %>%
      mutate(min.diff = case_when(lag(group) == group & lead(group) == group ~ min(c(abs(value - lag(value)), abs(value - lead(value))), na.rm = T),
                                  lag(group) == group ~ abs(value - lag(value)),
                                  lead(group) == group ~ abs(value - lead(value))
                                  )
             ) %>%
      ungroup() %>%
      arrange(group, index) %>% #rearrange by the index
      select(-index) #remove the index
    
    
    #   group value min.diff
    #   <chr> <int>    <int>
    # 1 A         9        2
    # 2 A         4        3
    # 3 A         7        2
    # 4 B         1        1
    # 5 B         2        1
    # 6 C         7        4
    # 7 C         2        1
    # 8 C         3        1
    

    【讨论】:

      猜你喜欢
      • 2014-01-28
      • 1970-01-01
      • 1970-01-01
      • 2019-02-26
      • 2018-05-21
      • 2014-02-13
      • 2013-10-08
      • 1970-01-01
      相关资源
      最近更新 更多