不使用apply函数对data.table的每一行进行操作的方法

2024-05-08

我在下面写了一个简单的函数:

mcs <- function(v) { ifelse(sum((diff(sort(v)) > 6) > 0), NA, sd(v)) }

它应该采用一个向量,对其进行排序,然后检查每个连续差异中是否存在大于 6 的差异。如果差值大于 6,则返回 NA;如果差值不大于 6,则返回标准差。

我想将此函数应用于数据表的所有行(仅选择某些列),然后将每行的返回值作为新的列条目附加到数据表中。

例如,给定一个像这样的数据表

> dat <- data.table(A=c(1,2,3,4,5), B=c(2,3,4,10,6), C=c(3,4,10,6,8),   
D=c(3,3,3,3,3))  
> dat  
   A  B  C D  
1: 1  2  3 3  
2: 2  3  4 3  
3: 3  4 10 3  
4: 4 10  6 3  
5: 5  6  8 3  

我想生成下面的输出。 (我在每行的第 2、3 和 4 列上应用了函数。)

> dat
   A  B  C D        sd
1: 1  2  3 3 0.5773503
2: 2  3  4 3 0.5773503
3: 3  4 10 3 3.7859389
4: 4 10  6 3 3.5118846
5: 5  6  8 3 2.5166115

我了解到可以使用以下方法对数据表进行按行操作:

> dat[, sd:=apply(.SD, 1, mcs), .SDcols=(c(2,3,4))]

而且这个方法确实有效,只是速度太慢了。我必须对几个大型数据表执行此操作,并且我编写了一个脚本来执行此操作。但是,它仅适用于较小的数据表。对于大约 300,000 行的表,它会在几秒钟内完成,但是当我尝试对大约 8 亿行的表执行此操作时,我的程序无法完成。我尝试等待两个小时,我认为 R 坏了或者其他什么原因,因为控制台死机了。我已经尝试运行该脚本多次,它总是正确完成前几个较小的表(我让程序将表写入文件进行检查),但是当它到达大型数据表时,它永远不会完成。我在计算集群上运行它,所以我绝对不认为这是硬件限制。可能是糟糕的代码。

我假设瓶颈是在 apply 中完成的循环,但我不知道如何使其更快。我对 R 还很陌生,所以我不知道如何优化我的代码。我在互联网上看到了很多关于矢量化的帖子,我在想如果我可以同时将我的函数应用到每一行,它会快得多,但我不知道该怎么做。请帮忙。

Edit
抱歉,我在复制时犯了一个错误mcs功能。我已经更新了。

Edit 2
对于那些感兴趣的人,我最终将桌子分成两半,并分别对每一半进行操作,这对我有用。


如果您确实需要速度,一如既往,最好使用 Rcpp 迁移到 C++,这为我们提供了速度快 100 倍以上的解决方案。

Data

我确实制作了一些不同的示例数据来测试它,其中有 1000 行而不是 5 行:

set.seed(123)
dat <- data.table(A = rnorm(1e3, sd=4), B = rnorm(1e3, sd=4), C = rnorm(1e3, sd=4),
                  D = rnorm(1e3, sd=4), E = rnorm(1e3, sd=4))

Solution

我使用以下 C++ 代码执行与您的函数相同的操作,但现在循环是在 C++ 中完成的,而不是通过 apply 在 R 中完成,这节省了大量时间:

#include <Rcpp.h>

using namespace Rcpp;

// [[Rcpp::export]]
NumericVector mcs2(DataFrame x) {
    int n = x.nrows();
    int m = x.size();
    NumericMatrix mat(n, m);
    for ( int j = 0; j < m; ++j ) {
        mat(_, j) = NumericVector(x[j]);
    }
    NumericVector result(n);
    for ( int i = 0; i < n; ++i ) {
        NumericVector tmp = mat(i, _);
        std::sort(tmp.begin(), tmp.end());
        bool do_sd = true;
        for ( int j = 1; j < m; ++j ) {
            if ( tmp[j] - tmp[j-1] > 6.0 ) {
                result[i] = NA_REAL;
                do_sd = false;
                break;
            }
        }
        if ( do_sd ) {
            result[i] = sd(tmp);
        }
        do_sd = true;
    }
    return result;
}

我们可以确保它返回相同的值:

all.equal(apply(dat[, 2:4], 1, mcs1), mcs2(dat[,2:4]))

[1] TRUE

现在让我们进行基准测试:

benchmark(mcs1 = dat[, sd:=apply(.SD, 1, mcs1), .SDcols=(c(2,3,4))],
          mcs2 = dat[, sd:=mcs2(.SD), .SDcols=(c(2,3,4))],
          order = 'relative',
          columns = c('test', 'elapsed', 'relative', 'user.self'))


  test elapsed relative user.self
