按值对变量进行分组,彼此为 %

Group variables by values with % of each other

提问人:zimia 提问时间:4/23/2021 最后编辑:AnilGoyalzimia 更新时间:4/23/2021 访问量:141

问:

我想对具有特定列的 df 行进行分组,其值彼此为 x%。 例如,在下面的 df 中,值差异为 10% 将分为 3 组:(A、C、F)、(B、D)、(E)。 因此,某种分组的值变化为 +/- 10%。

tibble(Item = c("A","B","C","D","E","F"), value = c(1.01,2.42,1.03,2.45, 3.1, 0.99))

r data.table tidyverse 数据操作

评论

0赞 AnilGoyal 4/23/2021
如果 3 个这样的值是 1、1.09、1.18,百分比仅为 10% 怎么办
0赞 zimia 4/23/2021
在我使用它的情况下,这种情况是不可能的,所以没有必要担心这一点。
0赞 AnilGoyal 4/23/2021
还行。看答案。这将在以下情况下起作用:(i) 您想将它们组合在一起或 (ii) 不会发生此类情况。

答:

0赞 tlaus 4/23/2021 #1

作为一个快速而肮脏的解决方案,我建议:

library(tidyverse)

df <- tibble(Item = c("A","B","C","D","E","F"), value = c(1.01,2.42,1.03,2.45, 3.1, 0.99))

df %>%
  mutate(group = ceiling((value/max(value))/0.1))

您可以在其中改变除数。0.1

1赞 Danielle McCool 4/23/2021 #2

这样的事情会起作用。然后,“组”是 Item。

您可以看到,由于您指定的方式,将出现许多边缘情况。您可以删除参数 mult = “first” 来解析它们。

dt <- data.table(tibble(Item = c("A","B","C","D","E","F"), value = c(1.01,2.42,1.03,2.45, 3.1, 0.99)))
dt[, `:=`(lower_bound = value * .9,
          upper_bound = value * 1.1)]
dt[dt, on = .(value > lower_bound,
              value < upper_bound), mult = "first"][, .(i.Item), Item]

#    Item i.Item
# 1:    A      A
# 2:    A      C
# 3:    A      F
# 4:    B      B
# 5:    B      D
# 6:    E      E

1赞 AnilGoyal 4/23/2021 #3

由于您在评论中澄清了顺序元素不会相互冲突,因此您可以执行如下操作

library(dplyr)
df %>% arrange(value) %>% 
  group_by(grp = cumsum(lag(value, default = 0)*1.1 <= value)) %>%
  ungroup() %>%
  arrange(Item)

# A tibble: 6 x 3
  Item  value   grp
  <chr> <dbl> <int>
1 A      1.01     1
2 B      2.42     2
3 C      1.03     1
4 D      2.45     2
5 E      3.1      3
6 F      0.99     1

这也将产生预期的结果,如果value

df %>% arrange(value) %>% 
  group_by(grp = 1 + cumsum(lag(value, default = first(value))*1.1 <= value)) %>%
  ungroup() %>%
  arrange(Item)

# A tibble: 6 x 3
  Item  value   grp
  <chr> <dbl> <dbl>
1 A      1.01     1
2 B      2.42     2
3 C      1.03     1
4 D      2.45     2
5 E      3.1      3
6 F      0.99     1