【问题标题】:Best way to bind several columns of a dataframe by row in R [duplicate]在R中逐行绑定数据帧的几列的最佳方法[重复]
【发布时间】:2015-07-24 21:05:45
【问题描述】:

我有一个具有以下形式的数据框

ID1 | VALUE |ID2 | VALUE | ID3 | VALUE
111  | one   |333 | three | 555 | five
222  | two   |    | NA    | 666 | six

请注意,每列中的值/行数会有所不同(NA/空值)。

我希望结果如下所示:

ID  | VALUE 
111 | one
222 | two
333 | three
555 | five
666 | six

我尝试了以下方法:

x = as.matrix(df)
x= matrix(x,ncol = 2)

此过程混合了某些列的 ID 和 VALUE。我的猜测是这是因为 NA 和 NULL 值。

ID  | VALUE 
111 | one
222 | two
333 | three
five| 555
six | 666

您能否建议我的问题的快速解决方案?

优雅的解决方案

感谢nongkrongakrun 的解答。 我不知道速度,但完成工作的最优雅的解决方案如下:

  • my_final = data.frame(VALUE=unlist(my_data[c(TRUE,FALSE)]), ID=unlist(my_data[c(FALSE, TRUE)]))
  • my_final = setNames(data.frame(lapply(split(as.list(my_data), c(F, T)), unlist)), c("VALUE", "ID"))

还要省略空行:

  • my_final_trimmed = my_final[complete.cases(my_final), ]

【问题讨论】:

    标签: r data-manipulation


    【解决方案1】:

    一种选择是使用data.table 的开发版本中的melt。开发版安装说明为here

    我们将“data.frame”转换为“data.table”(setDT(df1))。使用melt,我们用regexpatterns 指定以“ID”和“VALUE”开头的列名的measure 参数。可选参数包括命名“值”列,即value.name,并使用na.rm=TRUE 删除NA 值。如果我们不需要 'variable' 列,可以将其分配 (:=) 为 NULL。

    library(data.table)#v1.9.5+
    melt(setDT(df1), measure= patterns("^ID", "^VALUE"), 
       value.name= c("ID", "VALUE"), na.rm=TRUE)[,variable:=NULL][]
    #   ID VALUE
    #1: 111   one
    #2: 222   two
    #3: 333 three
    #4: 555  five
    #5: 666   six
    

    数据

    df1 <- structure(list(ID1 = c(111L, 222L), VALUE = c("one", "two"), 
    ID2 = c(333L, NA), VALUE.1 = c("three", NA), ID3 = c(555L, 
    666L), VALUE.2 = c("five", "six")), .Names = c("ID1", "VALUE", 
    "ID2", "VALUE.1", "ID3", "VALUE.2"), class = "data.frame",
    row.names = c(NA, -2L))
    

    【讨论】:

      【解决方案2】:

      另一个基础 R,使用 split 分隔交替列

      res <- setNames(
          data.frame(lapply(split(as.list(dat), c(F, T)), unlist))
        , c("VALUE", "ID"))
      
      res[complete.cases(res), ]
      #      VALUE      ID
      # ID11   111  one   
      # ID12   222  two   
      # ID21   333  three 
      # ID31   555    five
      # ID32   666     six
      

      【讨论】:

      • split 是个不错的选择。我在想data.frame(VALUE=unlist(df1[c(TRUE,FALSE)]), ID=unlist(df1[c(FALSE, TRUE)]))
      • @akrun 不错!我也有类似的想法,但我现在只想split
      • 它在我的数据框(超过 500000 行)上完美运行。非常感谢!
      【解决方案3】:

      好吧,对不起,如果这个答案对你的情况来说太具体了,但是以这种形式的数据框,答案是平易近人的(不优雅)如下:

      1) 消除列名

      colnames(dataframe_name) <- NULL
      

      2) 通过子集分割成更小的数据帧

      df1 <- dataframe_name[, 1:2]  # columns 1-2
      df2 <- dataframe_name[, 3:4]  # columns 3-4
      df3 <- dataframe_name[, 5:6]  # columns 5-6
      

      3) 向数据框添加列名

      f <- function(df) {
          colnames(df) <- c('ID', 'VALUE')  # set colnames for df with 2 cols
          return(df)
      } # function to apply to each df
      
      l <- list(df1, df2, df3)
      list_of_frames <- lapply(l, f)  # apply colname function to each
      

      4) 将数据框绑定在一起

      do.call(rbind, list_of_frames)  # call rbind (row bind) on each frame
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-04-17
        • 2021-12-11
        • 2021-07-08
        • 1970-01-01
        • 2013-10-16
        • 1970-01-01
        • 2013-08-23
        • 2016-04-13
        相关资源
        最近更新 更多