拆分列表中每列不同值的数量

Number of different values per column in a split list

我的数据集中的每一行都是一棵不同的树。 Plot 是指采样区域(其中大约有 700 个),Species 是树的种类,其他列是树是否存在(1)或不存在(NA)。下面是数据集的一个最小示例

Plot    Species    1983    1988    2003    2008    2013
   1         11       1       1       1       1       1
   1         11       1       1       1       1      NA
   1         21      NA       1       1       1       1
   2         11       1       1       1       NA     NA
   2         34       1       1       1       1       1 
   3         15       1       1       1       1      NA
   3         15      NA       1       1       1      NA
   3         11       1       1       1       1      NA 

基本上我想知道的是每年每个地块有多少不同的物种,不包括 NA 值:

Plot        1983    1988    2003    2008    2013
   1           1       2       2       2       2
   2           2       2       2       1       1
   3           2       2       2       2       0

我目前的策略如下 - 将所有值 1 更改为它们的物种编号,因此数据集如下所示

Plot    Species    1983    1988    2003    2008    2013
   1         11      11      11      11      11      11
   1         11      11      11      11      11      NA
   1         21      NA      21      21      21      21
   2         11      11      11      11      NA      NA
   2         34      34      34      34      34      34 
   3         15      15      15      15      15      NA
   3         15      NA      15      15      15      NA
   3         11      11      11      11      11      NA

然后使用

根据地块编号拆分数据集
split(data, as.factor(data$Plot))

我想我基本上想要每一列的长度来找出有多少不同的值,但是 colSums 没有考虑到不同的图。当我有一个拆分列表时,我不确定如何使用应用函数。

欢迎提出任何建议! 谢谢

一个tidyverse方法:

library(tidyr)
library(dplyr)

data %>%
  gather(Year, Value, na.rm = TRUE, -Plot, -Species) %>%
  group_by(Plot, Year) %>% 
  distinct(Species, .keep_all = TRUE) %>% 
  count(Plot, Year) %>% 
  spread(Year, n, fill = 0)

Source: local data frame [3 x 6]
Groups: Plot [3]

   Plot `1983` `1988` `2003` `2008` `2013`
* <int>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>
1     1      1      2      2      2      2
2     2      2      2      2      1      1
3     3      2      2      2      2      0

我们可以用 data.table

library(data.table)
setDT(df1)[, lapply(.SD, function(x) uniqueN(na.omit(x*Species))) , Plot, .SDcols = 3:7]
#   Plot 1983 1988 2003 2008 2013
#1:    1    1    2    2    2    2
#2:    2    2    2    2    1    1
#3:    3    2    2    2    2    0

或与 dplyr

类似的方法
library(dplyr)
df1 %>%
    group_by(Plot) %>%
    summarise_each(funs(n_distinct(na.omit(Species * .))), 3:7)
# A tibble: 3 × 6
#   Plot `1983` `1988` `2003` `2008` `2013`
#  <int>  <int>  <int>  <int>  <int>  <int>
#1     1      1      2      2      2      2
#2     2      2      2      2      1      1
#3     3      2      2      2      2      0

几个与接受的答案计算相同的备选方案。在 base R 中使用 split-apply-combine 方法,你得到

do.call(rbind, lapply(split(df[-(1:2)] * df$Species, df$lot),
                      function(x) sapply(x, function(y) length(unique(y[!is.na(y)])))))
  X1983 X1988 X2003 X2008 X2013
1     1     2     2     2     2
2     2     2     2     1     1
3     2     2     2     2     0

这需要嵌套循环。首先,遍历通过拆分批次创建的 data.frames 列表,然后遍历每个年份变量。这里,do.callrbind return 是一个矩阵。

您可以使用 rbind.data.framesetNames 到 return 一个 data.frame

setNames(do.call(rbind.data.frame, lapply(split(df[-(1:2)] * df$Species, df$lot),
                                         function(x) sapply(x,
                                                 function(y) length(unique(y[!is.na(y)]))))),
         names(df)[-(1:2)])

  X1983 X1988 X2003 X2008 X2013
1     1     2     2     2     2
2     2     2     2     1     1
3     2     2     2     2     0

在这两个中,批次都包含在行名称中。

然后用data.table

library(data.table)
setDT(df)

df[, lapply(.SD, function(x) length(unique((x * Species)[!is.na(x)]))),
  .SDcols=X1983:X2013, by=lot]
   lot X1983 X1988 X2003 X2008 X2013
1:   1     1     2     2     2     2
2:   2     2     2     2     1     1
3:   3     2     2     2     2     0