【问题标题】:R: Merge tables and fill empty cells with factor informationR:合并表格并用因子信息填充空白单元格
【发布时间】:2015-04-23 03:01:34
【问题描述】:

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

对于大型“示例”数据集,我深表歉意,但它们捕捉到了我的数据集的复杂性。我的完整数据集有点大,包括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

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    这是一个非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
    

    【讨论】:

      【解决方案2】:

      从您的数据开始:

      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...
      

      【讨论】:

      • 感谢@Frank 和@r2evans!我使用了混合方法....dplybase package。我的实际数据集比我提供的示例要复杂一些(例如,更多的因子列)。所以我用我从你的两个代码中学到的教训把一些东西放在一起。保重。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-13
      • 2021-04-14
      • 1970-01-01
      • 2011-10-12
      • 2013-10-15
      • 1970-01-01
      相关资源
      最近更新 更多