【问题标题】:Count number of zeros in each row of large data.frame using purrr::map function使用 purrr::map 函数计算大型 data.frame 每一行中的零数
【发布时间】:2026-02-02 15:10:02
【问题描述】:

我有一个非常大的数据框 280,000 x 20 并且许多行 (obs) 只有 1 或 0 个值。我使用的函数每次操作至少需要 2 个值。我可以使用 for 循环进行迭代,但这需要很长时间。我想使用其中一种 purrr 地图功能来提高速度,因为我将多次这样做。这就是我使用 for 循环的方式:

library(Matrix)
M1 <- as.matrix(rsparsematrix(100, 20, .1, rand.x = runif))
x <- vector("integer")
for(i in 1:dim(M1)[1]){
  l <- (length(which(M1[i,] == 0)))
  x <- c(x,l)
}
ind <- which(x == 19 | x == 20)
M1 <- M1[-ind,]

我还没有找到使用地图的正确方法。我认为它需要使用 mutate 创建另一个列。

M1 %>% mutate(zero_count = length(map(which(. == 0))))

【问题讨论】:

    标签: r purrr map-function


    【解决方案1】:

    目前尚不清楚预期。首先,我们将matrix 转换为tibbledata.frame,然后将mutate 列转换为逻辑列,reduce 转换为单个vector,方法是在每一行中添加(+)所有 TRUE 值,然后cbindvector 与原始矩阵 ('M1')

    library(tidyverse)
    M1 %>% 
      as_tibble %>%
      mutate_all(funs(.==0)) %>%
      reduce(`+`) %>% 
      cbind(M1, Count = .)
    

    更新

    用于根据总和对行进行子集

    M1 %>% 
      as_tibble %>% 
      mutate_all(funs(.==0)) %>% 
      reduce(`+`) %>% 
      `%in%`(19:20)  %>%
      magrittr::extract(M1, .,)
    

    对于base R,它是逻辑matrixcbind 上的rowSums 与原始matrix

    cbind(M1, Count = rowSums(!M1))
    

    或使用rowSums 进行子集化

    M1[rowSums(!M1) %in% 19:20, ]
    

    【讨论】:

    • 这正是我所需要的。数据框中的新列可以过滤计数等于 19 或 20 的任何行,这意味着观察中只有 1 或 0 个值。
    【解决方案2】:

    你可以用apply实现同样的事情

    apply(M1, 1 , function(x) sum(!x))
    

    【讨论】:

    • 我能够在 for 循环中成功运行,但我的数据集有近 30 万个观察值。使用 for 循环运行它需要 4 分钟,使用 @akrun 提供的 purrr 方法运行它需要 1 秒。我一直在尝试使用 tidy 包来保持 apply 系列函数的一致性。你是正确的应用是一个不错的选择。