【问题标题】:How To Row Combine And Drop Columns In A List of Data Frames Based On Conditions如何根据条件在数据框列表中行合并和删除列
【发布时间】:2019-02-10 04:46:35
【问题描述】:

以下是包含不同数据框的列表示例数据。我想根据以下两个条件从中获取一个数据框。

第一:

  1. 对于列表起始列 1 中的每个数据框,保留与前一列具有完全相同列名的 rbind()ing 列。遇到不同的列名时,删除该列以及所有列,直到最后一列。
  2. 例如:如果第 1 列命名为 Banana,则第 2 列命名为 Banana,但第 3 列命名为 Orange,然后第 4 列又命名为 Banana。然后第 1 列和第 2 列将 rbind() 并删除第 3 列和第 4 列。
  3. 另一个例子:如果第 1 列被命名为 Banana,那么第 2 列被命名为 Orange,但第 3 列被命名为 Banana,那么只有第 1 列将作为起始第 2 列存在,列名称不同,我不'不关心第 3 列的名称,即使它与第 1 列相同。

第二:

  1. 通过上述条件运行数据框列表后,我想将列表中的所有数据框组合起来得到一个我认为可以使用以下代码实现的数据框。
  2. 这里,lst2 是第一个条件的输出。
do.call(rowr::cbind.fill, c(lst2, list(fill = 0)))

以上代码信用@akrun。任何建议都会有所帮助。

样本数据

list(A = structure(list(`A-DIODE` = c(1.2, 0.4), `A-DIODE` = c(1.3, 
0.6)), row.names = c(NA, -2L), class = "data.frame"), B = structure(list(
    `B-DIODE` = c(1.4, 0.8), `B-ACC1` = c(1.5, 1), `B-ACC2` = c(1.6, 
    1.2), `B-ANA0` = c(1.7, 1.4), `B-ANA1` = c(1.8, 1.6), `B-BRICKID` = c(1.9, 
    1.8), `B-CC0` = c(2L, 2L), `B-CC1` = c(2.1, 2.2), `B-DIGDN` = c(2.2, 
    2.4), `B-DIGDP` = c(2.3, 2.6), `B-DN1` = c(2.4, 2.8), `B-DN2` = c(2.5, 
    3), `B-DP1` = c(2.6, 3.2), `B-DP2` = c(2.7, 3.4), `B-SCL` = c(2.8, 
    3.6), `B-SDA` = c(2.9, 3.8), `B-USB0DN` = 3:4, `B-USB0DP` = c(3.1, 
    4.2), `B-USB1DN` = c(3.2, 4.4), `B-USB1DP` = c(3.3, 4.6), 
    `B-ACC1` = c(3.4, 4.8), `B-ACC2` = c(3.5, 5), `B-ANA0` = c(3.6, 
    5.2), `B-ANA1` = c(3.7, 5.4), `B-BRICKID` = c(3.8, 5.6), 
    `B-CC0` = c(3.9, 5.8), `B-CC1` = c(4L, 6L), `B-DIGDN` = c(4.1, 
    6.2), `B-DIGDP` = c(4.2, 6.4), `B-DN1` = c(4.3, 6.6), `B-DN2` = c(4.4, 
    6.8), `B-DP1` = c(4.5, 7), `B-DP2` = c(4.6, 7.2), `B-SCL` = c(4.7, 
    7.4), `B-SDA` = c(4.8, 7.6), `B-USB0DN` = c(4.9, 7.8), `B-USB0DP` = c(5L, 
    8L), `B-USB1DN` = c(5.1, 8.2), `B-USB1DP` = c(5.2, 8.4), 
    `B-NA` = c(5.3, 8.6), `B-ACC2PWRLKG_0v4` = c(5.4, 8.8), `B-ACC2PWRLKG_0v4` = c(5.5, 
    9), `B-P_IN_Leak` = c(5.6, 9.2)), row.names = c(NA, -2L), class = "data.frame"))

更新 1

@ØysteinS回答后我意识到应该还有第三个条件:

第三:

  • 如果列表中的一个数据框中只有一列,则仅将该列添加到父数据框。

