将具有部分空值的嵌套列表转换为R data.frame

时间:2019-03-02 14:49:02

标签: r

对于data.frames对象的单个列表,我通常可以轻松地进行转换:

  list1  list2  list3
  1      x      i
  1      x      j
  1      x      l
  1      y      i
  1      y      j
  1      y      l
  2      x      i
  2      x      j
  2      x      l
  2      y      i
  2      y      j
  2      y      l

但是,我当前拥有的列表对象是嵌套的。它是data.frames列表的列表。需要注意的几点:

  1. 父级列表中某些子级列表的元素为空。
  2. 在带有信息的子列表中,有些列表具有多个data.frame对象。
  3. 子列表中data.frame对象的数量可以变化。

这是我正在处理的事情的简化示例:

my_df <- do.call("rbind", lapply(my_list, data.frame))

上面的List of 3 $ 1 :List of 2 ..$ : NULL ..$ : NULL $ 2 :List of 2 ..$ :'data.frame': 3 obs. of 2 variables: .. ..$ name : chr [1:3] "jack" "jim" "joe" "jon" .. ..$ value : chr [1:3] "10" "12" "13" "14" ..$ :'data.frame': 4 obs. of 2 variables: .. ..$ name : chr [1:4] "jacky" "jane" "juanita" "julia" .. ..$ value : chr [1:4] "11" "9" "10" "14" $ 3 :List of 1 ..$ :'data.frame': 5 obs. of 2 variables: .. ..$ name : chr [1:5] "adam" "ashley" "arnold" "avery" "arthur" .. ..$ value : chr [1:5] "6" "7" "11" "12" "11" 方法报告了一个错误do.call,看来我的具有不同行号的data.frames列表导致了此问题?

我尝试了this post中描述的一些策略,但是每次尝试都有其自己的独特错误。

arguments imply differing number of rows“ rbindlist”方法和data.table“ bind_rows”方法均报告:

dplyr

感谢有关如何处理这种情况的任何提示。

2 个答案:

答案 0 :(得分:0)

考虑两个select l.* from (select l.*, row_number() over (partition by name order by (feature_code = 'RGN') desc, id ) as seqnum from locations l ) l where seqnum = 1; <script> function secondsToHms(d) { d = Number(d); var h = Math.floor(d / 3600); var m = Math.floor(d % 3600 / 60); var s = Math.floor(d % 3600 % 60); var hDisplay = h > 0 ? h + (h == 1 ? " hour, " : " hours, ") : ""; var mDisplay = m > 0 ? m + (m == 1 ? " minute, " : " minutes, ") : ""; var sDisplay = s > 0 ? s + (s == 1 ? " second" : " seconds") : ""; return hDisplay + mDisplay + sDisplay; } function countDown(secs,elem) { var element = document.getElementById(elem); var h=secondsToHms(secs); element.innerHTML = "Time Remaining "+h; if(secs < 1) { clearTimeout(timer); element.innerHTML = '<h2>Your Time is up!</h2>'; element.innerHTML += '<p>Please evacuate the parking space as soon as possible</p><br>'; element.innerHTML += '<a href="Home.php">Return to Home</a>'; } secs--; var timer = setTimeout('countDown('+secs+',"'+elem+'")',1000); } </script> <div id="status"></div> <script>countDown(10,"status");</script> 之间运行:

do.call

答案 1 :(得分:0)

首先,NULL的值无关紧要,因为rbind(NULL, NULL, ..., A, B, C, ...)rbind(A, B, C, ...)相同。

第二,列表的结构很重要。如果嵌套列表与示例一样简单,那么答案也很简单。下面的代码可以解决此问题:

# This list is the same as your example
test <- list(
  list(NULL, NULL),
  list(data.frame(name = c("jack", "jim", "joe", "jon"), 
                  value = c("10", "12", "13", "14")),
       data.frame(name = c("jacky", "jane", "juanita", "julia"), 
                  value = c("11", "9", "10", "14"))),

  list(data.frame(name = c("adam", "ashley", "arnold", "avery", "arthur"),
                  value = c("6", "7", "11", "12", "11")))
)

# This function rbinds the dataframes inside a list
ls_rbind <- function(ls_of_df) do.call(rbind, ls_of_df)
# Applying "ls_rbind" to each of your child lists creates a list, each of whose elements is either a NULL or a dataframe
# Applying "ls_rbind" again to the result list gives you a dataframe you want
result_df <- ls_rbind(lapply(test, ls_rbind))

但是,如果嵌套列表实际上更复杂,那么您可能需要一种更通用的方式来处理它。例如,每个子列表可以是以下项之一:

  • 非列表项,即数据框或NULL
  • 可能还包含列表,数据框或NULL的列表

在这种情况下,递归可能会有所帮助。考虑以下代码:

# These two lines complicate the list structure 
test[[4]] <- test
test[[1]][[3]] <- test

recr_ls_rbind <- function(ls_of_ls) {
  are_lists <- lapply(ls_of_ls, class) == "list"
  # Any child lists will be recursively evaluated. "part1" is always a list
  part1 <- lapply(ls_of_ls[are_lists], recr_ls_rbind)
  # Applying the above function "ls_rbind" to all non-list child items and then coerce the result into a list. 
  part2 <- list(ls_rbind(ls_of_ls[!are_lists]))
  # Put part1 and part2 into the same list and apply "ls_rbind" to it.
  ls_rbind(c(part1, part2))
}
result_df <- recr_ls_rbind(test)