2 mcs2    0.19    1.000     0.183
1 mcs1   21.34  112.316    20.044

如何编译这段代码

作为通过 Rcpp 使用 C++ 代码的介绍,我建议本章 http://adv-r.had.co.nz/Rcpp.html#rcpp-introHadley Wickham 的《Advanced R》。如果您打算使用 Rcpp 做进一步的事情,我强烈建议您还阅读官方文档和小插图,但 Wickham 的书可能更适合初学者作为起点。出于您的目的,您只需启动并运行 Rcpp,以便可以编译上面的代码。

为了使此代码适合您,您需要 Rcpp 包(如果您还没有)。您可以通过运行来获取该包

install.packages(Rcpp)

来自 R。请注意,您还需要一个编译器;如果您使用的是基于 Debian 的 Linux 系统(例如 Ubuntu),您可以运行

sudo apt install r-base-dev

从航站楼。如果您使用的是 Mac 或 Windows,请检查here https://support.rstudio.com/hc/en-us/articles/200486498有关进行此设置的一些说明,或在上面链接的 Wickham 章节中。

安装 Rcpp 后,将上面的 C++ 代码保存到文件中。假设我们的示例中的文件名为“SOanswer.cpp”。然后你就可以制作它mcs2()通过将以下两行放入 R 脚本中,可以从 R 获得该函数:

library(Rcpp)
sourceCpp("SOanswer.cpp") # assuming the file is in your working directory

就是这样!现在您的 R 脚本可以调用mcs2()并且跑得更快。如果您想了解有关 Rcpp 的更多信息,除了上面的 Wickham 章节之外,我还可以查看参考手册和可用的小插图here https://cran.r-project.org/web/packages/Rcpp/index.html, 这一页 https://support.rstudio.com/hc/en-us/articles/200486088-Using-Rcpp-with-RStudio来自 RStudio(它也有大量链接,其中一些链接到此处),您还可以在周围找到一些真正有用的东西RCPP画廊 http://gallery.rcpp.org/.

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

