我有一个包含>200,000行和两列(Group和Value)的数据帧.GROUP包含字符串,VALUE包含正整数.所有行都是唯一的(即,对于给定组,每个值条目只出现一次).我想要group_by(Group),然后确定某一行的值相对于其他行值为≤5的实例数(请参见示例).

例如,如果一行的Group为"A",Value为"25",我们将搜索Group为"A"的所有行,以确定是否有任何行的Value在20到30之间.如果存在任何这样的行,则将值1添加到组"A"的计数,然后继续下一行.

我提供了一个只有7行的简化示例和一个使用purrr来正确计算实例数量的代码.然而,当应用于具有200,000行的数据帧时,它的运行速度非常慢.

有没有一种方法可以减少计算负担?

data <- data.frame(Group = c("A", "A", "A", "B", "B", "B", "B"),
                   Value = c(1, 2, 3, 9, 15, 17, 19))

count_pairs <- function(positions) {
  combn(positions, 2, function(x) abs(x[1] - x[2]) < 5) %>% sum
}

result <- data %>%
  group_by(Group) %>%
  summarise(Count = count_pairs(Value))
> print(result)
# A tibble: 2 × 2
  Group Count
  <chr> <int>
1 A         3
2 B         3

推荐答案

我们不是在计算每个Value中有多少个Value,我们希望看到if个其他值与"this"值匹配,然后计算每个组的出现次数.使用排序值减少了大量的数学运算,并使我们能够更快地确定事情.

原始数据:

library(dplyr)
data %>%
  arrange(Value) %>%
  group_by(Group) %>%
  summarize(
    Count = sum((Value - lag(Value)) < 5 | (lead(Value) - Value) < 5, na.rm = TRUE)
  )
# # A tibble: 2 × 2
#   Group Count
#   <chr> <int>
# 1 A         3
# 2 B         3

从ThomasIsCoding借来的更 Big Data :

set.seed(1701)
data <- tibble(
    Group = sample(LETTERS, size = 200000, replace = TRUE),
    Value = sample(1:100, size = 200000, replace = TRUE)
)
data
# # A tibble: 200,000 × 2
#    Group Value
#    <chr> <int>
#  1 H        91
#  2 O        27
#  3 W        70
#  4 G        33
#  5 D        42
#  6 F        70
#  7 X        66
#  8 X        37
#  9 X        68
# 10 D        45
# # ℹ 199,990 more rows
# # ℹ Use `print(n = ...)` to see more rows

重新运行dplyr方法:

data %>%
  arrange(Value) %>%
  group_by(Group) %>%
  summarize(Count = sum((Value - lag(Value)) < 5 | (lead(Value) - Value) < 5, na.rm = TRUE))
# # A tibble: 26 × 2
#    Group Count
#    <chr> <int>
#  1 A      7819
#  2 B      7541
#  3 C      7783
#  4 D      7574
#  5 E      7662
#  6 F      7850
#  7 G      7727
#  8 H      7710
#  9 I      7515
# 10 J      7707
# # ℹ 16 more rows
# # ℹ Use `print(n = ...)` to see more rows

我认为data.table英里可能会更快,

library(data.table)
setDT(data)
setorder(data, Group, Value) # just Value would be fine too
data[, sum(Value - lag(Value) < 5 | lead(Value) - Value < 5, na.rm = TRUE), by = "Group"]
#      Group    V1
#     <char> <int>
#  1:      A  7819
#  2:      B  7541
#  3:      C  7783
#  4:      D  7574
#  5:      E  7662
#  6:      F  7850
#  7:      G  7727
#  8:      H  7710
#  9:      I  7515
# 10:      J  7707
# ---             
# 17:      Q  7560
# 18:      R  7614
# 19:      S  7771
# 20:      T  7833
# 21:      U  7700
# 22:      V  7770
# 23:      W  7730
# 24:      X  7672
# 25:      Y  7648
# 26:      Z  7808

这两个都在1秒内运行,事实上,它们的相对性能很好,略高于data.table:

bench::mark(
dplyr = data %>%
    arrange(Value) %>%
    group_by(Group) %>%
    summarize(Count = sum((Value - lag(Value)) < 5 | (lead(Value) - Value) < 5, na.rm = TRUE)),
  data.table = data[, sum(Value - lag(Value) < 5 | lead(Value) - Value < 5, na.rm = TRUE), by = "Group"],
  check = FALSE, min_iterations = 100)
# # A tibble: 2 × 13
#   expression      min   median `itr/sec` mem_alloc `gc/sec` n_itr  n_gc total_time result memory time             gc                
#   <bch:expr> <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl> <int> <dbl>   <bch:tm> <list> <list> <list>           <list>            
# 1 dplyr        23.2ms   25.8ms      37.4        NA    0.763    98     2      2.62s <NULL> <NULL> <bench_tm [100]> <tibble [100 × 3]>
# 2 data.table   13.2ms     19ms      53.1        NA    0       100     0      1.88s <NULL> <NULL> <bench_tm [100]> <tibble [100 × 3]>

R相关问答推荐

根据固定值范围在tible中添加新行

如何使用按钮切换轨迹?

在某些栏和某些条件下,替换dfs列表中的NA

计算具有奇数日期的运行金额

从服务器在Shiny中一起渲染图标和文本

如何将SAS数据集的列名和列标签同时包含在r中GT表的表首?

基于R中的间隔扩展数据集行

在R函数中使用加号

基于数据集属性将科分配给物种

如何在R中使用hmm TMB提前一步预测观察到的状态?

使用R将简单的JSON解析为嵌套框架

我将工作代码重构为一个函数--现在我想不出如何传递轴列参数

将工作目录子文件夹中的文件批量重命名为顺序

有没有办法定制Plot(allEffects())面板标题?

整理ggmosaic图的标签

按镜像列值自定义行顺序

如何在R中创建这些列?

在直方图中显示两个变量

如何准确地指出Read_delim所面临的问题?

从多行中 Select 最小值