【问题标题】:Apply the same function with multiple columns as inputs to multiple columns in R with tidyverse使用 tidyverse 将具有多列的相同函数作为输入应用于 R 中的多列
【发布时间】:2020-12-04 00:26:36
【问题描述】:

例如,我有以下数据框:

df <- data.frame(a1=1,a2=2,a3=3,b1=1,b2=2,b3=3)

我有一个函数:

fn <- function(x,y,z) x^y+(z-x)^(y-x)

我想要以下:

df <- df %>% mutate(a=fn(a1,a2,a3),b=fn(b1,b2,b3))

问题是,我的数据集中有大量三元组,因此将它们一一写出来并不理想。

【问题讨论】:

    标签: r dplyr tidyverse


    【解决方案1】:

    这里是使用的基本 R 选项:

    • split.default + lapply + do.call
    cbind(
      df,
      lapply(
        split.default(df, gsub("\\d+", "", names(df))),
        function(x) do.call(fn, unname(x))
      )
    )
    
    • reshape + lapply + do.call
    cbind(
      df,
      lapply(
        subset(
          reshape(
            setNames(df, gsub("(\\d+)$", "\\.\\1", names(df))),
            direction = "long",
            varying = 1:length(df)
          ),
          select = -c(time, id)
        ),
        function(x) do.call(fn, as.list(x))
      )
    )
    

    输出

      a1 a2 a3 b1 b2 b3 a b
    1  1  2  3  1  2  3 3 3
    

    【讨论】:

      【解决方案2】:

      我会将df 转换为长格式,然后使用lag 创建3 列,然后在它们上应用fn()

      library(tidyverse)
      
      df_long <- df %>% 
        pivot_longer(everything(),
                     names_to = c(".value", "set"),
                     names_pattern = "(.)(.)")
      
      df_longer <- df_long %>% 
        pivot_longer(-c(set),
                     names_to = "key",
                     values_to = "val") %>% 
        arrange(key)
      df_longer
      #> # A tibble: 6 x 3
      #>   set   key     val
      #>   <chr> <chr> <dbl>
      #> 1 1     a         1
      #> 2 2     a         2
      #> 3 3     a         3
      #> 4 1     b         1
      #> 5 2     b         2
      #> 6 3     b         3
      

      lag 然后申请fn(),只保留非NA val_fn

      df_longer <- df_longer %>% 
        group_by(key) %>% 
        mutate(val_lag1 = lag(val, n = 1),
               val_lag2 = lag(val, n = 2)) %>% 
        mutate(val_fn = fn(val_lag2, val_lag1, val)) %>% 
        filter(!is.na(val_fn))
      df_longer
      #> # A tibble: 2 x 6
      #> # Groups:   key [2]
      #>   set   key     val val_lag1 val_lag2 val_fn
      #>   <chr> <chr> <dbl>    <dbl>    <dbl>  <dbl>
      #> 1 3     a         3        2        1      3
      #> 2 3     b         3        2        1      3
      

      reprex package (v0.3.0) 于 2020 年 12 月 3 日创建

      【讨论】:

        【解决方案3】:

        我认为将列组合成单独的组并将函数应用于每一列会更容易/更短。

        library(dplyr)
        library(tidyr)
        
        df %>%
          pivot_longer(cols = everything(), 
                       names_to = '.value', 
                       names_pattern = '([a-z]+)') %>%
          summarise(across(.fns = ~do.call(fn, as.list(.)))) -> result
        result
        
        #     a     b
        #  <dbl> <dbl>
        #1     3     3
        

        如果需要,您可以将result 绑定到您的原始数据集。

        bind_cols(df, result)
        #  a1 a2 a3 b1 b2 b3 a b
        #1  1  2  3  1  2  3 3 3
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-09-03
          • 2021-06-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多