【问题标题】:Generate multiple columns at once using mutate in R使用 R 中的 mutate 一次生成多个列
【发布时间】:2022-11-27 01:56:48
【问题描述】:

语境

假设我有一个 df,其中包含多个列(a1a2a3a4b1b2b3b4)。

我想根据现有列生成一些新列 (c1,c2,c3,c4)。

现在,我可以通过一个一个地创建它来做到这一点。


df = data.frame(a1 = 1:2, a2 = 3:4, a3 = 5:6, a4 = 7:8,
                b1 = 1:2, b2 = 3:4, b3 = 5:6, b4 = 7:8)

df %>% 
  mutate(c1 = a1 - b1,
         c2 = a2 - b2,
         c3 = a3 - b3,
         c4 = a4 - b4)

问题

有没有一种方法可以同时生成c1c2c3c4? 也许使用across()

可重现的代码

df = data.frame(a1 = 1:2, a2 = 3:4, a3 = 5:6, a4 = 7:8,
                b1 = 1:2, b2 = 3:4, b3 = 5:6, b4 = 7:8)

df %>% 
  mutate(c1 = a1 - b1,
         c2 = a2 - b2,
         c3 = a3 - b3,
         c4 = a4 - b4)

# Maybe the way like this, though it cannot run correctly
df %>% 
  mutate(paste('c', 1:4) = paste('a', 1:4) - paste('b', 1:4))

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    这是一种使用across的方法

    df <-
      data.frame(
        a1 = 1:2, a2 = 3:4, a3 = 5:6, a4 = 7:8,
        b1 = 1:2, b2 = 1:2, b3 = 5:6, b4 = 1:2
        )
    
    library(stringr)
    library(dplyr)
    
    df %>% 
      mutate(across(
        .cols = starts_with('a'),
        .fns = ~(. - get(str_replace(cur_column(), 'a', 'b'))),
        .names = "{str_replace(.col, 'a', 'c')}")
      )
    
      a1 a2 a3 a4 b1 b2 b3 b4 c1 c2 c3 c4
    1  1  3  5  7  1  1  5  1  0  2  0  6
    2  2  4  6  8  2  2  6  2  0  2  0  6
    

    【讨论】:

      【解决方案2】:

      使用purrr::map

      map_df(setNames(1:4, paste0("c", 1:4)),
             ~ df[[paste0("a", .x)]] - df[[paste0("b", .x)]]) %>% 
        cbind(df, .)
      

      另外的选择:

      map2_df(select(df, matches("a")),
              select(df, matches("b")),
              ~ .x - .y) %>%
        setNames(paste0("c", 1:4)) %>%
        cbind(df, .)
      

      【讨论】:

        【解决方案3】:

        base R 选项将是

        df[paste0("c", 1:4)] <- df[1:4]- df[5:8]
        

        或者在dplyr中,我们可以使用两个across

        library(dplyr)
        library(stringr)
        df <- df %>% 
          mutate(across(starts_with('a'), 
             .names = "{str_replace(.col, 'a', 'c')}") - across(starts_with('b')))
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2022-01-01
          • 1970-01-01
          • 2019-08-17
          • 2022-01-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-01-29
          相关资源
          最近更新 更多