【问题标题】:Renaming Variables Dynamically动态重命名变量
【发布时间】:2019-12-04 10:51:22
【问题描述】:

我有一个名为“模式”的文件。根据该文件,我需要重命名其他数据框。例如,TableA 的“Var1”需要重命名为“Col1”。同样,需要将 TableA 的 VarA 重命名为 ColA。简而言之,架构的“FROM”列中列出的所有变量都需要重命名为“To”列。

Schema <- read.table(header = TRUE, text = 
                  'Tables   From    To
                A   Var1    Col1
                A   Var2    Col2
                A   Var3    Col3
                B   VarA    ColA
                B   VarB    ColB
                B   VarC    ColC
                ')


A <- data.frame(Var1 = 1:3,
                  Var2 = 2:4,
                  Var3 = 3:5)

B <- data.frame(VarA = 1:3,
                VarB = 2:4,
                VarC = 3:5)

【问题讨论】:

    标签: r


    【解决方案1】:

    我们可以使用匹配

    lapply(list(A = A, B = B), function(i){
      setNames(i, Schema$To[ match(names(i), Schema$From) ])
     })
    
    # $A
    #   Col1 Col2 Col3
    # 1    1    2    3
    # 2    2    3    4
    # 3    3    4    5
    # 
    # $B
    #   ColA ColB ColC
    # 1    1    2    3
    # 2    2    3    4
    # 3    3    4    5
    

    或者:

    Anew <- setNames(A, Schema$To[ match(names(A), Schema$From) ])
    Bnew <- setNames(B, Schema$To[ match(names(B), Schema$From) ])
    

    list2env:

    list2env(lapply(list(A = A, B = B), function(i){
      setNames(i, Schema$To[ match(names(i), Schema$From) ])
      }), envir = globalenv())
    

    编辑:当没有匹配的 Schema 时,使用保持列名原样:

    list2env(lapply(list(A = A, B = B), function(i){
      # check if there is a match, if not keep name unchaged
      x <- as.character(Schema$To[ match(names(i), Schema$From) ])
      ix <- which(is.na(x))
      x[ ix ] <- names(i)[ ix ]
      # retunr with updated names
      setNames(i, x)
      }), envir = globalenv())
    

    【讨论】:

    • 效果很好。但它返回列表。可以显示给实际的dfs A和B吗?
    • @john 查看编辑,我不想重复代码,因此使用循环 - lapply
    • 这就是我想要的。我需要它在循环中。但是您的解决方案返回列表。反正有没有将它合并到实际的 dfs 中?
    • 谢谢。它工作得很好。唯一的问题 - 如果模式中不存在需要重命名的列名,则变量的名称变为空白。我们可以保持这些变量的名称不变吗?
    • @john 查看编辑,我们只需要添加一个检查是否匹配。
    【解决方案2】:
    • 以下代码可以从Schema 中提取检索表的名称(AB)并执行名称替换任务:
    r <- Map(function(v) function(v) {
      r <- get(v)
      names(r)[names(r) %in% Schema$From] <- as.character(Schema$To[Schema$From %in% names(r)])
      assign(v,r)},
        as.character(unique(Schema$Tables)))
    

    给了

    > r
    $A
      Col1 Col2 Col3
    1    1    2    3
    2    2    3    4
    3    3    4    5
    
    $B
      ColA ColB ColC
    1    1    2    3
    2    2    3    4
    3    3    4    5
    
    • 如果您不想将结果作为列表,您可以执行类似的操作
    list2env(Map(function(v) {
      r <- get(v)
      names(r)[names(r) %in% Schema$From] <- as.character(Schema$To[Schema$From %in% names(r)])
      assign(v,r)},
      as.character(unique(Schema$Tables))),envir = .GlobalEnv)
    

    for (v in as.character(unique(Schema$Tables))) {
      r <- get(v)
      names(r)[names(r) %in% Schema$From] <- as.character(Schema$To[Schema$From %in% names(r)])
      assign(v,r)
    }
    

    那么您将保留您的对象AB

    > A
      Col1 Col2 Col3
    1    1    2    3
    2    2    3    4
    3    3    4    5
    > B
      ColA ColB ColC
    1    1    2    3
    2    2    3    4
    3    3    4    5
    

    【讨论】:

    • 这就是我想要的。但是您的解决方案返回列表。反正有没有将它合并到实际的 dfs 中?
    • @john 在我编辑的解决方案中,您可以看到对象 AB 仍然存在,没有作为输出集成到列表中
    • 谢谢。它工作得很好。唯一的问题 - 如果模式中不存在需要重命名的列名,则变量的名称变为空白。我们可以保持这些变量的名称不变吗?
    • @john 我会尝试修复它
    • @john 我更新了我的解决方案,请问您能否检查问题是否已解决?
    【解决方案3】:
    lut <- setNames(as.character(Schema$To), Schema$From)
    
    setNames(A, lut[names(A)])
    
      Col1 Col2 Col3
    1    1    2    3
    2    2    3    4
    3    3    4    5
    
    setNames(B, lut[names(B)])
    
      ColA ColB ColC
    1    1    2    3
    2    2    3    4
    3    3    4    5
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-20
      • 2011-08-18
      • 2013-03-25
      • 2018-05-06
      • 1970-01-01
      • 2018-09-13
      • 2014-01-18
      • 2012-05-14
      相关资源
      最近更新 更多