r - 将具有部分空值的嵌套列表转换为 R data.frame
问题描述
对于单个 data.frames 对象列表,我通常可以轻松转换:
my_df <- do.call("rbind", lapply(my_list, data.frame))
但是,我目前拥有的列表对象是嵌套的。它是 data.frames 列表的列表。需要注意的几点:
- 父列表中的某些子列表的元素为空。
- 在包含信息的子列表中,一些列表具有多个 data.frame 对象。
- 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
方法报告了一个错误arguments imply differing number of rows
,所以看起来我的带有不同行号的 data.frames 的列表导致了这个问题?
我尝试了这篇文章中描述的一些策略,但每次尝试都有其独特的错误。
“ data.table
rbindlist”方法和dplyr
“bind_rows”方法都报告了:
fill=TRUE, but names of input list at position 1 is NULL
感谢您提供有关如何处理这种情况的任何提示。
解决方案
首先,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
s 的列表
在这种情况下,递归可能会有所帮助。考虑以下代码:
# 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)
推荐阅读
- java - Spring AMQP 客户端自动重新连接但不消耗简历
- qt - 如何在 qml 的单个窗口中运行来自不同项目的两个显示?
- python - MySQL查询使Friend of Friend网络运行时间过长
- ios - 如何在应用重新打开时刷新 iOS 主屏幕 PWA
- c# - 短线转换?到时间跨度
- javascript - 在javascript中打开新窗口的问题
- php - BinaryFileResponse 上的会话丢弃安全令牌
- wordpress - Woocommerce Wordpress 如何将搜索词作为动态变量
- python - 这是什么python数组语法
- unity3d - 如何为光设置负偏差值以消除阴影问题?