如果您确实需要速度,一如既往,最好使用 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/.