如何在 data.table 中分组后使用条件计算行数

2024-05-18

我有以下数据框:

dat <- read_csv(
  "s1,s2,v1,v2
   a,b,10,20
   a,b,22,NA
   a,b,13,33
   c,d,3,NA
   c,d,4.5,NA
   c,d,10,20"
)

dat
#> # A tibble: 6 x 4
#>      s1    s2    v1    v2
#>   <chr> <chr> <dbl> <int>
#> 1     a     b  10.0    20
#> 2     a     b  22.0    NA
#> 3     a     b  13.0    33
#> 4     c     d   3.0    NA
#> 5     c     d   4.5    NA
#> 6     c     d  10.0    20

我想做的是

  1. 过滤行基于v1 values
  2. 通过...分组s1 and s2
  3. 计算每组中的总行数
  4. 计算每个组中的行数,其中v2 is not NA.

例如与v1_filter >= 0我们得到这个:

s1 s2 total_line non_na_line
a  b     3          2
c  d     3          1

v1_filter >= 10我们得到这个:

s1 s2 total_line non_na_line
a  b     2          1
c  d     1          1

如何使用 data.table 或 dplyr 实现这一目标? 实际上,我们有大约 31M 行dat。所以我们需要 一种快速的方法。

我被这个困住了

 library(data.table)
 dat <- data.table(dat)

 v1_filter = 0
 dat[, v1 >= v1_filter, 
     by=list(s1,s2)]

Using sum应该有帮助。对逻辑向量进行操作,它对待每个TRUE as 1 and FALSE as 0,所以你可以轻松地做到这一点:

dat %>%
    group_by(s1, s2) %>%
    summarise(total_lines = n(),
              non_na_line = sum(!is.na(v2)))

# A tibble: 2 x 4
# Groups:   s1 [?]
     s1    s2 total_lines non_na_line
  <chr> <chr>       <int>       <int>
1     a     b           3           2
2     c     d           3           1

您可以轻松地在之间添加过滤器group_by and summarise,得到你想要的。请记住summarise将仅保留您分组依据的列。

基准

无论如何,我运行了一个快速基准测试,其中有一些与您的大小相似的测试数据。

s1charMix <- rep(letters[seq(from = 1, to = 10)], length.out = 30000000)
s2charMix <- rep(letters[seq(from = 11, to = 20)], length.out = 30000000)
s1chars <- sample(s1charMix, 30000000)
s2chars <- sample(s2charMix, 30000000)
v1Nums <- runif(30000000, min = 0, max = 20)
nomissing <- sample(1:200000,1)
int.mix <- rbinom(30000000 - nomissing, 30, 0.3)
nalist <- rep(NA, nomissing)
v2NumsNA <- sample(x = c(int.mix, nalist), 30000000)
df <- data_frame(s1 = s1chars, s2 = s2chars, v1 = v1Nums, v2 = v2NumsNA)

这应该大致复制您建议的数据的大小和类型:

df

# A tibble: 30,000,000 x 4
      s1    s2         v1    v2
   <chr> <chr>      <dbl> <int>
 1     d     s  9.2123603     7
 2     b     q 16.6638639    11
 3     g     o 18.3682028    11
 4     g     s  0.8779067     9
 5     a     s  0.0719127    10
 6     b     q 16.8809193    12
 7     h     q 15.4382455     6
 8     e     k  2.3565489    11
 9     h     p 16.4508811     9
10     d     n  2.7283823    11
# ... with 29,999,990 more rows

df %>%
    filter(is.na(v2))

# A tibble: 116,924 x 4
      s1    s2         v1    v2
   <chr> <chr>      <dbl> <int>
 1     d     r 13.1448988    NA
 2     b     o  0.2703848    NA
 3     b     t 18.8319385    NA
 4     a     s 11.6448437    NA
 5     j     m  0.5388760    NA
 6     i     k  8.7098427    NA
 7     d     s  6.1149735    NA
 8     h     p  2.5552694    NA
 9     g     r  0.9057442    NA
10     b     s 19.8886830    NA
# ... with 116,914 more rows

现在,让我们进行基准测试dplyr操作与data.table:

