使用 apply with mean 时忽略值

Ignoring values when using apply with mean

我想在使用 apply(x,1,mean) 计算平均值时排除值:

#Example data:
df <- data.frame(A1 = c(0,1,2,3,4,2,NA,5,6), 
                 A2 = c(5,0,0,4,NA,5,3,2,1), 
                 A3 = c(0,0,1,2,4,5,3,4,3), 
                 B1 = c(9,9,9,9,9,9,9,9,9))

#I am using grep, because I need to use specific parts of the column names and I can not use the index
df$MEANA <- apply(df[,grep("A", colnames(df))],1,mean, na.rm = TRUE)

这给了我平均值,忽略了 NA 值

df$MEANA
[1] 1.6666667 0.3333333 1.0000000 3.0000000 4.0000000 4.0000000 3.0000000 3.6666667 3.3333333

我也想忽略 0。我可以通过将 0 更改为 NA 来做到这一点。或者读入数据时设置0s为NA。

我的问题:我可以忽略 apply 命令中的 0,就像我可以使用 na.rm = TRUE 那样吗? (例如ignore.value = 0)我是apply概念的新手,不知道是否可行。

更新:

aind <- grep("A", names(df))
#ignore NAs
df$M1 <- apply(df[,grep("A", colnames(df))],1,mean, na.rm = TRUE)
#Ignore 0 and 6 and NA
df$M2 <-rowMeans(sapply(df[aind], function(x) replace(x, x %in% c(0, 6), NA)), na.rm = TRUE)
#ignore 0 and NA
df$M3 <- rowMeans(replace(df[aind], df[aind] == 0, NA), na.rm = TRUE)

df

    > A1 A2 A3 B1        M1       M2       M3
1  0  5  0  9 1.6666667 5.000000 5.000000
2  1  0  0  9 0.3333333 1.000000 1.000000
3  2  0  1  9 1.0000000 1.500000 1.500000
4  3  4  2  9 3.0000000 3.000000 3.000000
5  4 NA  4  9 4.0000000 4.000000 4.000000
6  2  5  5  9 4.0000000 4.000000 4.000000
7 NA  3  5  9 4.0000000 4.000000 4.000000
8  5  2  4  9 3.6666667 3.666667 3.666667
9  6  0  4  9 3.3333333 4.000000 5.000000
> 

用一个lamdba函数就更简单了

aind <- grep("A", names(df))
apply(df[aind], 1, function(x) mean(x[x !=0], na.rm = TRUE))

或者在 replace 将 0 转换为 NA 之后使用向量化的 rowMeans 会更快

rowMeans(replace(df[aind], df[aind] == 0, NA), na.rm = TRUE)

如果我们需要设置多个值,请在 vector 上使用 %in% 而不是 ==,因为 == 是逐元素比较,这可以回收值,从而产生不正确的结果

rowMeans(sapply(df[aind], function(x) 
       replace(x, x %in% c(0, 6), NA)), na.rm = TRUE)

试试这个:

df[df == 0] <- NA

然后是您的代码:

df$MEANA <- apply(df[,grep("A", colnames(df))],1,mean, na.rm = TRUE)
library(dplyr)

df %>% 
  rowwise() %>% 
  mutate(MeanA = c_across(starts_with('A')) %>% na_if(0) %>% mean(na.rm = TRUE))

# # A tibble: 9 x 5
# # Rowwise: 
#      A1    A2    A3    B1 MeanA
#   <dbl> <dbl> <dbl> <dbl> <dbl>
# 1     0     5     0     9  5   
# 2     1     0     0     9  1   
# 3     2     0     1     9  1.5 
# 4     3     4     2     9  3   
# 5     4    NA     4     9  4   
# 6     2     5     5     9  4   
# 7    NA     3     3     9  3   
# 8     5     2     4     9  3.67
# 9     6     1     3     9  3.33