If I didnβt miss something, it looks the same. Start by calculating the sums on the "P":
s = as.matrix(rowsum(dat[-1], dat$P))
Create the final matrix:
k = s[rep(1:nrow(s), each = ncol(s)), ]
Calculate indices to replace with "0" s:
k[col(k) != (row(k) - 1) %% ncol(k) + 1] = 0 k
Data:
dat = structure(list(P = c(1L, 2L, 3L, 1L, 3L, 3L, 2L), A = c(2L, 1L, 0L, 1L, 1L, 0L, 3L), B = c(0L, 1L, 4L, 1L, 1L, 2L, 3L), C = c(5L, 3L, 7L, 0L, 0L, 1L, 4L)), .Names = c("P", "A", "B", "C"), class = "data.frame", row.names = c(NA, -7L))
Having calculated s , user20650 is a simpler alternative:
matrix(diag(ncol(s)), nrow(s) * ncol(s), ncol(s), byrow = TRUE) * c(t(s))
or, also, messing around with other interesting alternatives on the same idea:
kronecker(rep_len(1, nrow(s)), diag(ncol(s))) * c(t(s)) diag(ncol(s))[rep(1:ncol(s), nrow(s)), ] * s[rep(1:nrow(s), each = ncol(s)), ]