【问题标题】:How do I add a prefix to several variable names using dplyr?如何使用 dplyr 为多个变量名添加前缀?
【发布时间】:2016-02-17 21:42:09
【问题描述】:

我正在尝试为 data.frame 中的每个变量名称添加一个公共前缀。例如,使用mtcars 数据,我可以添加前缀“汽车”。使用以下代码:

> data(mtcars)
> names(mtcars)
 [1] "mpg"  "cyl"  "disp" "hp"   "drat" "wt"   "qsec" "vs"  
 [9] "am"   "gear" "carb"
> names(mtcars) <- paste0("cars.", names(mtcars))
> names(mtcars)
 [1] "cars.mpg"  "cars.cyl"  "cars.disp" "cars.hp"  
 [5] "cars.drat" "cars.wt"   "cars.qsec" "cars.vs"  
 [9] "cars.am"   "cars.gear" "cars.carb"

但是,我想将其作为管道操作的一部分(即使用%&gt;% 串联在一起的一系列函数),使用一些dplyr 语法。似乎renameeverything() 的某种组合应该可以解决问题,但我不知道如何使它起作用。有人有什么想法吗?

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    另一个dplyr解决方案:

    我发现使用dplyr rename_allrename_atrename_if 最简单,它们从v.1.0.4.rename_with 取代...

    尝试重命名所有列名

    mtcars %>% rename_all(function(x){paste0("cars.", x)}) # older dplyr versions
    mtcars %>% rename_with(.cols = everything(), function(x){paste0("cars.", x)}) # v.1.0.4.
    

    试试这个重命名 "some" 列名:

    mtcars %>% rename_at(vars(hp:wt) ,function(x){paste0("cars.", x)}) # older dplyr versions
    mtcars %>% rename_with(.cols = hp:wt, function(x){paste0("cars.", x)}) # v.1.0.4.
    

    【讨论】:

    • 来自 dplyr v1.0.4 文档(“rename_if()、rename_at() 和 rename_all() 已被 rename_with() 取代。匹配的 select 语句已被 select( ) + rename_with()。”
    • 我认为您的论点在您的 rename_with() 示例中,或者至少是第一个:您的 mtcars %&gt;% rename_with(everything(), function(x){paste0("cars.", x)}) 行给我一个错误,但 mtcars %&gt;% rename_with(function(x){paste0("cars.", x)}, everything()) 按预期/描述的方式工作。 (或许功能变了?)
    【解决方案2】:

    最新的解决方案(2020)似乎使用rename_with,在dplyr 1.0.0 及更高版本中可用:

    mtcars %>% rename_with(.fn = ~ paste0("Myprefix_", .x, "_Mypostfix")) -> mtcars.custom
    

    使用.cols = 参数指定变量子集,默认为everything()

    【讨论】:

    • 是哪个包的?请添加文档链接。
    • @slhck 包名在问题标题中...
    • 这并不像其他包的功能建议在这里不常见。特别是,如果您在网络上搜索“rename_with r”,您会在dplyr 的任何结果出现之前从tidytable 获得函数的各种引用。就我而言,我有一个 1.0 之前的版本,所以它不可用。
    【解决方案3】:

    dplyr 现在需要列表并会抛出警告:

    Warning message:
    funs() is soft deprecated as of dplyr 0.8.0
    Please use a list of either functions or lambdas: 
    
      # Simple named list: 
      list(mean = mean, median = median)
    
      # Auto named with `tibble::lst()`: 
      tibble::lst(mean, median)
    
      # Using lambdas
      list(~ mean(., trim = .2), ~ median(., na.rm = TRUE))
    
    

    你可以这样解决这个例子:

    
    dplyr::select_all(mtcars, list(~ paste0("cars.", .)))
    #>                     cars.mpg cars.cyl cars.disp cars.hp cars.drat cars.wt
    #> Mazda RX4               21.0        6     160.0     110      3.90   2.620
    #> Mazda RX4 Wag           21.0        6     160.0     110      3.90   2.875
    #> Datsun 710              22.8        4     108.0      93      3.85   2.320
    #> Hornet 4 Drive          21.4        6     258.0     110      3.08   3.215
    #> Hornet Sportabout       18.7        8     360.0     175      3.15   3.440
    #> Valiant                 18.1        6     225.0     105      2.76   3.460
    #> Duster 360              14.3        8     360.0     245      3.21   3.570
    #> Merc 240D               24.4        4     146.7      62      3.69   3.190
    #> Merc 230                22.8        4     140.8      95      3.92   3.150
    #> Merc 280                19.2        6     167.6     123      3.92   3.440
    #> Merc 280C               17.8        6     167.6     123      3.92   3.440
    #> Merc 450SE              16.4        8     275.8     180      3.07   4.070
    #> Merc 450SL              17.3        8     275.8     180      3.07   3.730
    #> Merc 450SLC             15.2        8     275.8     180      3.07   3.780
    #> Cadillac Fleetwood      10.4        8     472.0     205      2.93   5.250
    #> Lincoln Continental     10.4        8     460.0     215      3.00   5.424
    #> Chrysler Imperial       14.7        8     440.0     230      3.23   5.345
    #> Fiat 128                32.4        4      78.7      66      4.08   2.200
    #> Honda Civic             30.4        4      75.7      52      4.93   1.615
    #> Toyota Corolla          33.9        4      71.1      65      4.22   1.835
    #> Toyota Corona           21.5        4     120.1      97      3.70   2.465
    #> Dodge Challenger        15.5        8     318.0     150      2.76   3.520
    #> AMC Javelin             15.2        8     304.0     150      3.15   3.435
    #> Camaro Z28              13.3        8     350.0     245      3.73   3.840
    #> Pontiac Firebird        19.2        8     400.0     175      3.08   3.845
    #> Fiat X1-9               27.3        4      79.0      66      4.08   1.935
    #> Porsche 914-2           26.0        4     120.3      91      4.43   2.140
    #> Lotus Europa            30.4        4      95.1     113      3.77   1.513
    #> Ford Pantera L          15.8        8     351.0     264      4.22   3.170
    #> Ferrari Dino            19.7        6     145.0     175      3.62   2.770
    #> Maserati Bora           15.0        8     301.0     335      3.54   3.570
    #> Volvo 142E              21.4        4     121.0     109      4.11   2.780
    #>                     cars.qsec cars.vs cars.am cars.gear cars.carb
    #> Mazda RX4               16.46       0       1         4         4
    #> Mazda RX4 Wag           17.02       0       1         4         4
    #> Datsun 710              18.61       1       1         4         1
    #> Hornet 4 Drive          19.44       1       0         3         1
    #> Hornet Sportabout       17.02       0       0         3         2
    #> Valiant                 20.22       1       0         3         1
    #> Duster 360              15.84       0       0         3         4
    #> Merc 240D               20.00       1       0         4         2
    #> Merc 230                22.90       1       0         4         2
    #> Merc 280                18.30       1       0         4         4
    #> Merc 280C               18.90       1       0         4         4
    #> Merc 450SE              17.40       0       0         3         3
    #> Merc 450SL              17.60       0       0         3         3
    #> Merc 450SLC             18.00       0       0         3         3
    #> Cadillac Fleetwood      17.98       0       0         3         4
    #> Lincoln Continental     17.82       0       0         3         4
    #> Chrysler Imperial       17.42       0       0         3         4
    #> Fiat 128                19.47       1       1         4         1
    #> Honda Civic             18.52       1       1         4         2
    #> Toyota Corolla          19.90       1       1         4         1
    #> Toyota Corona           20.01       1       0         3         1
    #> Dodge Challenger        16.87       0       0         3         2
    #> AMC Javelin             17.30       0       0         3         2
    #> Camaro Z28              15.41       0       0         3         4
    #> Pontiac Firebird        17.05       0       0         3         2
    #> Fiat X1-9               18.90       1       1         4         1
    #> Porsche 914-2           16.70       0       1         5         2
    #> Lotus Europa            16.90       1       1         5         2
    #> Ford Pantera L          14.50       0       1         5         4
    #> Ferrari Dino            15.50       0       1         5         6
    #> Maserati Bora           14.60       0       1         5         8
    #> Volvo 142E              18.60       1       1         4         2
    

    reprex package (v0.3.0) 于 2019 年 7 月 31 日创建

    【讨论】:

      【解决方案4】:

      对于未来的读者,dplyr 现在可以使用 select_ifselect_atselect_all 函数执行此操作:

      dplyr::select_all(mtcars, .funs = funs(paste0("cars.", .)))
      

      【讨论】:

      • 在 dplyr 版本 0.7.4 中显示“paste0("cars.", .) 中的错误:对象 '.'未找到”
      • 使用汽车,这行得通。但是,在我的数据中,使用 dplyr 0.7.6(通过 tidyverse 1.2.1 加载)会引发不同的错误:“错误:nm 必须是 NULL 或长度与 x 相同的字符向量。我”我对此感到困惑。
      【解决方案5】:

      确实,你可以使用rename_(NSE rename 本身不起作用):

      data %>% rename_(.dots = setNames(names(.), paste0('cars.', names(.))))
      

      ……但老实说,为什么?直接指定名称更短更易读:

      data %>% setNames(paste0('cars.', names(.)))
      

      【讨论】:

      • 谢谢!实际用例有点复杂——简而言之,我正在将一个数据集与其自身进行一系列合并,我不希望合并左侧的变量与相同的变量混淆合并右侧的名称。 merge 通过分配后缀“.x”和“.y”来分别指代合并的左侧和右侧来解决此问题,但我希望变量具有更具描述性的名称。我还希望避免使用新名称保存中间数据集,因此我努力使用dplyr 命令来做到这一点。
      • setNames(cars, paste0("cars.", names(cars)) 是有效的。再次感谢。
      • @Jake 我的第二个代码示例没有使用中间数据集。但是,是的,还不如使用setNames 而不是`names&lt;-`。
      • 我建议使用 data.table::setnames() 而不是来自 statssetNames() 。如果新旧名称向量的长度不匹配,这样做的好处是会引发错误,这有点节省。
      • @der_grund 如果(像我一样)你没有在其他地方使用这个包,那么仅仅为此加载data.table 会有点矫枉过正。编写具有独立功能的较小包而不是传统的、臃肿的 R 包的另一个理由。
      猜你喜欢
      • 1970-01-01
      • 2018-04-27
      • 2016-03-07
      • 1970-01-01
      • 1970-01-01
      • 2021-06-02
      • 1970-01-01
      • 2012-06-18
      相关资源
      最近更新 更多