不使用apply函数对data.table的每一行进行操作的方法 的相关文章

  • 获取函数的命名空间

    我正在开发一个包 我希望在其中向对象添加编辑历史记录 该包允许其他包注册用于编辑对象的函数 我正在寻找一种方法来记录注册用于编辑的函数的包的版本 问题是 给定一个函数 如何从导出的位置获取包 我的想法是调查它的搜索路径 但是search 仅
  • 从 n,k 维矩阵数组中减去 n,k 维矩阵

    如果我有一个数组A A lt array 0 c 4 3 5 for i in 1 5 set seed i A i lt matrix rnorm 12 4 3 如果我有矩阵 B set seed 6 B lt matrix rnorm
  • 如何在 R 中合并同名列表中的数据框?

    我有一个包含很多数据框的列表 如果它们具有相同的名称 我想合并它们 即合并所有具有相同名称 a 和 b 的数据框 像这样 a lt aaaaa b lt bbbbb c lt ccccc g lt list df1 lt data fram
  • 如何对数字进行四舍五入并使其显示零?

    R 中将数字四舍五入到小数点后 2 位的常用代码是 gt a 14 1234 gt round a digits 2 gt a gt 14 12 但是 如果该数字的前两位小数位为零 则 R 会在显示中抑制零 gt a 14 0034 gt
  • R 可以创建带有可单击条形图的条形图图像以插入网页吗?

    我知道如何创建条形图 以及如何将其粘贴在网页上 例如 使用hwriteImage in the 作家包 http www embl de gpau hwriter 我想要的是每个栏都是一个在鼠标悬停时突出显示的区域 并且每个栏在单击时都有不
  • R 闪亮仪表板中的动态重复条件面板

    我正在尝试创建一个动态条件面板 所以我的条件如下 在用户界面中输入 selectInput inpt Input Number seq 1 50 1 selectize FALSE 我的条件面板 UI 输入是 conditionalPane
  • 警告消息 - 来自 dummies 包的 dummy

    我正在使用 dummies 包为分类变量生成虚拟变量 其中一些变量具有两个以上类别 testdf lt data frame A as factor c 1 2 2 3 3 1 B c A B A B C C C c D D E D D E
  • 绘制 Cox 回归的 Kaplan-Meier 图

    我使用 R 中的以下代码设置了一个 Cox 比例风险模型来预测死亡率 添加协变量 A B 和 C 只是为了避免混淆 即年龄 性别 种族 但我们真正对预测变量 X 感兴趣 X 是一个连续变量 cox model lt coxph Surv t
  • 如何按用户定义(例如非字母顺序)对数据框进行排序[重复]

    这个问题在这里已经有答案了 给定一个数据框dna gt dna chrom start chr2 39482 chr1 203918 chr1 198282 chrX 7839028 chr17 3874 以下代码重新排序dna by ch
  • 如何纠正 data.frame 上的字符编码

    我有一个像这样的数据框 data names lt data frame DATA c 1 5 rownames data names lt c IV xc1N JOS xc9 LUC xcdA RAM xd3N TO xd1O data
  • 多个动态滤镜更新闪亮

    我希望能够让 UI 输入闪亮 并根据用户之前的选择进行自我更新 因此 在下面的示例中 预期的行为是用户选择cyl vsor carb那么这将 过滤数据集mtcars用于创建绘图 即用户根据过滤条件调整绘图并 更新其他过滤器中的剩余输入选择
  • 为什么 sapply 的缩放速度比样本大小的 for 循环慢?

    假设我想采用向量 X 2 1 N 并将 e 计算为每个元 素的指数 是的 我认识到最好的方法就是通过向量化 exp X 但这样做的目的是将 for 循环与 sapply 进行比较 我通过逐步尝试三种方法 一种使用 for 循环 两种以不同方
  • `dplyr::_join` 函数的命名向量“by”参数[重复]

    这个问题在这里已经有答案了 我正在写一个函数dplyr join两个数据框by不同的列 第一个数据帧的列名称动态指定为函数参数 我相信我需要使用rlang准引用 元编程 但未能找到可行的解决方案 我很感激任何建议 library dplyr
  • `as.matrix` 和 `as.data.frame` S3 方法与 S4 方法

    我注意到定义as matrix or as data frame作为 S4 类的 S3 方法 使例如lm formula objS4 and prcomp object 开箱即用 如果它们被定义为 S4 方法 则这不起作用 为什么将方法定义
  • 行对名称中具有特定模式的列求和

    我有一个像这样的数据表 DT lt ata table data table ref rep 3L 4L nb 12 15 i1 c 3 1e 05 0 044495 0 82244 0 322291 i2 c 0 000183 0 155
  • R Shiny:如何将无功值从闪亮模块返回到主服务器功能?

    我有一个简单的玩具示例 它使用 add removeBtn 模块在 第一个 模块中添加和删除 UI 我需要跟踪单击 添加 删除 的次数 如果我不使用模块 这很容易 但我试图在嵌套模块的上下文中执行此操作 代码如下 但基本上 我似乎无法访问主
  • 更新 R6 对象实例中的方法定义

    如何更新 R6 类实例的方法定义 正如我所期望的 S3 使用当前的方法定义 对于 R5 参考类 我可以使用 myInstance myInstance copy 在 R6 中 我尝试了 myInstance myInstance clone
  • 在ggplot中设置y轴中断

    我在代码中设置中断时遇到困难 我尝试添加breaks seq 0 100 by 20 但似乎无法让它正常工作 本质上我希望 Y 轴从 0 到 100 每 20 个刻度一次 YearlyCI lt read table header T te
  • 为什么这个 R ggplot2 代码会显示一个空白的显示设备?

    虽然 SO 通常不用于帮助解决错误 但这个显示了特别简单且特别烦人的行为 如果你是一个ggplot2用户 您可以在 10 秒或更短的时间内重现它 正如这个 GitHub 问题 ggplot gtable 创建空白显示 https githu
  • 要在子集中显示的非数字条目的维恩图

    我有以下数据框 SET1 SET2 SET3 par1 par2 par1 par2 par3 par2 par3 par4 par5 我想制作一个维恩图 其中所有这些 parX 元素都显示在各自的子集中 即作为标签 而不仅仅是重叠元素的数

