R:合并表格并用因子信息填充空单元格

R: Merge tables and fill empty cells with factor information

我有一个相对复杂的 table merge/expansion 问题。下面我包含了一个示例 DATA 和所需的 RESULT tables。我有 4 个因子(SITEDATESAMPLETAXA)和三个数字列(123).我需要让每个 SITEDATESAMPLE 都有 TAXA 1、2、100 和 150。通过这个过程我需要填写空因子用适当的信息填充单元格并用 0 填充数字列。

对于大型 "example" 数据集,我深表歉意,但它们捕捉到了我数据集的复杂性。我的完整数据集有点大,有4个SITE、15个DATE、12个SAMPLE、167个TAXA。使用 dplyr 的解决方案是首选,但我当然愿意接受其他选项。在 excel 中做到这一点需要一个浣熊的年龄!提前致谢。

 DATA
    SITE    DATE    SAMPLE  TAXA    1   2   3
    NSV 8-Jul-13    Pool    1   10  10  10
    NSV 8-Jul-13    Pool    2   10  10  10
    NSV 8-Jul-13    Riffle  1   10  10  10
    NSV 8-Jul-13    Riffle  2   10  10  10
    NSV 23-Oct-13   Pool    1   10  10  10
    NSV 23-Oct-13   Pool    2   10  10  10
    NSV 23-Oct-13   Riffle  1   10  10  10
    NSV 23-Oct-13   Riffle  2   10  10  10
    SFP 4-Jul-13    Pool    1   10  10  10
    SFP 4-Jul-13    Pool    2   10  10  10
    SFP 4-Jul-13    Riffle  1   10  10  10
    SFP 4-Jul-13    Riffle  2   10  10  10
    SFP 27-Oct-13   Pool    1   10  10  10
    SFP 27-Oct-13   Pool    2   10  10  10
    SFP 27-Oct-13   Pool    100 10  10  10
    SFP 27-Oct-13   Pool    150 10  10  10
    SFP 27-Oct-13   Riffle  1   10  10  10
    SFP 27-Oct-13   Riffle  2   10  10  10
    SFP 27-Oct-13   Riffle  100 10  10  10
    SFP 27-Oct-13   Riffle  150 10  10  10

RESULT
    SITE    DATE    SAMPLE  TAXA    1   2   3
    NSV 8-Jul-13    Pool    1   10  10  10
    NSV 8-Jul-13    Pool    2   10  10  10
    NSV 8-Jul-13    Pool    100 0   0   0
    NSV 8-Jul-13    Pool    150 0   0   0
    NSV 8-Jul-13    Riffle  1   10  10  10
    NSV 8-Jul-13    Riffle  2   10  10  10
    NSV 8-Jul-13    Riffle  100 0   0   0
    NSV 8-Jul-13    Riffle  150 0   0   0
    NSV 23-Oct-13   Pool    1   10  10  10
    NSV 23-Oct-13   Pool    2   10  10  10
    NSV 23-Oct-13   Pool    100 0   0   0
    NSV 23-Oct-13   Pool    150 0   0   0
    NSV 23-Oct-13   Riffle  1   10  10  10
    NSV 23-Oct-13   Riffle  2   10  10  10
    NSV 23-Oct-13   Riffle  100 0   0   0
    NSV 23-Oct-13   Riffle  150 0   0   0
    SFP 4-Jul-13    Pool    1   10  10  10
    SFP 4-Jul-13    Pool    2   10  10  10
    SFP 4-Jul-13    Pool    100 0   0   0
    SFP 4-Jul-13    Pool    150 0   0   0
    SFP 4-Jul-13    Riffle  1   10  10  10
    SFP 4-Jul-13    Riffle  2   10  10  10
    SFP 4-Jul-13    Riffle  100 0   0   0
    SFP 4-Jul-13    Riffle  150 0   0   0
    SFP 27-Oct-13   Pool    1   10  10  10
    SFP 27-Oct-13   Pool    2   10  10  10
    SFP 27-Oct-13   Pool    100 10  10  10
    SFP 27-Oct-13   Pool    150 10  10  10
    SFP 27-Oct-13   Riffle  1   10  10  10
    SFP 27-Oct-13   Riffle  2   10  10  10
    SFP 27-Oct-13   Riffle  100 10  10  10
    SFP 27-Oct-13   Riffle  150 10  10  10

从您的数据开始:

dat <- structure(list(SITE = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L),
                          .Label = c("NSV", "SFP"), class = "factor"),
                      DATE = structure(c(4L, 4L, 4L, 4L, 1L, 1L, 1L, 1L, 3L, 3L, 3L, 3L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L),
                          .Label = c("23-Oct-13", "27-Oct-13", "4-Jul-13", "8-Jul-13"
                                     ), class = "factor"),
                      SAMPLE = structure(c(1L, 1L, 2L, 2L, 1L, 1L, 2L, 2L, 1L, 1L, 2L, 2L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L), .Label = c("Pool", "Riffle"), class = "factor"),
                      TAXA = c(1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 100L, 150L, 1L, 2L, 100L, 150L),
                      v1 = c(10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L),
                      v2 = c(10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L),
                      v3 = c(10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L)),
                 .Names = c("SITE", "DATE", "SAMPLE", "TAXA", "v1", "v2", "v3"),
                 class = "data.frame", row.names = c(NA, -20L))

