【问题标题】:R: Scaling Every Column in Data.TableR:缩放 Data.Table 中的每一列
【发布时间】:2019-02-19 00:15:27
【问题描述】:

我有一个包含 37000 行和 27000 列的 data.table。我想在将数据用于预测任务之前对每一列进行预处理和缩放。

我正在使用this 帖子中提到的方法,但发现它工作得非常缓慢,甚至使 R Studio 崩溃。我附上了下面的方法,供参考。是否有更快的方法来缩放大型 data.table 的所有列?

scale.cols <- colnames(DT)
DT[, (scale.cols) := lapply(.SD, scale), .SDcols = scale.cols]

【问题讨论】:

  • 我认为scale 只是最基本的z 分数计算器,因此您可以将scale 替换为function(x) (x - mean(x))/sd(x),它可能会大大加快速度。
  • 如果有人使用data.table,可能想要迭代并使用set(),因为列数很大。
  • @zacdav 如果您拨打[ 一次,那将不是问题,许多set 比许多[ 电话要好得多

标签: r data.table


【解决方案1】:

假设您可以首先以矩阵格式获取数据,因为它在data.table 中对于大量列不会很快,那么一种可能性是使用RcppArmadillo

scale.cpp:

// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
using namespace Rcpp;

// [[Rcpp::export]]
arma::mat armaScale(arma::mat Z) {
    unsigned int j, n = Z.n_rows, k = Z.n_cols;
    double avg, sd;
    arma::colvec z;
    arma::mat res = arma::zeros(n, k);

    for (j=0; j<k; j++) {
        z = Z.col(j);
        avg = arma::mean(z);
        sd = arma::stddev(z);
        res.col(j) = (z - avg) / sd;
    }

    return res;
}

R 代码:

set.seed(0L)
#using a smaller dataset
s <- 2e3
nr <- 3*s
nc <- 2*s
mat <- matrix(rnorm(nr*nc), ncol=nc)

library(RcppArmadillo)
library(Rcpp)
sourceCpp("scale.cpp")

library(microbenchmark)
microbenchmark(armaScale(mat), scale(mat), times=3L)

时间安排:

Unit: milliseconds
           expr       min        lq      mean    median        uq       max neval cld
 armaScale(mat)  272.4988  290.1339  303.5027  307.7689  319.0047  330.2404     3  a 
     scale(mat) 1290.9581 1400.7916 1445.8927 1510.6251 1523.3600 1536.0950     3   b

【讨论】:

  • 不确定是否适合在一个小示例上进行基准测试。 OP特指输入数据大小为10Gb的情况,大概
  • @MichaelChirico。我同意你的观点,但我面临 RAM 限制。最终,需要存储 2 * 999mio(原始矩阵和结果)数字。
  • 我认为 600*400 和 37000*27000 之间有足够的回旋空间;我总是对以毫秒为单位的基准持怀疑态度,尤其是在实际用例可能持续更长的情况下
  • 你的意思是 6000*4000 吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-07-27
相关资源
最近更新 更多