【问题标题】:R rowSums for multiple groups of variables using mutate and for loops by prefix of variable namesR rowSums 使用 mutate 和 for 循环的多组变量,通过变量名的前缀
【发布时间】:2021-05-07 01:54:05
【问题描述】:

我有多个按前缀(par___、fri___、gp___ 等)分组在一起的变量,其中有 29 个。

每个变量的值为 0 或 1。我需要做的是对这些组求和(即,partner___1 + partner___2 等),如果 rowSums = 0,则使每个变量 NA。

例如。我的数据如下所示:

par___ par___2 fri___1 fri___2
0 0 1 1
0 1 0 0
0 0 1 0
0 0 0 0

我希望它看起来像这样:

par___ par___2 fri___1 fri___2
NA NA 1 1
0 1 NA NA
NA NA 1 0
NA NA NA NA

我可以这样单独做:

  df<- df%>%
    mutate(rowsum = rowSums(.[grep("par___", names(.))])) %>% 
    mutate_at(grep("par___", names(.)), funs(ifelse(rowsum == 0, NA, .))) %>%
    select(-rowsum) 

我想我可以这样做:

vars <- c('par___', "fri___','gp___')


for (i in vars) {
  df<- df%>%
    # creates a "rowsum" column storing the sum of columns 1:2 
    mutate(rowsum = rowSums(.[grep(i, names(.))])) %>% 
    # applies, to columns 1:2, a function that puts NA when the sum of the rows is 0
    mutate_at(grep(i, names(.)), funs(ifelse(rowsum == 0, NA, .))) %>%
    select(-rowsum) 
    }

没有错误消息,但它不起作用。

另外,我试过 mutate(across()) 而不是 mutate_at() 并得到这个错误:

错误:mutate() 输入 ..1 有问题。 x 无法将列表转换为函数 i 输入..1across(grep(i, names(.)), list(ifelse(rowsum == 0, NA, .)))

而且,我尝试使用 list 而不是 funs 并收到此错误:

rowsum == 0 中的错误: 比较 (1) 仅适用于 atomic 和 list 类型

任何帮助将不胜感激!

谢谢大家。

【问题讨论】:

    标签: r for-loop dplyr prefix


    【解决方案1】:

    tidyverse 选项将是:

    df %>%
      stack() %>%
      group_by(ind) %>%
      group_by(grp = row_number(), grp2 = str_remove(ind, "_.*")) %>%
      mutate(values = values + na_if(all(values==0), 1)) %>%
      pivot_wider(grp, ind, values_from = values)
      
    # A tibble: 4 x 5
    # Groups:   grp [4]
        grp par___1 par___2 fri___1 fri___2
      <int>   <int>   <int>   <int>   <int>
    1     1      NA      NA       1       1
    2     2       0       1      NA      NA
    3     3      NA      NA       1       0
    4     4      NA      NA      NA      NA
    

    另一方面,如果您更喜欢基础 R,那么您可以这样做:

    d <- ave(unlist(df), row(df), sub("_.*", "", names(df))[col(df)], FUN = function(x) x * NA ^ all(x==0))
    array(d, dim(df), dimnames(df))
    
      par___1 par___2 fri___1 fri___2
    1      NA      NA       1       1
    2       0       1      NA      NA
    3      NA      NA       1       0
    4      NA      NA      NA      NA
    

    请注意,最后一个是矩阵,您可以将其转换为数据框。

    【讨论】:

    • 非常感谢。他们都工作!非常感谢。他们甚至可以处理丢失的数据(我还没有,但可能在数据收集结束时)。非常感谢您的帮助!
    【解决方案2】:

    使用split.default 的基本 R 选项:

    do.call(cbind, unname(lapply(split.default(df, 
         sub('(\\w+)_.*', '\\1', names(df))), function(x) {
               x[rowSums(x) == 0, ] <- NA
               x
    })))
    
    #  fri___1 fri___2 par___ par___2
    #1       1       1     NA      NA
    #2      NA      NA      0       1
    #3       1       0     NA      NA
    #4      NA      NA     NA      NA
    

    【讨论】:

    • 非常感谢。这行得通,但我用 NA 尝试了它并得到了一个错误。真的很感谢你的帮助。我还没有丢失数据,但我们还没有完成数据收集,我们可能会在那里得到一些 NA。上述解决方案也有效。非常感谢!!
    • 如果数据中有NAs,则可以使用x[rowSums(x, na.rm = TRUE) == 0, ] &lt;- NA
    • 非常感谢您提供此代码。这正是我想要的!我一直在使用上面的 tidyverse 代码,但由于某种原因,一旦我更新了 R 和 Rstudio,它就不再工作了。我现在正在使用您提供的基本代码,它运行良好。但想知道是否其他人也遇到过同样的问题。
    猜你喜欢
    • 2021-10-21
    • 2019-03-10
    • 1970-01-01
    • 2018-12-07
    • 2018-07-30
    • 1970-01-01
    • 1970-01-01
    • 2019-12-29
    • 1970-01-01
    相关资源
    最近更新 更多