### dplyr
df %>%
    filter(v1 > 10) %>%
    group_by(s1, s2) %>%
    summarise(total_lines = n(),
              non_na_line = sum(!is.na(v2)))

# A tibble: 100 x 4
# Groups:   s1 [?]
      s1    s2 total_lines non_na_line
   <chr> <chr>       <int>       <int>
 1     a     k      150327      149734
 2     a     l      149655      149062
 3     a     m      149794      149200
 4     a     n      149771      149197
 5     a     o      149495      148942
...
> system.time(df %>% filter(v1 > 10) %>% group_by(s1, s2) %>% summarise(total_lines = n(), non_na_line = sum(!is.na(v2))))
   user  system elapsed 
  1.848   0.420   2.290
> system.time(for (i in 1:100) df %>% filter(v1 > 10) %>% group_by(s1, s2) %>% summarise(total_lines = n(), non_na_line = sum(!is.na(v2))))
   user  system elapsed 
187.657  55.878 245.528 

### Data.table
library(data.table)
dat <- data.table(df)
> dat[v1 > 10, .N, by = .(s1, s2)][dat[v1 > 10 & !is.na(v2), .N, by = .(s1, s2)] , on = c("s1", "s2") , nomatch = 0]
 s1 s2      N    i.N
  1:  b  q 149968 149348
  2:  g  o 150411 149831
  3:  h  q 150132 149563
  4:  h  p 150786 150224
  5:  e  o 149951 149353
 ...
> system.time(dat[v1 > 10, .N, by = .(s1, s2)][dat[v1 > 10 & !is.na(v2), .N, by = .(s1, s2)] , on = c("s1", "s2") , nomatch = 0])
   user  system elapsed 
  2.027   0.228   2.271
> system.time(for (i in 1:100) dat[v1 > 10, .N, by = .(s1, s2)][dat[v1 > 10 & !is.na(v2), .N, by = .(s1, s2)] , on = c("s1", "s2") , nomatch = 0])
   user  system elapsed 
213.281  43.949 261.664

