【问题标题】:How to replace columns with respect to column names?如何根据列名替换列?
【发布时间】:2021-08-18 13:00:17
【问题描述】:

让我们考虑两个数据框:

df1 <- data.frame("A" = c(1, 1, 2), 
                  "B" = 2:4,
                  "C" = 3:5,
                  "D" = 1:3)

> df1
  A B C D
1 1 2 3 1
2 1 3 4 2
3 2 4 5 3

df2 <- data.frame("A_log" = log(c(1, 1, 2)),
                  "C_diff" = diff(c(2,4,1,7)),
                  "C_log" = log(3:5))

> df2
       A_log C_diff    C_log
1 0.0000000      2 1.098612
2 0.0000000     -3 1.386294
3 0.6931472      6 1.609438

我想用来自df2 的列替换df1 的列,方法如下-df2 的列名是df1 的转换列名(df2 的列名总是格式为@987654327 @)。 因此,我想将 df1 中的列替换为 df2 中修改了列名的列。例如: 列“A”应替换为 A_log(相同的列名并添加 _log)。现在我们要替换 df1 中的“C”列,因为我们有两列从 df2 中的“C”开始,那么我们将用 df2 中的两列替换 df1 中的一列“C”。我们不替换列"B""D",因为在df2 中没有以这些字母开头的变量

即我想要一个输出:

       Alog B C_diff    C_log D
1 0.0000000 2      2 1.098612 1
2 0.0000000 3     -3 1.386294 2
3 0.6931472 4      6 1.609438 3

我目前的工作

for (i in seq_len(ncol(df1))) {
  # Obtain next column names of df1
  df1.colname <- colnames(df1)[i]
  # Compare patterns of df1.colname with df2 column names and look for similarities.
  which_match <- which(grepl(df1.colname, colnames(df2)))
  if (length(which_match) >= 1) {
    df3 <- cbind(df3, df2[which_match])
  }
  else {
    df3 <- cbind(df3, df1[i])
  }
}

> df3[, -1]
       A_log B C_diff    C_log D
1 0.0000000 2      2 1.098612 1
2 0.0000000 3     -3 1.386294 2
3 0.6931472 4      6 1.609438 3

在我看来,这个解决方案非常好 - 可以肯定它是有效的。它的最大缺点是它使用了循环,在这种情况下可能没有必要。你认为也许还有其他更好的方法可以做到这一点,或者循环是可以避免的?

【问题讨论】:

    标签: r string dataframe loops


    【解决方案1】:

    您可以按原样使用df2,并从df1 中选择df2 中不存在其子集的列。

    cbind(df2, df1[setdiff(names(df1), sub('_.*', '', names(df2)))])
    
    #      A_log C_diff    C_log B D
    #1 0.0000000      2 1.098612 2 1
    #2 0.0000000     -3 1.386294 3 2
    #3 0.6931472      6 1.609438 4 3
    

    sub('_.*', '', names(df2)) 部分可能特定于实际数据集中的列名。在示例中,您拥有的模式是 ColumnNameFromdf1_somethingelse,因此我从列名中删除 _somethingelse,仅保留 df1 中可用的部分,因此它返回。

    sub('_.*', '', names(df2))
    #[1] "A" "C" "C"
    

    【讨论】:

    • 嘿罗纳克!非常感谢您的回答!我对您的解决方案的唯一问题是您以不同的方式排列列。您拥有的第一列是转换的列("A_log", "C_diff", "C_log"),然后是未转换的("B" , "D")。如果你看看我得到的输出,那就是我正在寻找的东西,即变量布局没有改变(仍然 B 在 A 之后)
    • 如果您将来自cbind 的输出存储在result 中。您可以通过result[gtools::mixedsort(names(result))] 获得所需的订单。
    【解决方案2】:

    您可以尝试遍历 df1 的每个 name,使用 grepdf2 中搜索名称,如果找到则返回这些表单 df2 否则为 df1.

    do.call(cbind, lapply(names(df1), function(x) {
      i <- grep(paste0("^", x, "_"), names(df2))
      if(length(i) > 0) df2[i]
      else df1[x]
    }))
    #      A_log B C_diff    C_log D
    #1 0.0000000 2      2 1.098612 1
    #2 0.0000000 3     -3 1.386294 2
    #3 0.6931472 4      6 1.609438 3
    

    【讨论】:

      猜你喜欢
      • 2022-09-30
      • 2021-05-14
      • 1970-01-01
      • 1970-01-01
      • 2021-10-04
      • 1970-01-01
      • 1970-01-01
      • 2020-10-21
      • 2015-12-31
      相关资源
      最近更新 更多