【问题标题】:Switched columns with dplyr rename_if使用 dplyr rename_if 切换列
【发布时间】:2021-01-07 16:36:48
【问题描述】:

尝试使用 dplyr rename_if 和新旧模式列表重命名一些数据框列,一些列名最终在输出中切换。

head(mtcars)
                   mpg cyl disp  hp drat    wt  qsec vs am gear carb
Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
Valiant           18.1   6  225 105 2.76 3.460 20.22  1  0    3    1

lst <- list(Old=c("mpg", "cyl", "disp", "carb", "wt", "gear"), New=c("Miles per Gallon", "Cylinder", "Displacement", "Carburator", "Weight", "Gear"))

mtcars %>% 
rename_if(names(.) %in% lst$Old,
          function(x){
             lst$New[which(lst$Old %in% x)]}) %>% 
head()
                  Miles per Gallon Cylinder Displacement  hp drat Carburator
Mazda RX4                     21.0        6          160 110 3.90      2.620
Mazda RX4 Wag                 21.0        6          160 110 3.90      2.875
Datsun 710                    22.8        4          108  93 3.85      2.320
Hornet 4 Drive                21.4        6          258 110 3.08      3.215
Hornet Sportabout             18.7        8          360 175 3.15      3.440
Valiant                       18.1        6          225 105 2.76      3.460
                   qsec vs am Weight Gear
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

我们可以看到wtCarburator 列已经切换了。

当引用名称列表与数据框列的顺序不同时,如何使用rename_if 重命名列?

编辑 当引用列表包含特定数据框列中不存在的名称时,rename_at(lst$Old, ~lst$New) 的使用不起作用。

例如:

lst <- list(Old=c("mpg", "cyl", "disp", "carb", "wt", "gear", "xtra"), New=c("Miles per Gallon", "Cylinder", "Displacement", "Carburator", "Weight", "Gear", "ExtraCol"))

(请参阅 xtraExtraCol 名称)

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    请尝试使用 rename_at 而不是 rename_if,因为您有要替换的列名称。

    library(dplyr)
    head(mtcars) %>% rename_at(lst$Old, ~lst$New)
    

    但是,_at/_if/_all 变体已被取代,因此请尝试使用rename_with

    head(mtcars) %>% rename_with(~lst$New, lst$Old)
    
    #                  Miles per Gallon Cylinder Displacement  hp drat Weight  qsec vs am Gear Carburator
    #Mazda RX4                     21.0        6          160 110 3.90  2.620 16.46  0  1    4          4
    #Mazda RX4 Wag                 21.0        6          160 110 3.90  2.875 17.02  0  1    4          4
    #Datsun 710                    22.8        4          108  93 3.85  2.320 18.61  1  1    4          1
    #Hornet 4 Drive                21.4        6          258 110 3.08  3.215 19.44  1  0    3          1
    #Hornet Sportabout             18.7        8          360 175 3.15  3.440 17.02  0  0    3          2
    #Valiant                       18.1        6          225 105 2.76  3.460 20.22  1  0    3          1
    

    在基础 R 中,我们可以使用 match 来做到这一点:

    names(mtcars)[match(lst$Old, names(mtcars))] <- lst$New
    

    如果lst 中存在名称中不存在的值,我们可以先过滤它们,然后使用上述方法。

    inds <- lst$Old %in% names(mtcars)
    lst <- lapply(lst, `[`, inds)
    

    【讨论】:

    • 感谢列表仅包含数据框列中存在的名称时效果很好。当列表还包含不在特定数据框中的名称时怎么办(请参阅我的编辑)?
    • @u31889 我们可以过滤lst 以仅保留名称中存在的那些值。使用rename_if 时的问题是您可以选择列,但在重命名时您并不确切知道要重命名哪个列,因此我们需要先过滤它们。查看更新的答案。
    【解决方案2】:

    which() 替换为match() 可以按出现顺序保留索引并解决问题

    mtcars %>% rename_if(names(.) %in% lst$Old, function(x){lst$New[match(x, lst$Old)]})
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-03
      • 1970-01-01
      相关资源
      最近更新 更多