【问题标题】:Delete columns where all values are 0删除所有值为 0 的列
【发布时间】:2020-08-23 18:01:39
【问题描述】:

我有一个带有15000 列的数字矩阵。我想完全删除 all 值为0 的列。

     col1     col2     col3     col4
row1  1        0        0        1
row2  3.4      0        0        2.4
row3  0.56     0        0        0
row4  0        0        0        0
 

在这里,我想删除列col2 和col3,并保留其余列。 我怎么能用R做到这一点? 谢谢

【问题讨论】:

    标签: r


    【解决方案1】:

    做同样事情的更快方法(快 3 - 5 倍)是

    M[,colSums(M^2) !=0]
    

    编辑:添加了此处建议的各种方法的时间细节。 @Dwin 使用 M[, colSums(abs(M)) ! == 0] 建议的方法似乎工作得最快,尤其是当矩阵很大时。如果有其他解决方案,我会更新基准测试报告。

    m <- cbind(rnorm(1000),0)
    M <- matrix(rep(m,7500), ncol=15000)
    
    f_joran   = function(M) M[, !apply(M==0,2,all)]
    f_ramnath = function(M) M[, colSums(M^2) != 0]
    f_ben     = function(M) M[, colSums(M==0) != ncol(M)]
    f_dwin    = function(M) M[, colSums(abs(M)) != 0]
    
    library(rbenchmark)
    benchmark(f_joran(M), f_ramnath(M), f_ben(M), f_dwin(M), 
       columns = c('test', 'elapsed', 'relative'), 
       order = 'relative', replications = 10)
    
    
              test elapsed relative
    4    f_dwin(M)  11.699 1.000000
    2 f_ramnath(M)  12.056 1.030515
    1   f_joran(M)  26.453 2.261133
    3     f_ben(M)  28.981 2.477220
    

    【讨论】:

    • @Ramnath:使用abs()可能比平方更快
    • @Dwin。你是对的。 abs() 确实似乎比对矩阵求平方更快。有关时间安排,请参阅我的答案。
    • 嘿,感谢您的时间安排。我会得出结论,我错了。 3% 的差异不值得麻烦。
    • 为了健壮性,我会添加drop=F,例如f_dwin = function(M) M[, colSums(abs(M)) != 0, drop = F]
    【解决方案2】:

    这个怎么样,使用apply和all:

    M <- as.matrix(data.frame(a=runif(10),b=rep(0,10),c=runif(10),d=rep(0,10)))
    
    M[,which(!apply(M,2,FUN = function(x){all(x == 0)}))]
    

    【讨论】:

    • 你可以稍微压缩一下:M[,which(!apply(M==0,2,all))]
    • 或者更进一步:M[ , !apply(M==0,2,all)]
    • 光滑。如果数据中没有零,您可以将零换成 NA,转置矩阵,应用 complete.cases 并转回。只是把它放在那里......
    【解决方案3】:

    您提到了 15,000 列,但没有提到行数。如果有几千行并且速度是一个问题,colSums 将比apply 快很多。

    m <- cbind(rnorm(1000),0)
    M <- matrix(rep(m,7500), ncol=15000)
    system.time(foo <- M[,which(!apply(M==0,2,all))])
    #   user  system elapsed 
    #   1.63    0.23    1.86 
    system.time(bar <- M[,colSums(M)!=0])
    #   user  system elapsed 
    #  0.340   0.060   0.413
    identical(foo,bar)
    # [1] TRUE
    

    【讨论】:

    • 使用colSums(M) != 0的问题是矩阵中可能有负值。
    • 啊,真的;我没有看到你的答案。我开始发布我的,被打断了,30 分钟后完成了。
    猜你喜欢
    • 1970-01-01
    • 2016-07-18
    • 2022-11-23
    • 2015-03-26
    • 2014-03-28
    • 2014-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多