使用组外组合完成组内的数据框

时间:2018-11-26 20:00:59

标签: r dplyr tidyverse tidyr

我需要在组内添加缺失的变量组合,但要使用该组外部的组合。请看下面的例子。这是一个数据框架,评分者在其中查看样本,然后回答有关样本的三个问题。评估者A查看了样本1、2和3,而评估者B仅查看了样本1和2。还请注意,评估者B仅完成了样本1的项目7060和7930,但没有完成项目7842。隐式缺失项得分为显式缺失。目标是为样本中缺少的项目添加行,但不添加评估者中缺少的样本(即,不要将样本3添加到评估者B中,而是将缺失的项目添加到由评估者B评估的样本中)。

library(tidyverse)

df <- data_frame(
  rater_id = c(rep("A", 9), rep("B", 5)),
  sample_id = c(rep(1, 3), rep(2, 3), rep(3, 3), rep(1, 2), rep(2, 3)),
  item_id = c(7060, 7842, 7930, 9571, 4678, 5966, 1758, 3148, 2574,
              7060, 7930, 9571, 4678, 5966),
  score = sample(c(0, 1), size = 14, replace = TRUE)
)
df
#> # A tibble: 14 x 4
#>    rater_id sample_id item_id score
#>    <chr>        <dbl>   <dbl> <dbl>
#>  1 A                1    7060     0
#>  2 A                1    7842     0
#>  3 A                1    7930     1
#>  4 A                2    9571     0
#>  5 A                2    4678     0
#>  6 A                2    5966     1
#>  7 A                3    1758     0
#>  8 A                3    3148     1
#>  9 A                3    2574     0
#> 10 B                1    7060     0
#> 11 B                1    7930     0
#> 12 B                2    9571     0
#> 13 B                2    4678     1
#> 14 B                2    5966     1

我尝试使用tidy::complete收效甚微。通过sample_iditem_id进行嵌套不会添加丢失的行,因为数据中已经存在sample_iditem_id的所有组合。

df %>% complete(nesting(sample_id, item_id))
#> # A tibble: 14 x 4
#>    sample_id item_id rater_id score
#>        <dbl>   <dbl> <chr>    <dbl>
#>  1         1    7060 A            0
#>  2         1    7060 B            0
#>  3         1    7842 A            0
#>  4         1    7930 A            1
#>  5         1    7930 B            0
#>  6         2    4678 A            0
#>  7         2    4678 B            1
#>  8         2    5966 A            1
#>  9         2    5966 B            1
#> 10         2    9571 A            0
#> 11         2    9571 B            0
#> 12         3    1758 A            0
#> 13         3    2574 A            0
#> 14         3    3148 A            1

在嵌套语句之外添加rater_id也无法提供所需的输出。它成功添加了示例1的缺失行,而且还添加了示例3的其他缺失行。但是,由于从未给评定者B提供样品3,因此我们不会将其视为“缺失”(即使从技术上讲是这样)

df %>% complete(rater_id, nesting(sample_id, item_id))
#> # A tibble: 18 x 4
#>    rater_id sample_id item_id score
#>    <chr>        <dbl>   <dbl> <dbl>
#>  1 A                1    7060     0
#>  2 A                1    7842     0
#>  3 A                1    7930     1
#>  4 A                2    4678     0
#>  5 A                2    5966     1
#>  6 A                2    9571     0
#>  7 A                3    1758     0
#>  8 A                3    2574     0
#>  9 A                3    3148     1
#> 10 B                1    7060     0
#> 11 B                1    7842    NA
#> 12 B                1    7930     0
#> 13 B                2    4678     1
#> 14 B                2    5966     1
#> 15 B                2    9571     0
#> 16 B                3    1758    NA
#> 17 B                3    2574    NA
#> 18 B                3    3148    NA

理想的输出如下:

#> # A tibble: 18 x 4
#>    rater_id sample_id item_id score
#>    <chr>        <dbl>   <dbl> <dbl>
#>  1 A                1    7060     0
#>  2 A                1    7842     0
#>  3 A                1    7930     1
#>  4 A                2    4678     0
#>  5 A                2    5966     1
#>  6 A                2    9571     0
#>  7 A                3    1758     0
#>  8 A                3    2574     0
#>  9 A                3    3148     1
#> 10 B                1    7060     0
#> 11 B                1    7842    NA
#> 12 B                1    7930     0
#> 13 B                2    4678     1
#> 14 B                2    5966     1
#> 15 B                2    9571     0

1 个答案:

答案 0 :(得分:1)

这有点难看,但是您可以使用最后一次尝试(在nesting语句之外添加rater_id),然后删除完全不存在rater-sample对的情况。可能有几种方法可以做到这一点,但这种方法似乎可行:

df %>% 
  complete(rater_id, nesting(sample_id, item_id)) %>% # This was your approach
  group_by(rater_id, sample_id) %>% 
  mutate(count_non_nas = sum(!is.na(score))) %>% # Count up the number of non-NA scores
  filter(count_non_nas > 0) %>% # Remove cases where ALL the scores in a group are NA
  select(-count_non_nas) %>% # Drop the intermediate column
  ungroup()

df

# A tibble: 15 x 4
   rater_id sample_id item_id score
   <chr>        <dbl>   <dbl> <dbl>
 1 A                1    7060     1
 2 A                1    7842     0
 3 A                1    7930     0
 4 A                2    4678     0
 5 A                2    5966     0
 6 A                2    9571     0
 7 A                3    1758     0
 8 A                3    2574     0
 9 A                3    3148     0
10 B                1    7060     1
11 B                1    7842    NA
12 B                1    7930     1
13 B                2    4678     0
14 B                2    5966     1
15 B                2    9571     0