【问题标题】:Add row to data frame with dplyr使用 dplyr 将行添加到数据框
【发布时间】:2016-02-07 13:12:28
【问题描述】:

我有这个样本数据:

cvar <- c("2015-11-01","2015-11-02","All")
nvar1 <- c(12,10,5)
nvar2 <- c(7,5,6)
data <- cbind.data.frame(cvar,nvar1,nvar2)

我只想在 data.frame 中添加一个新行,其中包含 nvar1 和 nvar2 的总和以及一个字符,所以对于基本 R,我只会使用

data[nrow(data)+1,] <- c("add",sum(data[,2]),sum(data[,3]))

或者更聪明的 lapply,但只是为了向你展示我在寻找什么。

我想在管道环境中使用这个简单的命令,所以 data %>% ... 给了我上述结果。

感谢任何帮助,谢谢。

【问题讨论】:

  • 这里有data.table
  • 只要你把它放到管道中,它就会变成一个data.table,不是吗?
  • data.table 是一个不同的包。转换成data.table,应该是data.table(cvar, ....) 如果你使用dplyr,那么试试bindrows
  • 你可能指的是tbl_df
  • 啊好吧,很抱歉我会编辑这个。

标签: r dplyr


【解决方案1】:

那么可能是这样的:

data %>% 
     rbind(c("add",sum(nvar1),sum(nvar2)))
#        cvar nvar1 nvar2
#1 2015-11-01    12     7
#2 2015-11-02    10     5
#3        All     5     6
#4        add    27    18

编辑:

根据您的评论,这将起作用:

data %>% 
  mutate(nvar3 = nvar1) %>% 
  rbind(c("add",sum(nvar1),sum(nvar2),sum(.$nvar3))) 

使用. 将允许rbind 找到nvar3

编辑2:

将新行作为列表提供,它将维护列类:

> str(
+ data %>% 
+   mutate(nvar3 = nvar1) %>% 
+   rbind(list("add",sum(nvar1),sum(nvar2),sum(.$nvar3))) 
+ )
'data.frame':   4 obs. of  4 variables:
 $ cvar : chr  "2015-11-01" "2015-11-02" "All" "add"
 $ nvar1: num  12 10 5 27
 $ nvar2: num  7 5 6 18
 $ nvar3: num  12 10 5 27

【讨论】:

  • 我可以在这里证明“dplyr”的唯一方法是,如果您将第一列转换为“字符”。 data %&gt;% mutate(cvar = as.character(cvar)) %&gt;% rbind(c("add",sum(nvar1),sum(nvar2)))。否则,rbind(data, c("add",sum(nvar1),sum(nvar2))) 也会这样做......
  • 谢谢LyzanderR,它确实解决了上述问题,+1。但是在管道内它对我不起作用说: data %>% mutate(nvar3 = nvar1) %>% rbind(c("add",sum(nvar1),sum(nvar2),sum(nvar3))) ,我需要经过一系列的转换后使用 rbind,在问题中没有提到这一点,对不起..
  • @Sebastian 是的,在您上面描述的情况下,nvar3 无法在 data 中找到,因此出现错误。你应该这样做:data %&gt;% mutate(nvar3 = nvar1) %&gt;% rbind(c("add",sum(nvar1),sum(nvar2),sum(.$nvar3))) 它会起作用。
  • @AnandaMahto 我完全同意。在更复杂的情况下,OP 似乎需要它作为一个步骤。
  • 通过 rbinding 字符向量,您已将结果中的 nvar 转换为 char。
【解决方案2】:

使用tibble 1.2 版,您可以使用add_row()

https://blog.rstudio.org/2016/08/29/tibble-1-2-0/

data %>% 
 add_row(cvar = "add", nvar1 = sum(nvar1), nvar2 = sum(nvar2))

【讨论】:

  • 这是有效的,因为向量是在全局环境中定义的。对列名进行惰性评估会很好。开了一个issue
  • 现在可以很好地处理列名的惰性评估,显然是最tidyverse选项imo!
【解决方案3】:

仅使用 dplyr 您可以执行以下操作

data %<>%
  summarise(cvar = "add",
            nvar1 = sum(nvar1),
            nvar2 = sum(nvar2)) %>%
  bind_rows(data)

导致

        cvar nvar1 nvar2
1        add    27    18
2 2015-11-01    12     7
3 2015-11-02    10     5
4        All     5     6

请注意,这样新行将添加到开头而不是原始数据帧的末尾。

如果您想在末尾添加新行,请使用以下代码(感谢krlmlr for pointing this out

data %<>%
  summarise(cvar = "add",
            nvar1 = sum(nvar1),
            nvar2 = sum(nvar2)) %>%
  bind_rows(data, .)

导致

        cvar nvar1 nvar2
1 2015-11-01    12     7
2 2015-11-02    10     5
3        All     5     6
4        add    27    18

【讨论】:

  • 使用bind_rows(data, .)添加到末尾。
  • @krlmlr 谢谢!我没有意识到在最后添加新行是那么容易。有趣的是,警告消息 In bind_rows_(x, .id) : binding factor and character vector, coercing into character vector 在执行此操作时出现 - 但它不会以相反的方式出现 (bind_rows(., data))。你知道这是为什么吗?
  • 更简单的例子:bind_rows(data_frame(a = "a"), data_frame(a = factor("a"))) vs. bind_rows(data_frame(a = factor("a")), data_frame(a = "a"))。似乎取决于顺序,也许我的第一个示例中没有警告是一个简单的遗漏。仔细检查dplyr NEWS 以确保。
  • 是的,我注意到这取决于订单...但对我来说这种行为似乎不一致,所以我 opened a corresponding issue on GitHub :)
【解决方案4】:

如果有人仍在寻找我会使用的通用解决方案:

cvar <- c("2015-11-01","2015-11-02","All")
nvar1 <- c(12,10,5)
nvar2 <- c(7,5,6)
data <- tibble::tibble(cvar,nvar1,nvar2)

purrr::map_df(data, ~c(.x, ifelse(is.numeric(.x), sum(.x, na.rm=TRUE), NA)))

附:我使用 tibble 来保持字符,因为数据框将它们转换为因子和 base::c “销毁”它们

【讨论】:

    【解决方案5】:

    使用summarise_all()bind_rows() 的一个选项可能是:

    data %>% 
     bind_rows(summarise_all(., ~ if (is.numeric(.)) sum(.) else "add"))
    
            cvar nvar1 nvar2
    1 2015-11-01    12     7
    2 2015-11-02    10     5
    3        All     5     6
    4        add    27    18
    

    或者添加行,然后使用if_else() 仅计算最后一行的总和:

    data %>%
     add_row(cvar = "add") %>%
     mutate_at(-1, ~ if_else(row_number() == max(row_number()), sum(., na.rm = TRUE), .))
    

    或者当变量不在全局环境中时@Rickard 的答案的替代方案:

    data %>% 
     add_row(cvar = "add", nvar1 = sum(data$nvar1), nvar2 = sum(data$nvar2))
    

    【讨论】:

    • 顶!谢谢 会添加使用 sum(., na.rm = T)
    • 还会添加使用括号来防止 RStudio 中出现警告: data %>% bind_rows(summarise_all(., ~ if (is.numeric(.)) {sum(., na.rm = T )} 否则 {"Total"}))
    猜你喜欢
    • 2014-06-20
    • 1970-01-01
    • 2014-03-16
    • 2021-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-15
    相关资源
    最近更新 更多