首页 文章

dplyr - 使用正则表达式的多列的总和

提问于
浏览
1

对于数据集mtcars2

mtcars2 = mtcars
mtcars2 = mtcars2 %>% mutate(cyl9=cyl, disp9=disp, gear2=gear)

我希望通过使用正则表达式捕获模式来获得一个新列,即多列的总和 .

这是一个解决方案,但这是通过硬编码完成的

select(mtcars2, cyl9) + select(mtcars2, disp9) + select(mtcars2, gear2)

我试过这样的东西,但它给了我一个数字而不是矢量

mtcars2 %>% select(matches("[0-9]")) %>% sum

请仅使用dplyr解决方案,因为我需要稍后将这些函数应用于sql表 .

谢谢!

更新..我需要解决方案来处理sql表,数据设置如下..

mydb <- dbConnect(RSQLite::SQLite(), "")
dbWriteTable(mydb, "mt", mtcars)
mt.sql=tbl(mydb, "mt")
mt.sql = mt.sql %>% mutate(cyl9=cyl, disp9=disp, gear2=gear)

reduce(),rowSums(),rowwise()在sql表上不起作用,我尝试过这些并且它们给我错误 .

我试过了,

mt.sql %>% rowwise()

错误:is.data.frame(data)不为TRUE

mt.sql %>% select(matches("[0-9]")) %>% mutate(sum=rowSums(.))

UseMethod中的错误(“转义”):没有适用于“转义”的方法应用于类“c('tbl_dbi','tbl_sql','tbl_lazy','tbl')的对象”

mt.sql %>% select(matches("[0-9]")) %>% reduce(`+`)

.x .y中的错误:二元运算符的非数字参数

如果我将mt.sql切换到mtcars2,它们都可以工作,所以我想这是一个sql表问题 .

2 回答

  • 1

    考虑到SQL约束阻止使用更简单和优雅的解决方案,如 rowSumsreduce ,我提供了一个更黑客的答案,让我们回到更基本的 new_col = a + b + c + ... + n

    library(dplyr)
    library(stringr)
    
    # get the variable names and form a text equation
    col_eqn <- paste0(str_subset(colnames(mtcars), "[a-z]", collapse = " + ")
    
    # run a normal  mutate function parsing and evaluating the equation
    mtcars %>% mutate(new_col = eval(parse(text = col_eqn)))
    
    # mpg cyl  disp  hp drat    wt  qsec vs am gear carb new_col
    # 1  21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4 328.980
    # 2  21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4 329.795
    # 3  22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1 259.580
    # 4  21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1 426.135
    # 5  18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2 590.310
    # 6  18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1 385.540
    # 7  14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4 656.920
    # 8  24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2 270.980
    # 9  22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2 299.570
    # 10 19.2   6 167.6 123 3.92 3.440 18.30  1  0    4    4 350.460
    
  • 1

    我们可以使用 tidyverse 选项

    library(tidyverse)
    mtcars2 %>%
          select(matches("[0-9]")) %>%
          reduce(`+`) #%>%
          #if needed to create a new column   
          #mutate(mtcars2, newcol = .)
    
    #[1] 170.0 170.0 116.0 267.0 371.0 234.0 371.0 154.7 148.8 177.6 177.6 286.8
    #[13] 286.8 286.8 483.0 471.0 451.0  86.7  83.7  79.1 127.1 329.0 315.0 361.0
    #[25] 411.0  87.0 129.3 104.1 364.0 156.0 314.0 129.0
    

相关问题