按因子将 data.frame 拆分为列表,然后使用 xtabs 将列表转换为矩阵并删除所有未使用的级别?

Split data.frame by factor into list, then turn the list into matrix with xtabs and drop all unused levels?

我有一个相对较大的生态网络数据集(植物 x 动物相互作用)。最终,我想按一个因素(例如,站点)将数据集拆分为一系列列表,并对这些迷你网络中的每一个进行 运行 分析。例如,数据看起来像这样:

site<-c("A", "A", "A", "A", "B", "B", "B", "B", "C", "C", "C", "C")
animal<-c("bee", "bee", "fly", "bird", "bee", "fly", "fly", "fly", "bird", "bird", "bee", "fly")
plant<-c("red", "red", "blue", "blue", "blue", "purple", "green", "yellow", "blue", "blue", "red", "yellow")
interactions<-c(4, 9, 5, 7, 2, 3, 5, 5, 10, 9, 2, 12)

df<-data.frame(site, animal, plant, interactions)

我首先将 data.frame 由 "site" 拆分为一系列列表,我使用 split()

完成了这些列表
dl<-split(df, df$site)

然后我将这些列表中的每一个转换成一个矩阵,其中植物和动物作为行和列,矩阵的内容作为每种植物和动物之间相互作用的总和。我已经使用 lapply() 和 xtabs():

实现了这一点
ml<-lapply(dl, function(x) xtabs(x$interactions ~ x$animal + x$plant))

但是...当我这样做时,整个 data.frame 中的每一种植物和动物都包含在每个单独的矩阵中,出于各种原因我不想这样做。当查看 str(ml) 时,这一点很明显。我尝试使用 lapply() 和 factor() 删除每个单独矩阵中未使用的植物和动物,但这没有用。

如何有效地将列表中每个站点的 data.frame 转换为仅包含该站点上的植物和动物的矩阵?例如,我希望站点 "A" 矩阵看起来像这样:

          plant
  animal  blue  red 
    bee     0    13
    bird    7     0 
    fly     5     0 

我们可以使用droplevels删除未使用的关卡

ml <- lapply(dl, function(x) xtabs(interactions~animal+plant, droplevels(x)))

ml[[1]]
#       plant
#animal blue red
# bee     0  13
# bird    7   0
# fly     5   0