代码之家  ›  专栏  ›  技术社区  ›  Raquel Feltrin

删除数据帧中复制的列

  •  1
  • Raquel Feltrin  · 技术社区  · 2 年前

    我有一个包含重复变量的大数据框。这只是我的数据样本,用来说明这个问题:

    df <- data.frame(
      ID = rep(1:4, each = 1),
      CMW = rep(c(10, 20, 30, 30), each = 1),
      D_D = c(rep(100, 3), 200), 
      D_D = c(rep(100, 3), 200),
      D_D = c(rep(100, 1), 200),
      Eref = rep(4:4, each = 1),
      Eref = rep(4:4, each = 1),
      Eref = rep(1:4, each = 1),
      Eref = rep(1:4, each = 1)
    )
    
    
      ID CMW  DD DD.1 DD.2 Eref Eref.1 Eref.2 Eref.3
       1  10 100  100  100    4      4      1      1
       2  20 100  100  200    4      4      2      2
       3  30 100  100  100    4      4      3      3
       4  30 200  200  200    4      4      4      4
    

    R会在变量名中添加数字以使其唯一,但具有相同“根名称”(点前的字符串)的变量实际上是相同的。所以我想做的是,如果变量重复,看看特定变量中的值,如果值相同,只保留该变量的一列。但是,如果有两组相同的变量是相同的,则保留每组中的一列。所以我想对数据帧中所有重复的变量进行处理。例如,从上面的数据帧示例(df)中,我希望得到以下结果:

      ID CMW  DD DD.1 Eref Eref.1
       1  10 100  100    4      1
       2  20 100  200    4      2
       3  30 100  100    4      3
       4  30 200  200    4      4
    

    到目前为止,我能够用以下代码检查数据帧中是否有重复的变量:

    duplicated_col <- unique(sub("\\.\\d+$", "", names(df))[duplicated(sub("\\.\\d+$", "", names(df)))])
    

    但我不知道如何比较重复的变量并丢弃/保持以获得df_result。欢迎任何帮助。非常感谢。

    3 回复  |  直到 2 年前
        1
  •  2
  •   LMc    2 年前

    这是一个基本的R解决方案:

    df |> 
      split.default(gsub("\\.\\d+$", "", names(df))) |>
      lapply(\(x) {
        l <- as.list(x)
        distinct <- unique(l)
        setNames(distinct, names(l)[seq_along(distinct)])
      }) |>
      unname() |>
      data.frame()
    #   CMW D_D D_D.1 Eref Eref.1 ID
    # 1  10 100   100    4      1  1
    # 2  20 100   200    4      2  2
    # 3  30 100   100    4      3  3
    # 4  30 200   200    4      4  4
    
        2
  •  1
  •   Onyambu    2 年前
    split.default(df, sub(".\\d+$", "", names(df))) |>
      lapply(\(x)unique(as.matrix(unname(x)), MARGIN = 2)) |>
      data.frame()
    
      CMW D_D.1 D_D.2 Eref.1 Eref.2 ID
    1  10   100   100      4      1  1
    2  20   100   200      4      2  2
    3  30   100   100      4      3  3
    4  30   200   200      4      4  4
    

    如果你想保持外观的秩序。添加另一个管道:

    fn <- function(x,d) x[order(match(names(x), names(d)))]
    
    split.default(df, sub(".\\d+$", "", names(df))) |>
       lapply(\(x)unique(as.matrix(unname(x)), MARGIN = 2)) |>
       data.frame() |> fn(df)
    
      ID CMW D_D.1 D_D.2 Eref.1 Eref.2
    1  1  10   100   100      4      1
    2  2  20   100   200      4      2
    3  3  30   100   100      4      3
    4  4  30   200   200      4      4
    
        3
  •  1
  •   zx8754    2 年前

    转置并检查是否重复:

    df[, c("ID", names(df[, -1])[ !duplicated(t(df[, -1 ]))]) ]
    #   ID CMW D_D D_D.2 Eref Eref.2
    # 1  1  10 100   100    4      1
    # 2  2  20 100   200    4      2
    # 3  3  30 100   100    4      3
    # 4  4  30 200   200    4      4
    

    注意,我将ID从转置步骤中排除,因为它与Eref.2和Eref.3具有相同的值。如果您的ID与其他列上的值不相同,则代码看起来更简单:

    df[, names(df)[ !duplicated(t(df)) ] ]