假设我有以下数据表:
tempmat=matrix(c(1,1,0,4,1,0,0,4,0,1,0,4, 0,0,1,4, 0,0,0,5),5,4,byrow=T)
tempmat=rbind(rep(0,4),tempmat)
tempmat=data.table(tempmat)
names(tempmat)=paste0('prod1vint',1:4)
看起来像:
prod1vint1 prod1vint2 prod1vint3 prod1vint4
1: 0 0 0 0
2: 1 1 0 4
3: 1 0 0 4
4: 0 1 0 4
5: 0 0 1 4
6: 0 0 0 5
我想定义一个新列TN,它以以下方式按行平均。
对于每一行,找到第一个从左到右的非零元素。
然后,找到所有非零元素的平均值。
输出应为:
prod1vint1 prod1vint2 prod1vint3 prod1vint4 TN
1: 0 0 0 0 NA
2: 1 1 0 4 2.5
3: 1 0 0 4 4
4: 0 1 0 4 4
5: 0 0 1 4 4
6: 0 0 0 5 NA
出现NA的原因是:在1中:没有非零元素,在6中:在第一个非零元素的右边没有非零元素。
最佳答案
这是melt
的一个选项
library(data.table)
library(dplyr)
TN <- melt(tempmat[, rid := seq_len(.N)], id.var = 'rid')[,
{i1 <- cumsum(value) > 0
mean(na_if(value[i1][-1], 0), na.rm = TRUE)}, rid]$V1
tempmat[, TN := TN][]
或使用
tidyverse
library(tidyverse)
tempmat %>%
mutate(TN = pmap(., ~ c(...) %>%
keep(., cumsum(.) > 0) %>%
tail(-1) %>%
na_if(0) %>%
mean(na.rm = TRUE)))
或者另一个选择是转置数据集,然后进行逐级操作
t(tempmat) %>%
as.data.frame %>%
summarise_all(list(~ mean(na_if(.[cumsum(.) > 0], 0)[-1],
na.rm = TRUE))) %>%
unlist %>%
mutate(tempmat, TN = .)
或使用向量化方法
library(matrixStats)
m1 <- rowCumsums(as.matrix(tempmat)) > 0
m1[cbind(seq_len(nrow(m1)), max.col(m1, 'first'))] <- FALSE
rowMeans(na_if(tempmat * NA^!m1, 0), na.rm = TRUE)
或使用
apply
apply(tempmat, 1, FUN = function(x)
mean(na_if(x[cumsum(x) > 0], 0)[-1], na.rm = TRUE))