【问题标题】:Complete a data.frame with new values by group [duplicate]按组完成具有新值的data.frame [重复]
【发布时间】:2021-02-06 02:16:20
【问题描述】:

tidyr 包有一个非常有用的complete 函数,它允许我们明确“丢失”行:你将所有相关列传递给函数,它确保所有可能的组合都存在,如果出现则创建新行缺少的组合需要。您还可以为其指定给定列的预期值(即calendar_quarter = 1:4)。

还有nesting(),可以在complete() 中使用对列进行分组,以便仅使用这些列的现有组合。

但是,“中间”案例呢?也就是说,我们想为每个组提供不同的期望值?最好用一个例子来说明这一点:

suppressPackageStartupMessages({
  library(dplyr)
  library(tidyr)
})

df <- tribble(
  ~id, ~year, ~semester,
  1, 2000, 1,
  1, 2001, 1,
  1, 2001, 2,
  
  2, 1999, 1,
  2, 1999, 2,
  2, 2001, 1
)

这里有一个表格,其中包含给定id 相关的年份和学期。但是,我们缺少一些学期(id=1 的 2000S1 和 id=2 的 2000S1、2000S2 和 2001S2)。

首先我们尝试使用nesting(),否则我们会为id=1, year=1999 创建行,而我们不需要:

complete(df, nesting(id, year), semester = 1:2)
#> # A tibble: 8 x 3
#>      id  year semester
#>   <dbl> <dbl>    <dbl>
#> 1     1  2000        1
#> 2     1  2000        2  # new
#> 3     1  2001        1
#> 4     1  2001        2
#> 5     2  1999        1
#> 6     2  1999        2
#> 7     2  2001        1
#> 8     2  2001        2  # new

没关系,为ids 填写一些缺失的学期。但是,它仍然为id=2 隐藏了缺失的 2000 年。这是很自然的,因为我们没有告诉 complete()year 列使用任何额外的值。

那么让我们这样做吧。我们必须抛弃nesting(),然后我们可以告诉complete() 来检查整个已知年份范围的存在:

complete(df, id, year = min(year):max(year), semester = 1:2)
#> # A tibble: 12 x 3
#>       id  year semester
#>    <dbl> <dbl>    <dbl>
#>  1     1  1999        1  # new, unwanted
#>  2     1  1999        2  # new, unwanted
#>  3     1  2000        1
#>  4     1  2000        2  # new
#>  5     1  2001        1
#>  6     1  2001        2
#>  7     2  1999        1
#>  8     2  1999        2
#>  9     2  2000        1  # new
#> 10     2  2000        2  # new
#> 11     2  2001        1
#> 12     2  2001        2  # new

reprex package (v0.3.0) 于 2020 年 10 月 22 日创建

这样更好,显示所有缺失的学期,包括 id=2 的 2000 年。

但是,这样做的代价是还暴露了 id=1 的 1999 年,这是我们不希望的。

那么,有没有一种优雅的方式来获得以下输出?

#> # A tibble: 10 x 3
#>       id  year semester
#>    <dbl> <dbl>    <dbl>
#>  1     1  2000        1
#>  2     1  2000        2  # new
#>  3     1  2001        1
#>  4     1  2001        2
#>  5     2  1999        1
#>  6     2  1999        2
#>  7     2  2000        1  # new
#>  8     2  2000        2  # new
#>  9     2  2001        1
#> 10     2  2001        2  # new

我想出的唯一解决方案是构建另一个表startEndY 来存储每个id 的初始和最后年份,运行complete(df, id, year = min(year):max(year), semester = 1:2),然后在df 和@987654348 之间执行连接@ 删除不需要的结果,但这似乎不优雅且缓慢,因为 complete() 会创建许多不必要的行(尤其是在我的实际用例中)。

【问题讨论】:

    标签: r dataframe tidyr


    【解决方案1】:

    您可以通过completeid 的缺失观察结果:

    library(dplyr)
    
    df %>% group_by(id) %>% tidyr::complete(year = min(year):max(year), semester)
    
    #      id  year semester
    #   <dbl> <dbl>    <dbl>
    # 1     1  2000        1
    # 2     1  2000        2
    # 3     1  2001        1
    # 4     1  2001        2
    # 5     2  1999        1
    # 6     2  1999        2
    # 7     2  2000        1
    # 8     2  2000        2
    # 9     2  2001        1
    #10     2  2001        2
    

    【讨论】:

    • 哦,不知道complete尊重group_by
    猜你喜欢
    • 2013-09-18
    • 1970-01-01
    • 1970-01-01
    • 2021-01-16
    • 2017-06-03
    • 2022-06-23
    • 1970-01-01
    • 2021-09-29
    • 1970-01-01
    相关资源
    最近更新 更多