Count previous occurences of a string across multiple column



我有一个带有时间顺序索引的四列矩阵和三列名称(字符串)。这是一些玩具数据:

x = rbind(c(1,"sam","harry","joe"), c(2,"joe","sam","jack"),c(3,"jack","joe","jill"),c(4,"harry","jill","joe"))

我想创建三个额外的向量,以计数(每行)任何以前(但不是后续)名称的出现。这是玩具数据的所需结果:

y = rbind(c(0,0,0),c(1,1,0),c(1,2,0),c(1,1,3))

我将失去如何解决问题,并搜索了堆栈溢出以获取相关示例。Dplyr为查找总数提供了答案,但(据我所知)并非一排。

我试图编写一个函数以在单栏空间中处理此问题,但没有运气,即。

thing = sapply(x,function(i)length(grep(i,x[x[1:i]])))

任何提示都将不胜感激。

这是典型的ave seq_along问题类型,但是我们需要首先将数据转换为向量:

t(`dim<-`(ave(rep(1, prod(dim(x[, -1]))), 
              c(t(x[, -1])), FUN = seq_along)  - 1, 
          rev(dim(x[, -1]))))
#      [,1] [,2] [,3]
# [1,]    0    0    0
# [2,]    1    1    0
# [3,]    1    2    0
# [4,]    1    1    3

也许更可读性:

## x without the first column as a vector
x_vec <- c(t(x[, -1]))
## The values that you are looking to obtain...
y_vals <- ave(rep(1, length(x_vec)), x_vec, FUN = seq_along) - 1
## ... in the format you want to obtain them
matrix(y_vals, ncol = ncol(x) - 1, byrow = TRUE)
#      [,1] [,2] [,3]
# [1,]    0    0    0
# [2,]    1    1    0
# [3,]    1    2    0
# [4,]    1    1    3

您可以做:

el = unique(c(x[,-1]))
val = Reduce(`+`, lapply(el, function(u) {b=c(t(x[,-1]))==u; b[b==T]=(cumsum(b[b==1])-1); b}))
matrix(val, ncol=ncol(x[,-1]), byrow=T)
#         [,1] [,2] [,3]
#[1,]    0    0    0
#[2,]    1    1    0
#[3,]    1    2    0
#[4,]    1    1    3

最新更新