【问题标题】:Add row in each group using dplyr and add_row()使用 dplyr 和 add_row() 在每个组中添加行
【发布时间】:2017-09-10 05:25:46
【问题描述】:

如果我向 iris 数据集添加新行:

iris <- as_tibble(iris)

> iris %>% 
    add_row(.before=0)

# A tibble: 151 × 5
    Sepal.Length Sepal.Width Petal.Length Petal.Width Species
          <dbl>       <dbl>        <dbl>       <dbl>   <chr>
1            NA          NA           NA          NA    <NA> <--- Good!
2           5.1         3.5          1.4         0.2  setosa
3           4.9         3.0          1.4         0.2  setosa

它有效。那么,为什么我不能在每个“子集”的顶部添加一个新行:

iris %>% 
 group_by(Species) %>% 
 add_row(.before=0)

Error: is.data.frame(df) is not TRUE

【问题讨论】:

  • 升级您的tibble 版本,该错误消息至少为three months old。 (新的错误消息显示"Cannot add rows to grouped data frames",它回答了您关于它为什么不起作用的问题。)
  • 您可以使用do向每个组添加行:iris %&gt;% group_by(Species) %&gt;% do(add_row(., .before=0))
  • 感谢 JasonWang 和 r2evans。我已经更新了我的包,使用 do() 就可以了。

标签: r dplyr tidyverse tibble


【解决方案1】:

如果你想使用分组操作,你需要 do 就像 JasonWang 在他的评论中描述的那样,因为其他函数像 mutatesummarise 期望结果与分组数据框的行数相同(在你的情况下,50)或一行(例如在总结时)。

您可能知道,通常do 可能会很慢,如果您无法以其他方式获得结果,则应该是最后的手段。您的任务非常简单,因为它只涉及在数据框中添加额外的行,这可以通过简单的索引来完成,例如查看iris[NA, ]的输出。

你想要的本质上是创建一个向量

indices <- c(NA, 1:50, NA, 51:100, NA, 101:150)

(因为第一组在 1 到 50 行,第二组在 51 到 100 行,第三组在 101 到 150 行)。

那么结果就是iris[indices, ]

构建此向量的更通用方法是使用group_indices

indices <- seq(nrow(iris)) %>% 
    split(group_indices(iris, Species)) %>% 
    map(~c(NA, .x)) %>%
    unlist

map 来自purrr,我假设你已经加载了它,因为你已经用tidyverse 标记了它)。

【讨论】:

  • 哇。感谢@konvas 的彻底回答。仅供参考,不,我不知道 do 很慢,并且不知道 purrr/map 的替代方案。这就是为什么如此伟大。现在我知道在哪里寻找这个问题的答案。谢谢
【解决方案2】:

更新的版本将使用group_modify() 而不是do()

iris %>%
  as_tibble() %>%
  group_by(Species) %>% 
  group_modify(~ add_row(.x,.before=0))
#> # A tibble: 153 x 5
#> # Groups:   Species [3]
#>    Species Sepal.Length Sepal.Width Petal.Length Petal.Width
#>    <fct>          <dbl>       <dbl>        <dbl>       <dbl>
#>  1 setosa          NA          NA           NA          NA  
#>  2 setosa           5.1         3.5          1.4         0.2
#>  3 setosa           4.9         3            1.4         0.2

【讨论】:

  • 现在应该使用它,而不是 @JasonWang 在 OP 的 cmets 中提出的 do 调用。 group_modify 在创建新行时保留组名,而 do 不保留,为用户提供分组变量的 NA 值。
【解决方案3】:

稍有不同,也可以这样做:

library(purrr)
library(tibble)

iris %>%
  group_split(Species) %>%
  map_dfr(~ .x %>%
            add_row(.before = 1))

# A tibble: 153 x 5
   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
          <dbl>       <dbl>        <dbl>       <dbl> <fct>  
 1         NA          NA           NA          NA   NA     
 2          5.1         3.5          1.4         0.2 setosa 
 3          4.9         3            1.4         0.2 setosa 
 4          4.7         3.2          1.3         0.2 setosa 
 5          4.6         3.1          1.5         0.2 setosa 
 6          5           3.6          1.4         0.2 setosa 
 7          5.4         3.9          1.7         0.4 setosa 
 8          4.6         3.4          1.4         0.3 setosa 
 9          5           3.4          1.5         0.2 setosa 
10          4.4         2.9          1.4         0.2 setosa 
# ... with 143 more rows

这也可以用于分组数据帧,但是有点冗长:

library(dplyr)

iris %>%
  group_by(Species) %>%
  summarise(Sepal.Length = c(NA, Sepal.Length), 
            Sepal.Width = c(NA, Sepal.Width), 
            Petal.Length = c(NA, Petal.Length),
            Petal.Width = c(NA, Petal.Width), 
            Species = c(NA, Species))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-17
    • 1970-01-01
    • 1970-01-01
    • 2018-05-03
    • 2014-06-20
    • 2018-06-06
    相关资源
    最近更新 更多