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

R 拆分列表中每列的不同值数,r,split,apply,R,Split,Apply,我的数据集中的每一行都是不同的树。地块是指约700个采样区域,物种为该树的物种,其他列为该树是否存在NA。下面是数据集的一个最小示例 Plot Species 1983 1988 2003 2008 2013 1 11 1 1 1 1 1 1 11 1 1 1 1 NA 1 21

我的数据集中的每一行都是不同的树。地块是指约700个采样区域,物种为该树的物种,其他列为该树是否存在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不能解释不同的图。当我有一个拆分列表时,我不确定如何使用应用函数

欢迎任何建议! 谢谢你的整洁方式:

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
整洁的方法:

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来实现这一点

或者使用dplyr的类似方法

我们可以使用data.table来实现这一点

或者使用dplyr的类似方法


计算结果与公认答案相同的两个备选方案。在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
这需要一个嵌套循环。首先,循环遍历通过在lot上拆分创建的data.frames列表,然后循环遍历每年的每个变量。这里,do.callwithrbind返回一个矩阵

可以将rbind.data.frame与setNames一起使用以返回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


计算结果与公认答案相同的两个备选方案。在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
这需要一个嵌套循环。首先,循环遍历通过在lot上拆分创建的data.frames列表,然后循环遍历每年的每个变量。这里,do.callwithrbind返回一个矩阵

可以将rbind.data.frame与setNames一起使用以返回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


我认为rowsumdf[-1:2],group=df$lot,na.rm=TRUE就可以了,尽管它与你的总数不太一致。例如,1988年的第三个元素是3,而不是2。这似乎是最有效的,但它似乎添加了实际值,而不是存在的不同值的数量。1988年的第三个元素应该是2,因为存在两个不同的物种15和1511@Henrik你说得对!对这里的错误表示歉意,我认为rowsumdf[-1:2],group=df$lot,na.rm=TRUE可以编辑,尽管它与您的总数不太一致。例如,1988年的第三个元素是3,而不是2。这似乎是最有效的,但它似乎添加了实际值,而不是存在的不同值的数量。1988年的第三个元素应该是2,因为存在两个不同的物种15和1511@Henrik你说得对!抱歉这里的错误,我会编辑我喜欢的方法,一些我还没有遇到的东西!但是,它似乎在添加值的数量,而不是存在的不同物种的数量-输出中的最后一行与我的期望输出不匹配。期望输出与数据不一致,这让我想到你想要一个所有物种的总数,见图1 1988,当有2个物种存在时,值为3。我已经包含了唯一计数的代码。第二位非常适合我,非常感谢!我喜欢这个方法,一些我还没有遇到的东西!但是,它似乎在添加值的数量,而不是存在的不同物种的数量-输出中的最后一行与我的期望输出不匹配。期望输出与数据不一致,这让我想到你想要一个所有物种的总数,见图1 1988,当有2个物种存在时,值为3。我已经包含了唯一计数的代码。第二位非常适合我,非常感谢!不是真的。我同时回答它,它使用了我的基本R解决方案中的逻辑。不是真的。我同时回答了这个问题,它使用了我的基本R解决方案中的逻辑。