TL;DR dplyr and data.table如果有的话,同样快dplyr稍微快一点

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 data.table 中分组后使用条件计算行数 的相关文章

  • 如何上下移动字符串并从中删除相似的字符串?

    我问了一个可能不太清楚的问题 所以我尝试用一 种可以理解的方式来解释它 这是我的数据 我的数据看起来像这样 看起来像这样 V1 V2 V3 1 Q9UNZ5 Q9Y2W1 2 Q9ULV4 Q6QEF8 3 Q9UNZ5 4 Q9H6F5
  • dplyr:带引号变量名的 mutate 的标准评估

    我将如何使用mutate 我的假设是我正在寻找标准评价就我而言 因此mutate 但我对此并不完全有信心 当使用接受变量名列表的函数时 如下所示 createSum function data variableNames data gt m
  • R 带有列和行的分面 qqplots

    我需要使用按行和列的构面创建 qqplot 我了解如何用列和行绘制分面图 但我不确定如何设置我的数据 最终 我想按列和行对数据集进行分组 然后按升序对 建模 结果和 观察到 结果进行排序 同时添加带有 行 组的列和带有 列 组的列 我一直在
  • 在 R 中安全地计算算术表达式?

    Edit 好吧 由于似乎有很多混乱 我将稍微简化一下问题 您可以尝试回答下面的原始问题 或者您可以解决此版本并忽略该行下面的所有内容 我的目标是采用任意表达式并在极其受限的环境中对其进行评估 该环境将仅包含具有以下类型值的变量 数值向量 接
  • 如何使用 ggplot2 对曲线下的区域进行着色

    我一直在尝试使用 ggplot2 生成类似于此 R 图形的绘图 xv lt seq 0 4 0 01 yv lt dnorm xv 2 0 5 plot xv yv type l polygon c xv xv lt 1 5 1 5 c y
  • data.table 的包装函数

    我有一个已经使用 data frame 上下文编写的项目 为了缩短计算时间 我尝试利用 data table 的速度 我的方法是构造包装函数 读取帧 将它们转换为表 进行计算 然后转换回帧 这是一个简单的例子 FastAgg lt func
  • 更新两组单选按钮 - 闪亮

    我问了这个问题 反应式更新两组单选按钮 闪亮 https stackoverflow com questions 35040579 update two sets of radiobuttons reactively shiny 昨天 但也
  • 如何在R中将英尺转换为厘米?

    我得到了一个高度的字符向量 如下所示 859 5 10 5 8 5 11 6 0 5 10 6 2 5 11 6 2 6 2 5 7 5 9 5 7 6 1 6 0 5 11 6 0 6 5 6 1 6 1 5 10 5 11 5 11 6
  • 使用faceting()时如何连接geom_point()和geom_line?

    我有一个问题 但我在互联网上没有找到任何相关信息 我很高兴得到一些提示 我有一个数据集 其中 x 轴是离散的 但我想将这些点相互连接 我可以做到 我的问题是当我添加分面选项时 我无法再将这些点相互链接起来 我找到了一个替代方案 但看起来不太
  • 如何通过组度量的平均值在 df 内排列 dplyr:: 组?

    借鉴吴卡拉的设计https stackoverflow com a 26555424 9350837 https stackoverflow com a 26555424 9350837答案 我希望根据各个组汇总测量的平均值对分组 df 进
  • 使用 R 下载压缩数据文件、提取并导入 .csv

    我正在尝试使用以下方法从网页下载并提取 csv 文件R 这个问题是重复的使用 R 下载压缩数据文件 提取和导入数据 https stackoverflow com questions 3053833 using r to download
  • 如何不显示 ggplot 轴上的所有标签?

    I m trying to using ggplot2 to plot this But as you can see on the x axis you can t read anything 那么如何在 x 轴上显示每 10 年的值呢
  • 如何创建 highcharter 事件函数以在 Shiny R 中创建“下拉函数”

    我正在建造一个shiny应用程序 我想要完成的事情之一是创建一个下拉菜单 我想将劳动力变量绘制为不同级别的年份变量的函数 请参阅下面的示例数据框 year level 2 level 3 labour 1 2013 10 101 1 2 2
  • R 无法回忆起内存中的对象

    我正在构建一个包含多个步骤的函数 其中每个步骤都会创建一个对象 某个步骤失败 temp3 并且无法找到前面的步骤对象 错误 未找到对象 temp2 我不知道为什么 我有类似的函数 遵循完全相同的结构 每个步骤都遵循先前创建的对象 在函数内
  • 基本 dyplr 函数给出错误:“check_dots_used”

    试图找出为什么我会收到此错误 以前从未见过 谷歌没有帮助 check dots used action warn 中的错误 未使用参数 action warn 我在下面的非常基本的试验中收到错误 而且在 group by count 中也收
  • 使用矢量相应地更改传单线条的颜色

    无论如何 是否可以根据某些变量的值更改传单线条的颜色 我用谷歌搜索 发现了这个link http hgoebl github io Leaflet MultiOptionsPolyline demo 然而 我想知道是否有一种简单的方法可以在
  • ggplot2 中的中心图标题

    这个简单的代码 以及今天早上我的所有脚本 已经开始在 ggplot2 中给我一个偏离中心的标题 Ubuntu version 16 04 R studio version Version 0 99 896 R version 3 3 2 G
  • SparkR 和 Sparklyr 之间导入 parquet 文件所需的时间差异

    我正在使用 databricks 导入镶木地板文件SparkR and sparklyr data1 SparkR read df dbfs data202007 source parquet header TRUE inferSchema
  • ggplot:类似于scale_color_steps()的有序因子的色标

    With scale color steps 我们可以通过设置low和high争论 一个例子 df lt data frame x rnorm 99 y rnorm 99 col rnorm 99 ggplot df aes x y col
  • 在 R 中读入原始二进制数据并将其转换为整数

    我有一个二进制文件 其中包含编码为不同长度 主要是 2 4 字节 的有符号或无符号整数的数值 为了处理这些数据 我将文件的所需部分读取为raw向量与readBin 然后尝试将其转换为十进制 问题是 R的内置函数有限制 我不太明白 比如没有l

随机推荐