【问题标题】:How to add a row to each group and assign values如何向每个组添加一行并分配值
【发布时间】:2022-01-02 21:26:13
【问题描述】:

我有这个小标题:

library(tibble)
library(dplyr)

df <- tibble(id = c("one", "two", "three"),
             A = c(1,2,3), 
             B = c(4,5,6))

  id        A     B
  <chr> <dbl> <dbl>
1 one       1     4
2 two       2     5
3 three     3     6

我想为每个组添加一行AND使用函数将值分配给新列BUT(这里每个组中的新行应该得到A=4 B = B 列的第一组值 USING first(B)-> 期望输出

id        A     B
<chr> <dbl> <dbl>
1 one       1     4
2 one       4     4
3 three     3     6
4 three     4     6
5 two       2     5
6 two       4     5

到目前为止我已经尝试过:

如果我使用add_row 在未分组的小标题中添加一行 -> 这完美运行

df %>% 
  add_row(A=4, B=4)

  id        A     B
  <chr> <dbl> <dbl>
1 one       1     4
2 two       2     5
3 three     3     6
4 NA        4     4

如果我尝试在分组的 tibble 中使用 add_row -> 这不起作用

df %>% 
  group_by(id) %>%
  add_row(A=4, B=4)

Error: Can't add rows to grouped data frames.
Run `rlang::last_error()` to see where the error occurred.

根据这篇文章Add row in each group using dplyr and add_row(),我们可以使用group_modify -> 这效果很好

df %>% 
  group_by(id) %>% 
  group_modify(~ add_row(A=4, B=4, .x))

  id        A     B
  <chr> <dbl> <dbl>
1 one       1     4
2 one       4     4
3 three     3     6
4 three     4     4
5 two       2     5
6 two       4     4

我想将B 列的第一个值分配给B 列(或者它可以是任何函数min(B)max(B) 等)-> 这不起作用:

df %>% 
  group_by(id) %>% 
  group_modify(~ add_row(A=4, B=first(B), .x))

Error in h(simpleError(msg, call)) : 
  Fehler bei der Auswertung des Argumentes 'x' bei der Methodenauswahl für Funktion 'first': object 'B' not found

【问题讨论】:

  • 你能翻译“Fehler bei der Auswertung des Argumentes 'x' bei der Methodenauswahl für Funktion 'first': object 'B' not found”吗?
  • 类似:在函数first 的方法选择中评估参数“x”时出错;找不到对象B
  • first(.$B) 为我工作。
  • 如果我添加 first(.$B) 我得到 Error in (function (classes, fdef, mtable) : unable to find an inherited method for function ‘first’ for signature ‘"numeric"’
  • group_modify(~ add_row(A=4, B=first(.x$B), .x))group_modify(~ add_row(A=4, B=first(df$B), .x)) 怎么样?

标签: r dplyr tibble


【解决方案1】:
library(tidyverse)

df <- tibble(id = c("one", "two", "three"),
             A = c(1,2,3), 
             B = c(4,5,6))

df %>% 
    group_by(id) %>% 
    summarise(add_row(cur_data(), A = 4, B = first(cur_data()$B)))
#> `summarise()` has grouped output by 'id'. You can override using the `.groups` argument.
#> # A tibble: 6 × 3
#> # Groups:   id [3]
#>   id        A     B
#>   <chr> <dbl> <dbl>
#> 1 one       1     4
#> 2 one       4     4
#> 3 three     3     6
#> 4 three     4     6
#> 5 two       2     5
#> 6 two       4     5

或者

df %>% 
    group_by(id) %>% 
    group_split() %>% 
    map_dfr(~ add_row(.,id = first(.$id),  A = 4, B = first(.$B)))
#> # A tibble: 6 × 3
#>   id        A     B
#>   <chr> <dbl> <dbl>
#> 1 one       1     4
#> 2 one       4     4
#> 3 three     3     6
#> 4 three     4     6
#> 5 two       2     5
#> 6 two       4     5

reprex package (v2.0.1) 于 2022-01-02 创建

【讨论】:

  • @IceCreamToucan 是的! new_data 来自依赖于列表列和 unnest() 的第一次编辑。谢谢。
  • 对我来说非常有趣和新鲜,感谢您分享这一见解!!!
【解决方案2】:

也许这是一个选择

library(dplyr)

df %>% 
  group_by(id) %>%
  summarise( A=c(A,4), B=c(B,first(B)) ) %>% 
  ungroup
`summarise()` has grouped output by 'id'. You can override using the `.groups` argument.
# A tibble: 6 x 3
  id        A     B
  <chr> <dbl> <dbl>
1 one       1     4
2 one       4     4
3 three     3     6
4 three     4     6
5 two       2     5
6 two       4     5

【讨论】:

  • 这真是一个不错的选择,非常感谢!
【解决方案3】:

根据函数group_modify的文档,如果使用公式,则必须使用“..x引用给定组的.tbl的行子集;”这就是您在 add_row 函数中使用 .x 的原因。为了完全一致,您还必须在 first 函数中执行此操作。

df %>% 
  group_by(id) %>% 
  group_modify(~ add_row(A=4, B=first(.x$B), .x))

# A tibble: 6 x 3
# Groups:   id [3]
  id        A     B
  <chr> <dbl> <dbl>
1 one       1     4
2 one       4     4
3 three     3     6
4 three     4     6
5 two       2     5
6 two       4     5

使用first(.$B)first(df$B) 将提供相同的结果。

【讨论】:

  • 太棒了。这样可行。对不起,昨天我以为我做了同样的事情..并且它与您在 cmets 中的回复不起作用(今天我处于不同的设置中......)。现在它很清晰,效果很好。
  • 没问题,我很高兴它能正常工作:)
【解决方案4】:

一个可能的解决方案:

library(tidyverse)

df <- tibble(id = c("one", "two", "three"),
             A = c(1,2,3), 
             B = c(4,5,6))

df %>% 
  group_by(id) %>%
  slice(rep(1,2)) %>% mutate(A = if_else(row_number() > 1, first(df$B), A)) %>% 
  ungroup

#> # A tibble: 6 × 3
#>   id        A     B
#>   <chr> <dbl> <dbl>
#> 1 one       1     4
#> 2 one       4     4
#> 3 three     3     6
#> 4 three     4     6
#> 5 two       2     5
#> 6 two       4     5

【讨论】:

  • 非常感谢这个版本关于如何添加行!
猜你喜欢
  • 1970-01-01
  • 2016-08-13
  • 2018-12-30
  • 2012-10-02
  • 1970-01-01
  • 2017-08-20
  • 1970-01-01
  • 2021-12-17
  • 1970-01-01
相关资源
最近更新 更多