【问题标题】:Rowsums conditional on column name以列名为条件的行和
【发布时间】:2017-04-20 09:45:40
【问题描述】:

我的 data.frage 看起来像这样:

   VAR1 VAR2 AUS1 AUS2 AUS3 AUS4 ... AUS56 VAR3 VAR4
   A    D    23   234  34   856  ... 99    0    FCK
   B    D    55   76   55   36   ... 6456  0    XYC

我希望 R 添加一个新变量 AUS,它显示变量 AUS1AUS56 的行和,最好使用 dplyr。然后可以删除AUS1AUS56

【问题讨论】:

  • 考虑对数据使用整洁的“长”格式,其中AUS 是一列,后面的数字是另一列。然后,您将轻松地与最传统的 dplyr 动词(如 group_bysummarise)进行聚合。

标签: r dplyr rowsum


【解决方案1】:

您可以尝试将rowSumsgrep 结合使用:

df %>% mutate(AUS_sum = rowSums(.[grep("AUS", names(.))]))

【讨论】:

  • 我想知道这是否可以使用dplyr::select_if? 而不是grep 来完成。
  • 这确实有效。但是有什么办法可以同时删除旧变量呢? Transmute 删除了所有剩余的变量,但我只想摆脱那些用于进行计算的变量。
【解决方案2】:

这是另一个使用tidyverse 语法的选项

library(tidyverse)
df1 %>% 
     select(matches("AUS")) %>% 
     reduce(`+`) %>%
     mutate(df1, AUS_sum = .)
#   VAR1 VAR2 AUS1 AUS2 AUS3 AUS4 AUS56 VAR3 VAR4 AUS_sum
#1    A    D   23  234   34  856    99    0  FCK    1246
#2    B    D   55   76   55   36  6456    0  XYC    6678

使用dplyr 的开发版(即将发布0.6.0),我们可以使用quosures 创建一个函数并使其更具动态性。在这里,enquobase R 中的substitute 执行类似的功能,方法是获取输入参数并将其转换为quosure,使用quo_name,我们将其转换为字符串,其中matches 接受字符串参数。 lhs 名称也可以创建为字符串('newN'),在mutate/summarise/group_by 中,我们取消引用(!!UQ)来评估字符串

fSum <- function(dat, pat){
  pat <- quo_name(enquo(pat))
  newN <- paste0(pat, "_sum")
  newSum <- dat %>%
            select(matches(pat)) %>%
            reduce(`+`)
  dat %>%
      mutate(!!newN :=  newSum)
}

fSum(df1, AUS)
#    VAR1 VAR2 AUS1 AUS2 AUS3 AUS4 AUS56 VAR3 VAR4 AUS_sum
#1    A    D   23  234   34  856    99    0  FCK    1246
#2    B    D   55   76   55   36  6456    0  XYC    6678

根据 OP 对另一篇关于删除用于sum 的列的评论,我们可以修改函数

fSumN <- function(dat, pat){
  pat <- quo_name(enquo(pat))
  newN <- paste0(pat, "_sum")
  newSum <- dat %>%
            select(matches(pat)) %>%
            reduce(`+`)
  dat %>%
       select(-matches(pat)) %>%
       mutate(!!newN :=  newSum)
}

fSumN(df1, AUS)
#     VAR1 VAR2 VAR3 VAR4 AUS_sum
#1    A    D    0  FCK    1246
#2    B    D    0  XYC    6678

数据

df1 <- structure(list(VAR1 = c("A", "B"), VAR2 = c("D", "D"), AUS1 = c(23L, 
55L), AUS2 = c(234L, 76L), AUS3 = c(34L, 55L), AUS4 = c(856L, 
36L), AUS56 = c(99L, 6456L), VAR3 = c(0L, 0L), VAR4 = c("FCK", 
"XYC")), .Names = c("VAR1", "VAR2", "AUS1", "AUS2", "AUS3", "AUS4", 
 "AUS56", "VAR3", "VAR4"), class = "data.frame", row.names = c(NA, 
-2L))

【讨论】:

  • 不错。你也可以在select之后做mutate(sum1 = rowSums(.))
  • 第一个给我一个错误信息:Error in function_list[[i]](value) : could not find function "reduce"。第二个,老实说,对于这么简单的操作来说,看起来相当复杂。
  • @Laubsauger 如果您加载了tidyverse,则应该加载library(purrr)。该功能来自该软件包。第二个是使用非标准评估,与使用interp 之类的早期版本相比,它更简单。函数具有多次使用多种模式的优势
  • @Laubsauger 也更新为get rid of those that have been used to make the calculation
  • 如果您有新问题,您可以发布一个问题,而不是用新的要求更新当前问题。 @Laubsauger
【解决方案3】:

在基础 R 中:

df$AUS <- rowSums(df[,grep('AUS', names(df))])

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多