随机推荐

  • 计算分组序列中两个值之间的差异

    这是这篇文章的后续问题 循环遍历 R 中的数据帧并测量两个值之间的时间差 https stackoverflow com questions 44885856 loop through dataframe in r and measure
  • 为什么每次合并分支后我的 git log graph 都会多增长一行?

    我习惯使用git log oneline graph decorate all作为别名git ll在终端中查看提交图表 但是当我每次合并我的时 一个问题让我感到困惑develop to master 上面命令的输出可能是这样的 0d1bf7
  • WritePrivateProfileString 未在末尾添加属性

    我正在使用以下命令在 ini 文件中写入一些属性WritePrivateProfileString函数并且一切正常 但是当我添加多行文本时 出现了问题 这是代码和输出 WritePrivateProfileString T General
  • 通过 JavaScript 获取页面/iframe 的编码

    我想通过 JavaScript 或浏览器中的其他一些 API 以编程方式确定页面的编码 我想要这些信息的原因是因为我试图对主要浏览器支持的字符编码进行模糊测试 显然仅仅因为我发送了适当的 内容类型 并不意味着浏览器会使用编码做正确的事情 欢
  • 如何通过MFC将应用程序设置保存到注册表中?

    我有一个由 MFC 项目向导创建的 MFC 应用程序 我想在注册表中保存 读取应用程序设置 所以问了这个question https stackoverflow com questions 1880275 good c registry w
  • 更改 WinForms 按钮突出显示颜色

    I found 这一页 https stackoverflow com questions 9260303 how to change menu hover color winforms 其中概述了如何更改 MenuStrip 及其项目的呈
  • 岛屿和缺口问题

    背景故事 我有一个数据库 其中包含卡车司机的数据点 其中还包含 在卡车上时 驾驶员可以拥有 驾驶员身份 我想做的是按司机 卡车对这些状态进行分组 截至目前 我已尝试使用 LAG LEAD 来提供帮助 这样做的原因是我可以知道驱动程序状态何时
  • waitUntilObjectExists() Amazon S3 PHP SDK 方法,它到底是如何工作的?

    该函数是否会暂停 php 脚本 直到在 s3 服务器上找到该对象 我将它放在 foreach 循环中 一张一张地上传图像 找到对象后 我调用一个方法在本地删除图像 然后删除本地文件夹 如果为空 这是正确的处理方式吗 谢谢 foreach f
  • 从 json 创建下拉列表

    我有一个这种形式的 json COLUMNS ID Name DATA 1 Joe 2 Sam 3 Doug 我正在寻找一个如何在 javascript 中从该数据创建下拉列表的示例 但 json dropdown 列表的所有示例 json
  • set() 可以在 Python 进程之间共享吗?

    我正在 Python 2 7 中使用多重处理来处理非常大的数据集 当每个进程运行时 它会将整数添加到共享的 mp Manager Queue 中 但前提是其他进程尚未添加相同的整数 由于您无法对队列进行 in 式成员资格测试 因此我这样做的
  • “user-images.githubusercontent.com”中的图像是否有过期时间?

    我正在使用博客提供服务GitHub 页面 https pages github com 博客服务有很多图像文件需要上传 所以我需要一个存储图像的存储库 在搜索存储库时 我发现了一种使用 github issues 的方法 我首先捕获图像 然
  • BeautifulSoup 抓取街道地址

    我正在使用最底部的代码来获取weblink 以及清真寺名称 不过我也想得到面值 and 街道地址 请帮助我被困住了 目前我得到以下信息 Weblink div class subtitleLink a href http www salat
  • cx_freeze:QODBC 驱动程序未加载

    我的 python 应用程序如下所示 test py from PyQt4 import QtCore from PyQt4 import QtGui from PyQt4 import QtSql import sys import at
  • 在流浪机器中使用elasticsearch设置graylog2服务器

    我正在尝试在本地开发计算机上安装graylog2 服务器 但遇到了elasticsearch 设置问题 我的elasticsearch作为服务安装在我的开发机器上运行的vagrant机器上 所以我的elasticsearch没有安装在127
  • 如何在样式中访问控件父级的属性

    我的列表视图将项目数据模板化为标签 我正在为该标签设计一种样式 但我不知道如何访问父级的 ListViewItem IsSelected 属性 编辑 尝试了下面的建议 但仍然出现异常 这是我的完整代码
  • 有没有办法让 ion-segment 在 iOS 和 Android 上看起来一样?

    设置ion segment模式后 在ionic lab中渲染后看起来还是不一样 我尝试将离子段和离子工具栏的模式设置为 md 但它们看起来仍然不同 https ibb co HV75Ly2 https ibb co HV75Ly2这是设置模
  • 如何使用 gradle 动态切换/更改 testInstrumentationRunner

    我的项目有两组不同的测试 一组仅使用默认值运行AndroidJUnitRunner另一个必须使用自定义实现来运行TestRunner extends MonitoringInstrumentation 目前我切换testInstrument
  • 如何让 CMake 为目标安装 PDB 文件

    如何让 CMake 安装调试 Visual Studio 生成的 DLL 文件和 EXE 文件所需的配套 PDB 文件 我已经挣扎了一段时间 试图找到这个问题的一个好的答案 我现在认为我找到了一个 使用安装文件命令
  • 在基本模块中找不到动态功能模块中的 Android 提供程序

    我在动态功能模块中使用了一些库 这些库正在将一些提供程序添加到清单中 例如在我的动态模块中的 build gradle 文件中 dependencies implementation com github esafirm android i
  • 不使用apply函数对data.table的每一行进行操作的方法

    我在下面写了一个简单的函数 mcs lt function v ifelse sum diff sort v gt 6 gt 0 NA sd v 它应该采用一个向量 对其进行排序 然后检查每个连续差异中是否存在大于 6 的差异 如果差值大于