[英]deparse(substitute()) with lapply
I want to give labels to data frames using a combination of a small function in combination with lapply()我想使用小型 function 和 lapply() 的组合为数据帧提供标签
I have the following code:我有以下代码:
df1 <- data.frame(c(1,2,3), c(3,4,5))
df2 <- data.frame(c(6,7,8), c(9,10,11))
f.generate.name <- function(x) {
x$name <- deparse(substitute(x))
return(x)
}
my_list <- list(df1, df2)
# This works fine.
f.generate.name(df1)
# This does not work.
lapply(my_list, f.generate.name)
which produces the following output产生以下 output
[[1]]
c.1..2..3. c.3..4..5. name
1 1 3 X[[i]]
2 2 4 X[[i]]
3 3 5 X[[i]]
[[2]]
c.6..7..8. c.9..10..11. name
1 6 9 X[[i]]
2 7 10 X[[i]]
3 8 11 X[[i]]
What I want instead is:我想要的是:
[[1]]
c.1..2..3. c.3..4..5. name
1 1 3 df1
2 2 4 df1
3 3 5 df1
[[2]]
c.6..7..8. c.9..10..11. name
1 6 9 df2
2 7 10 df2
3 8 11 df2
What is the best way of dong this without using loops?不使用循环的最佳方法是什么? How can I tweak the lapply() function or the function that I created in order to achieve the desired result?
我如何调整我创建的 lapply() function 或 function 以获得所需的结果?
lapply()
cannot iterate over more than one argument. lapply()
不能迭代多个参数。 You can use mapply()
or its wrapper Map()
in this case that always returns a list.在这种情况下,您可以使用
mapply()
或其包装器Map()
始终返回一个列表。
Map(f = function(x, y){
x$name <- y
x },
my_list,
names(my_list))
$df1
c.1..2..3. c.3..4..5. name
1 1 3 df1
2 2 4 df1
3 3 5 df1
$df2
c.6..7..8. c.9..10..11. name
1 6 9 df2
2 7 10 df2
3 8 11 df2
In case you are open to a purrr
solution, you can use imap()
.如果您愿意接受
purrr
解决方案,您可以使用imap()
。 It makes the names of the object conveniently available.它使 object 的名称方便地获得。 There is no need to write a function then:
则无需编写 function :
my_list <- list(df1 = df1, df2 = df2)
imap(my_list, ~{
.x$name <- .y
.x
})
$df1
c.1..2..3. c.3..4..5. name
1 1 3 df1
2 2 4 df1
3 3 5 df1
$df2
c.6..7..8. c.9..10..11. name
1 6 9 df2
2 7 10 df2
3 8 11 df2
Really the question is where do the names come from?真正的问题是这些名字是从哪里来的? An unnamed list like
my_list
in the question has lost the df1
and df2
names as we can see by looking at its internals:像问题中的
my_list
这样的未命名列表丢失了df1
和df2
名称,我们可以通过查看其内部结构看到:
dput(my_list) # no df1 or df2 seen
## list(structure(list(c.1..2..3. = c(1, 2, 3), c.3..4..5. = c(3,
## 4, 5)), class = "data.frame", row.names = c(NA, -3L)), structure(list(
## c.6..7..8. = c(6, 7, 8), c.9..10..11. = c(9, 10, 11)), class =
## "data.frame", row.names = c(NA,
## -3L)))
Thus either we need to create a named list in the first place or else provide a vector of names.因此,要么我们首先需要创建一个命名列表,要么提供一个名称向量。 We show both using only base R.
我们仅使用基础 R 来展示两者。
First create a named list of the data frames and then use Map as shown:首先创建数据帧的命名列表,然后使用 Map,如下所示:
L <- mget(ls("^df")) # create named list
Map(data.frame, L, name = names(L))
Alternately if all you have is an unnamed list then we can Map over that and a vector of names:或者,如果您只有一个未命名的列表,那么我们可以 Map 和名称向量:
my_list <- list(df1, df2) # unnamed list as in question
Map(data.frame, my_list, name = c("df1", "df2"))
Yet another approach is to pass the individual data frames instead of a list.另一种方法是传递单个数据帧而不是列表。 Because we have not destroyed the original names by creating an unnamed list we can still retrieve them.
因为我们没有通过创建未命名列表来破坏原始名称,所以我们仍然可以检索它们。 On R 4.0 and later
deparse1
could optionally be used in place of deparse
in the code.在 R 4.0 和更高版本上,可以选择使用
deparse1
代替代码中的deparse
。
add_names <- function(...) {
mc <- match.call()
Map(data.frame, list(...), names = sapply(mc[-1], deparse))
}
add_names(df1, df2)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.