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

时间:2016-12-28 16:43:54

标签: r split apply

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

欢迎任何建议! 感谢

3 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:2)

一些替代方案与接受的答案计算相同。在基础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.call的{​​{1}}会返回一个矩阵。

您可以rbind使用rbind.data.frame来返回data.frame

setNames

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

然后使用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

答案 2 :(得分:1)

我们可以使用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

的类似方法
{{1}}
相关问题