【问题讨论】:

    标签: r dataframe


    【解决方案1】:

    这应该可以完成工作:

    data <- list(A = structure(list(`A-DIODE` = c(1.2, 0.4), `A-DIODE` = c(1.3, 
    0.6)), row.names = c(NA, -2L), class = "data.frame"), B = structure(list(
        `B-DIODE` = c(1.4, 0.8), `B-ACC1` = c(1.5, 1), `B-ACC2` = c(1.6, 
        1.2), `B-ANA0` = c(1.7, 1.4), `B-ANA1` = c(1.8, 1.6), `B-BRICKID` = c(1.9, 
        1.8), `B-CC0` = c(2L, 2L), `B-CC1` = c(2.1, 2.2), `B-DIGDN` = c(2.2, 
        2.4), `B-DIGDP` = c(2.3, 2.6), `B-DN1` = c(2.4, 2.8), `B-DN2` = c(2.5, 
        3), `B-DP1` = c(2.6, 3.2), `B-DP2` = c(2.7, 3.4), `B-SCL` = c(2.8, 
        3.6), `B-SDA` = c(2.9, 3.8), `B-USB0DN` = 3:4, `B-USB0DP` = c(3.1, 
        4.2), `B-USB1DN` = c(3.2, 4.4), `B-USB1DP` = c(3.3, 4.6), 
        `B-ACC1` = c(3.4, 4.8), `B-ACC2` = c(3.5, 5), `B-ANA0` = c(3.6, 
        5.2), `B-ANA1` = c(3.7, 5.4), `B-BRICKID` = c(3.8, 5.6), 
        `B-CC0` = c(3.9, 5.8), `B-CC1` = c(4L, 6L), `B-DIGDN` = c(4.1, 
        6.2), `B-DIGDP` = c(4.2, 6.4), `B-DN1` = c(4.3, 6.6), `B-DN2` = c(4.4, 
        6.8), `B-DP1` = c(4.5, 7), `B-DP2` = c(4.6, 7.2), `B-SCL` = c(4.7, 
        7.4), `B-SDA` = c(4.8, 7.6), `B-USB0DN` = c(4.9, 7.8), `B-USB0DP` = c(5L, 
        8L), `B-USB1DN` = c(5.1, 8.2), `B-USB1DP` = c(5.2, 8.4), 
        `B-NA` = c(5.3, 8.6), `B-ACC2PWRLKG_0v4` = c(5.4, 8.8), `B-ACC2PWRLKG_0v4` = c(5.5, 
        9), `B-P_IN_Leak` = c(5.6, 9.2)), row.names = c(NA, -2L), class = "data.frame"))
    
    # Use lapply to apply the same function to each data frame in the list.
    combined_frames <- lapply(data, function(df){
      first_name <- names(df)[[1]]
      result <- df[, 1, drop = FALSE]
      # Keep adding if name is the same as the first
      if (ncol(df) != 1) {
       for(i in seq(2, length(names(df)), by = 1)){
         if(names(df)[[i]] == names(df)[[1]]){
           result <- rbind(result, df[, i, drop = FALSE])
         } else { 
           # Otherwise, break out of loop
           break
         }
       }
      }
      return(result)
    })
    
    # Yes, your suggested code seems to work as expected for the last task
    do.call(rowr::cbind.fill, c(combined_frames, list(fill = 0)))
    #>   A.DIODE B.DIODE
    #> 1     1.2     1.4
    #> 2     0.4     0.8
    #> 3     1.3     0.0
    #> 4     0.6     0.0
    

    【讨论】:

    • .@ØysteinS - 谢谢。如果列表中的数据框只有单列,您的代码会起作用吗?对于样本数据,我从数据框data$A 中删除了第二列,它给了我错误Error in seq.default(2, length(names(df)), by = 1) : wrong sign in 'by' argument
    • .@ØysteinS - 我认为在result &lt;- df[ , 1, drop = FALSE] 之后,需要一个if else 来检查ncol(),并且只有在ncol() 大于1 时才执行后面的部分。你同意吗?
    【解决方案2】:

    一个简单的选择是遍历list,获取列名的运行长度ID,只提取等于1的那些,unlist,使用第一个列名转换为data.frame,然后然后用cbind.fill将data.frame的list绑定在一起

    library(data.table)
    lst1 <- lapply(data, function(x) 
           setNames(data.frame(unlist(x[rleid(names(x)) == 1])), names(x)[1]))
    do.call(rowr::cbind.fill, c(lst1, list(fill = 0)))
    #    A.DIODE B.DIODE
    #1     1.2     1.4
    #2     0.4     0.8
    #3     1.3     0.0
    #4     0.6     0.0
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-15
      • 1970-01-01
      • 2022-08-02
      • 2016-04-26
      • 2017-05-09
      相关资源
      最近更新 更多