Question

Let's say I have species-habitat abundance matrices sampled in time. I am trying to find a neat way to to aggregate over temporal replicates, creating a single species abundances matrix.

# Construct dummy data

mat1<-matrix(c(1,3,0,2,0,0,6,0,10,1), ncol=5, nrow=2)
mat2<-matrix(c(0,11,0,0,1,0,2,3,7,1), ncol=5, nrow=2)
mat3<-matrix(c(2,1,0,0,3,1,1,0,4,0), ncol=5, nrow=2)
colnames(mat1) <-c('sp1','sp2','sp3','sp4','sp5')
rownames(mat1) <- c('h1','h2')
colnames(mat2) <-c('sp1','sp2','sp3','sp4','sp5')
rownames(mat2) <- c('h1','h2')
colnames(mat3) <-c('sp1','sp2','sp3','sp4','sp5')
rownames(mat3) <- c('h1','h2')
# Special case when new species occur
mat4 <- matrix(c(2,1,0,0,3,1,1,0,4,0,6,3), ncol=6, nrow=2)
colnames(mat4) <-c('sp1','sp2','sp3','sp4','sp5','sp6')
rownames(mat4) <- c('h1','h2')

# Replicate matrices are within a list
l.mat<-list(mat1,mat2,mat3,mat4)

My first thought was to use apply(margin=2)(but then again, the matices are within a list, lapply?) and colSums but I have not find a way not to sum over rows (habitat) within each matrix, but rather between, as seen below. Also when a new species occur, it should appear in the aggregated matrix

# Desired output

# Aggregated matrix
   sp1 sp2 sp3 sp4 sp5 sp6
h1   5   0   7  10  25  6
h2  16   2   2   3   2  3

Any pointers would be very much appreciated, thanks!

Was it helpful?

Solution

This is pretty direct to do if you use the "reshape2" package:

library(reshape2)
allMat <- do.call(rbind, lapply(l.mat, melt))
dcast(allMat, X1 ~ X2, fun.aggregate=sum)
#   X1 sp1 sp2 sp3 sp4 sp5 sp6
# 1 h1   5   0   7  10  25   6
# 2 h2  16   2   2   3   2   3

Or, now that I think of it (since there's a melt method for lists, you can just do:

dcast(melt(l.mat), X1 ~ X2, value.var="value", fun.aggregate=sum)

If you want to stick with base R, I haven't found anything quite as direct. Here are two ways I came up with that's along the same lines as above:

Base option 1

allMat <- do.call(rbind, lapply(l.mat, function(x) 
  cbind(id = rownames(x), stack(data.frame(x)))))
xtabs(values ~ id + ind, data = allMat)
#     ind
# id   sp1 sp2 sp3 sp4 sp5 sp6
#   h1   5   0   7  10  25   6
#   h2  16   2   2   3   2   3

Base option 2

allMat <- do.call(rbind, lapply(l.mat, function(x) {
  cbind(expand.grid(dimnames(x)), value = as.vector(x))
}))
allMat
xtabs(value ~ Var1 + Var2, allMat)
#     Var2
# Var1 sp1 sp2 sp3 sp4 sp5 sp6
#   h1   5   0   7  10  25   6
#   h2  16   2   2   3   2   3

OTHER TIPS

library(reshape2)
library(dplyr)
df = rbind(melt(mat1),melt(mat2),melt(mat3),melt(mat4))
sdf = df %.% group_by(Var1,Var2)%.%summarize(value=sum(value))
dcast(sdf, Var1~Var2)

would produce

  Var1 sp1 sp2 sp3 sp4 sp5 sp6
1   h1   5   0   7  10  25   6
2   h2  16   2   2   3   2   3
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top