【问题标题】:Rename variables based on values in another dataframe根据另一个数据框中的值重命名变量
【发布时间】:2019-03-18 08:19:09
【问题描述】:

我有两个数据框,DF1 和 DF2:

DF1 <- data.frame(V1 = factor(c("A", "B", "C", "D")),
                 V2 = factor(c("E", "F", "G", "H")),
                 Va3 = factor(c("I", "J", "K", "L")),
                 column = factor(c("M", "N", "O", "P")))

DF2 <- data.frame(N1 = factor(c("x", "V1", "V2", "y", "z", "Va3", "a", "column")),
                  N2 = factor(c("A", "var1", "random", "R", "Q", "nameofcolumn", "S", "varname4")))

我想根据DF2$N2中相应单元格的值更改DF1V1:column)中变量的名称,例如V2 变为 randomcolumn 变为 varname4

通常,如果DF1 中的变量名与DF2 中的单元格值匹配,我会使用colnames(DF1) &lt;- DF2$N2;但在这里我有那些额外的价值。如何正确重命名变量?

【问题讨论】:

    标签: r dataframe


    【解决方案1】:

    在 1.12.0 版(CRAN 2019 年 1 月 13 日)中,setnames() 函数获得了一个新参数 skip_absent 以跳过 old 中不存在的名称。 setnames() 同样适用于 data.framedata.table

    data.table::setnames(DF1, as.character(DF2$N1), as.character(DF2$N2), skip_absent = TRUE)
    DF1
    
      var1 random nameofcolumn varname4
    1    A      E            I        M
    2    B      F            J        N
    3    C      G            K        O
    4    D      H            L        P
    

    或者,使用DF2 中未包含的附加列:

    DF1 <- data.frame(V1 = factor(c("A", "B", "C", "D")),
                      V2 = factor(c("E", "F", "G", "H")),
                      Va3 = factor(c("I", "J", "K", "L")),
                      column = factor(c("M", "N", "O", "P")),
                      other = 1:4)
    data.table::setnames(DF1, as.character(DF2$N1), as.character(DF2$N2), skip_absent = TRUE)
    DF1
    
      var1 random nameofcolumn varname4 other
    1    A      E            I        M     1
    2    B      F            J        N     2
    3    C      G            K        O     3
    4    D      H            L        P     4
    

    【讨论】:

    • 我编写了这个附加参数,这正是实现它的原因——防止setnames 在值不存在时停止。我会在庞大的数据集上运行它,它偶尔会在几分钟后停止运行,因为自动生成的数据帧(我无法控制/先验知识)中不存在值(列名)。我很高兴看到skip_absent 在社区的其他地方被要求和实施。
    【解决方案2】:

    我们可以使用match

    names(DF1)=DF2$N2[match(names(DF1),DF2$N1)]
    DF1
      var1 random nameofcolumn varname4
    1    A      E            I        M
    2    B      F            J        N
    3    C      G            K        O
    4    D      H            L        P
    

    更新

    names(DF1)[which(names(DF1)%in%DF2$N1)]=as.character(DF2$N2[match(names(DF1)[which(names(DF1)%in%DF2$N1)],DF2$N1)])
    DF1
      var1 random nameofcolumn varname4 somethingelse
    1    A      E            I        M             M
    2    B      F            J        N             N
    3    C      G            K        O             O
    4    D      H            L        P             P
    

    【讨论】:

    • 这是一个伟大而优雅的解决方案。它在此示例中完美运行,但它似乎有一个不幸的副作用,即删除较大版本 DF1 中在 DF2$N2 中没有等效项的所有列的名称。
    • @KaC 检查更新,我在 DF1 中添加了一个额外的列,这不在 DF2 中
    【解决方案3】:

    您需要使用。根据您的实际需要,您需要提取值的模式可能会发生变化。现在,我正在提取以(^ 转换为)varname* 开头的“单元格”,表示接下来发生的任何事情。假设变量名的顺序也是正确的。

    注意:基于以varname# 作为列名的问题的第一个版本。

    colnames(DF1) <-  subset(DF2$N2, grepl("^varname*", DF2$N2))
    
    str(DF1)
    # 'data.frame': 4 obs. of  4 variables:
    # $ varnames1: Factor w/ 4 levels "A","B","C","D": 1 2 3 4
    # $ varname2 : Factor w/ 4 levels "E","F","G","H": 1 2 3 4
    # $ varname3 : Factor w/ 4 levels "I","J","K","L": 1 2 3 4
    # $ varname4 : Factor w/ 4 levels "M","N","O","P": 1 2 3 4        
    

    我知道我的模式中存在冗余。刚刚包含了*^,以便为 OP 提供更多洞察力。

    更新以回答已编辑的问题:匹配 N1 中的值以查找 N2 中的列名称:

    您可以根据N1colnames(DF1) 中的值进行子集化:

    subset(DF2, (N1 %in% colnames(DF1)))
    #       N1           N2
    # 2     V1         var1
    # 3     V2       random
    # 6    Va3 nameofcolumn
    # 8 column     varname4
    

    您可以将它们分配为DF1 的列名,如下所示(您也可以尝试$ 运算符):

    colnames(DF1) <- DF2$N2[as.numeric(rownames(subset(DF2, (N1 %in% colnames(DF1)))))]
    

    如果两个数据帧中的排序不同,请查看此线程:Sort one vector based on another

    【讨论】:

    • 谢谢。现在,我知道这是一个不同的问题,但如果没有明确的模式怎么办?有没有办法仅根据 DF2 中的位置将变量名称与行值匹配?
    • 这是完美的。谢谢你。非常感谢。
    猜你喜欢
    • 2018-11-22
    • 1970-01-01
    • 1970-01-01
    • 2021-04-30
    • 2022-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多