可以使用unlist(list, recursive = FALSE)
展开列表列表,如this问题所示。此操作使用默认点(.
)分隔符连接列表名称,这是R中变量命名的标准。一个简单的示例说明了这一点:
# Create example list, l
> l <- list("a" = list("x" = 1, "y" = 2), "b" = list("x" = 3, "y" = 4))
> l
$a
$a$x
[1] 1
$a$y
[1] 2
$b
$b$x
[1] 3
$b$y
[1] 4
# Unlist lists in l
> l.unlisted <- unlist(l, recursive = FALSE)
> l.unlisted
$a.x
[1] 1
$a.y
[1] 2
$b.x
[1] 3
$b.y
[1] 4
尽管有标准命名约定,但我希望名称具有不同的分隔符(_
)。通过使用sub
来查找和替换每个名称中的默认.
分隔符,并在unlist()
中进行了一次连接后,可以通过字符串操作来执行此操作,如下所示:
> names(l.unlisted) <- sub('.', '_', names(l.unlisted), fixed=TRUE)
> l.unlisted
$a_x
[1] 1
$a_y
[1] 2
$b_x
[1] 3
$b_y
[1] 4
虽然这在大多数情况下已经足够,但我认为可以通过更改unlist()
使用的默认分隔符来消除额外的连接步骤。我假设这可以通过使用fix()
添加sep
参数来改变函数的源代码来完成,类似于paste()
中使用的参数。但是,我不知道该怎么做,因为unlist()
是一个内部函数。
有没有办法改变unlist()
中的默认名称连接分隔符,如何做到这一点?
答案 0 :(得分:0)
虽然可以按照akrun的注释中的建议搜索替换点,但这是一种黑客解决方案,如果名称中已经包含点,则不一定有效。这是一个更强大的解决方案。
示例列表:
ex_list = list(
a = c(x1=1, x2=2, x3=3),
b = c(y1=1, y2=2),
c = c(z1=1)
)
看起来像:
> ex_list
$a
x1 x2 x3
1 2 3
$b
y1 y2
1 2
$c
z1
1
常用方法:
> #tries
> unlist(ex_list)
a.x1 a.x2 a.x3 b.y1 b.y2 c.z1
1 2 3 1 2 1
> do.call(what = c, args = ex_list)
a.x1 a.x2 a.x3 b.y1 b.y2 c.z1
1 2 3 1 2 1
> unlist(unname(ex_list))
x1 x2 x3 y1 y2 z1
1 2 3 1 2 1
前两个使用点(.
)分隔符进行连接,第三个不使用前缀(在某些情况下有用)。
一个功能:
#with custom separator
unlist2 = function(x, sep = "_") {
#save top names
top_names = names(x)
x = unname(x)
#flatten
x2 = unlist(x)
#add prefix
#determine how many prefixes to add of each
lengths_top = sapply(x, length)
prefixes = rep(top_names, times = lengths_top)
names(x2) = paste0(prefixes, sep, names(x2))
x2
}
测试:
> #tests
> unlist2(ex_list)
a_x1 a_x2 a_x3 b_y1 b_y2 c_z1
1 2 3 1 2 1
> unlist2(ex_list, sep = "-")
a-x1 a-x2 a-x3 b-y1 b-y2 c-z1
1 2 3 1 2 1
unlist()
基本的R函数调用.Internal
,因此我们不能轻易对其进行修改:
> unlist
function (x, recursive = TRUE, use.names = TRUE)
{
if (.Internal(islistfactor(x, recursive))) {
lv <- unique(.Internal(unlist(lapply(x, levels), recursive,
FALSE)))
nm <- if (use.names)
names(.Internal(unlist(x, recursive, use.names)))
res <- .Internal(unlist(lapply(x, as.character), recursive,
FALSE))
res <- match(res, lv)
structure(res, levels = lv, names = nm, class = "factor")
}
else .Internal(unlist(x, recursive, use.names))
}
<bytecode: 0x558a410998b0>
<environment: namespace:base>
根据.Internal
的文档:
只有真正的R向导甚至应该考虑使用此功能,并且仅 R开发人员可以将其添加到内部函数列表中。