获取列意味着非零数据

How*_*ing 6 r

R可以获取数据框的非零值的colMeans吗?

data<-data.frame(col1=c(1,0,1,0,3,3),col2=c(5,0,5,0,7,7))
colMeans(data)   # 1.33,4
Run Code Online (Sandbox Code Playgroud)

我想要像:

mean(data$col1[data$col1>0]) # 2
mean(data$col2[data$col2>0]) # 6
Run Code Online (Sandbox Code Playgroud)

提前致谢


解决方案的基准:

n <- 2E4
m <- 1E3
data <- matrix(runif(n*m),nrow = n)

system.time (col_means <- colSums(data)/colSums(!!data) ) 
#   user  system elapsed 
# 0.087   0.007   0.094 

system.time (   colMeans(NA^(data==0)*data, na.rm=TRUE)) 
#   user  system elapsed 
#  0.167   0.084   0.251 

system.time (vapply(data, function(x) mean(x[x!=0]), numeric(1))) 
#   user  system elapsed 
#126.519   0.737 127.715 

library(dplyr)
system.time (summarise_each(data, funs(mean(.[.!=0])))) # Gave error
Run Code Online (Sandbox Code Playgroud)

Jam*_*mes 9

您可以同时使用colSums数据和"逻辑表示"来将列总和除以每列的非零元素数:

colSums(data)/colSums(!!data)
col1 col2 
   2    6 
Run Code Online (Sandbox Code Playgroud)


akr*_*run 6

您可以更改0NA,然后使用,colMeans因为它有一个选项na.rm=TRUE.在两步过程中,我们将'0'的数据元素转换为'NA',然后colMeans排除NA元素.

  is.na(data) <- data==0
  colMeans(data, na.rm=TRUE) 
  #   col1 col2 
  #    2    6 
Run Code Online (Sandbox Code Playgroud)

如果您只需要一步,我们可以通过对('0'和非零元素对应的值执行()将逻辑矩阵(data==0)更改为NA和1 NA^,然后与原始数据相乘,以便将1个值更改为元素在那个位置,NA仍然如此.我们可以colMeans按照上面的那样输出.

   colMeans(NA^(data==0)*data, na.rm=TRUE)
   #  col1 col2 
   #   2    6 
Run Code Online (Sandbox Code Playgroud)

另一种选择是使用sapply/vapply.如果数据集非常大,转换为a matrix可能不是一个好主意,因为它可能会导致内存问题.通过使用sapply或更具体vapply(更快一点)循环列,我们得到mean非零元素.

 vapply(data, function(x) mean(x[x!=0]), numeric(1))
 #  col1 col2 
 #  2    6 
Run Code Online (Sandbox Code Playgroud)

或者我们可以使用summarise_each并指定在对funs非零元素进行子集化之后的函数.

 library(dplyr)
 summarise_each(data, funs(mean(.[.!=0])))
 #  col1 col2
 #1    2    6
Run Code Online (Sandbox Code Playgroud)