一种技术,使用dplyr

library(dplyr)
eg <- do.call('expand.grid', lapply(dat[,1:4], unique))
result <- right_join(dat, eg, by=c('SITE', 'DATE', 'SAMPLE', 'TAXA')) %>%
    mutate(v1 = ifelse(is.na(v1), 0, v1),
           v2 = ifelse(is.na(v2), 0, v2),
           v3 = ifelse(is.na(v3), 0, v3)) %>%
    arrange(SITE, DATE, SAMPLE, TAXA)
head(result, n=8)
##   SITE      DATE SAMPLE TAXA v1 v2 v3
## 1  NSV 23-Oct-13   Pool    1 10 10 10
## 2  NSV 23-Oct-13   Pool    2 10 10 10
## 3  NSV 23-Oct-13   Pool  100  0  0  0
## 4  NSV 23-Oct-13   Pool  150  0  0  0
## 5  NSV 23-Oct-13 Riffle    1 10 10 10
## 6  NSV 23-Oct-13 Riffle    2 10 10 10
## 7  NSV 23-Oct-13 Riffle  100  0  0  0
## 8  NSV 23-Oct-13 Riffle  150  0  0  0

使用arrange只是简单的按照你的结果排列,但是不管怎样数据都是完整的

编辑:

我意识到结果 data.frame 中的内容太多了。根据@Frank 的评论,这是更正确的,而且更紧凑(arrange 仍然是可选的):

dat %>% select(SITE, DATE, SAMPLE) %>% unique() %>%
    merge(y=list(TAXA=unique(dat$TAXA)), all.x=TRUE) %>%
    arrange(SITE, DATE, SAMPLE, TAXA)
##    SITE      DATE SAMPLE TAXA
## 1   NSV 23-Oct-13   Pool    1
## 2   NSV 23-Oct-13   Pool    2
## 3   NSV 23-Oct-13   Pool  100
## 4   NSV 23-Oct-13   Pool  150
## 5   NSV 23-Oct-13 Riffle    1
## 6   NSV 23-Oct-13 Riffle    2
## 7   NSV 23-Oct-13 Riffle  100
## 8   NSV 23-Oct-13 Riffle  150
## ...snip...

这是一个非dplyr的解决方案。我敢肯定还有更优雅的方法,但这里有一个基本的 R 方法。我调用了你的输入 data.frame d:

d2 <- expand.grid(apply(unique(d[,c("SITE","DATE")]), 1, paste, collapse=" "),
                  unique(d$SAMPLE), unique(d$TAXA))
d2 <- cbind(matrix(unlist(strsplit(as.character(d2$Var1), " ")), ncol=2, byrow=TRUE),
            d2[,2:3])
names(d2)<-names(d)[1:4]

d2 <- merge(d2,d, all.x=TRUE)

d2[which(is.na(d2), arr.ind=TRUE)] <- 0

输出:

   SITE      DATE SAMPLE TAXA X1 X2 X3
1   NSV 23-Oct-13   Pool    1 10 10 10
2   NSV 23-Oct-13   Pool    2 10 10 10
3   NSV 23-Oct-13   Pool  100  0  0  0
4   NSV 23-Oct-13   Pool  150  0  0  0
5   NSV 23-Oct-13 Riffle    1 10 10 10
6   NSV 23-Oct-13 Riffle    2 10 10 10
7   NSV 23-Oct-13 Riffle  100  0  0  0
8   NSV 23-Oct-13 Riffle  150  0  0  0
9   NSV  8-Jul-13   Pool    1 10 10 10
10  NSV  8-Jul-13   Pool    2 10 10 10
11  NSV  8-Jul-13   Pool  100  0  0  0
12  NSV  8-Jul-13   Pool  150  0  0  0
13  NSV  8-Jul-13 Riffle    1 10 10 10
14  NSV  8-Jul-13 Riffle    2 10 10 10
15  NSV  8-Jul-13 Riffle  100  0  0  0
16  NSV  8-Jul-13 Riffle  150  0  0  0
17  SFP 27-Oct-13   Pool    1 10 10 10
18  SFP 27-Oct-13   Pool    2 10 10 10
19  SFP 27-Oct-13   Pool  100 10 10 10
20  SFP 27-Oct-13   Pool  150 10 10 10
21  SFP 27-Oct-13 Riffle    1 10 10 10
22  SFP 27-Oct-13 Riffle    2 10 10 10
23  SFP 27-Oct-13 Riffle  100 10 10 10
24  SFP 27-Oct-13 Riffle  150 10 10 10
25  SFP  4-Jul-13   Pool    1 10 10 10
26  SFP  4-Jul-13   Pool    2 10 10 10
27  SFP  4-Jul-13   Pool  100  0  0  0
28  SFP  4-Jul-13   Pool  150  0  0  0
29  SFP  4-Jul-13 Riffle    1 10 10 10
30  SFP  4-Jul-13 Riffle    2 10 10 10
31  SFP  4-Jul-13 Riffle  100  0  0  0
32  SFP  4-Jul-13 Riffle  150  0  0  0