在R中按年份和地区分割计数数据

10

我有一个非常大的(太大了,无法在Excel中打开)生物数据集,看起来像这样

    year <- c(1990, 1980, 1985, 1980, 1990, 1990, 1980, 1985, 1985,1990, 
              1980, 1985, 1980, 1990, 1990, 1980, 1985, 1985,
              1990, 1980, 1985, 1980, 1990, 1990, 1980, 1985, 1985)
    species <- c('A', 'A', 'B', 'B', 'B', 'C', 'C', 'C', 'A','A', 'A', 
                 'B', 'B', 'B', 'C', 'C', 'C', 'A', 'A', 'A', 'B', 'B', 'B', 
                 'C', 'C', 'C', 'A')
    region <- c(1, 1, 1, 3, 2, 3, 3, 2, 1, 1, 3, 3, 3, 2, 2, 1, 1, 1,1, 3, 3, 
                3, 2, 2, 1, 1, 1)
    df <- data.frame(year, species, region)

    df
    year species region
 1  1990       A      1
 2  1980       A      1
 3  1985       B      1
 4  1980       B      3
 5  1990       B      2
 6  1990       C      3
 7  1980       C      3
 8  1985       C      2
 9  1985       A      1
 10 1990       A      1
 11 1980       A      3
 12 1985       B      3
 13 1980       B      3
 14 1990       B      2
 15 1990       C      2
 16 1980       C      1
 17 1985       C      1
 18 1985       A      1
 19 1990       A      1
 20 1980       A      3
 21 1985       B      3
 22 1980       B      3
 23 1990       B      2
 24 1990       C      2
 25 1980       C      1
 26 1985       C      1
 27 1985       A      1

我想要做的是确定每个地区(1、2或3)在我手头有的三年中(1980、1985或1990年)有多少个A、B或C物种。

我希望得到一个数据集,其外观类似于以下内容:

      region A_1980 B_1980 C_1980 A_1985 B_1985 C_1985 A_1990 B_1990 C_1990
 1      1      0      0      0      0      0      0      0      0      0
 2      2      1      1      1      1      1      1      1      1      1
 3      3      2      2      2      2      2      2      2      2      2

希望每行代表一个区域,每列代表特定年份中每个物种的计数。我尝试过使用spread函数与group_by dplyr函数一起使用来实现这一点,但我无法得到接近我想要的结果。

有人有什么建议吗?

2个回答

12

像这样的吗?

library(dplyr)

df2 <- df %>% 
  mutate(sp_year = paste(species, year, sep = "_")) %>%
  group_by(region) %>% 
  count(sp_year) %>% 
  spread(sp_year,n)

df2

这将会给出:

# A tibble: 3 x 10
# Groups:   region [3]
  region A_1980 A_1985 A_1990 B_1980 B_1985 B_1990 C_1980 C_1985 C_1990
   <dbl>  <int>  <int>  <int>  <int>  <int>  <int>  <int>  <int>  <int>
1      1      1      3      3     NA      1     NA      2      2     NA
2      2     NA     NA     NA     NA     NA      3     NA      1      2
3      3      2     NA     NA      3      2     NA      1     NA      1

1
还可以使用?tidyr::unite代替mutate(paste)。至少会更简洁。 - Shree

5

与wl1234的答案类似,但更加简洁。我们可以使用unite来合并列。我们还可以在不使用group_by变量的情况下使用count。最后,我们可以在spread函数中设置fill = 0,以将NA替换为0。

library(tidyverse)

df2 <- df %>%
  unite(sp_year, species, year, sep = "_") %>%
  count(sp_year, region) %>%
  spread(sp_year, n, fill = 0)
df2
# # A tibble: 3 x 10
#   region A_1980 A_1985 A_1990 B_1980 B_1985 B_1990 C_1980 C_1985 C_1990
#    <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>
# 1      1      1      3      3      0      1      0      2      2      0
# 2      2      0      0      0      0      0      3      0      1      2
# 3      3      2      0      0      3      2      0      1      0      1

1
这太棒了,我也喜欢NA => 0的添加!谢谢你! - colebrookson
我不知道 unite 这个函数。下次我会用它代替 paste - william3031

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接