2015-05-14 3 views
3

У меня есть четырехколоночная матрица с хронологическим индексом и три столбца имен (строк). Вот некоторые игрушки данные:Подсчитайте предыдущие вхождения строки в несколько столбцов в R

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]]))) 

Любые советы будут оценены.

+0

Вы действительно используете матрицы, или ваши фактические данные считаются как 'data.frame's? – A5C1D2H2I1M1N2O1R2T1

+0

Похоже на то, что вы хотите, чтобы это не выполнялось «для каждой строки», а скорее делается путем обхода всей матрицы «по строке». Естественное упорядочение R-матриц является столбцом, поэтому @AnandaMahto необходимо было дважды использовать операции транспонирования. –

ответ

4

Это типичный 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 
2

Вы можете сделать :

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