我想使用一个小函数与lapply()相结合的方式为数据帧添加标签。
我有以下代码:
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)这将产生以下输出
[[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]]我想要的是:
[[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不使用循环的最好方法是什么?如何调整lapply()函数或我创建的函数以获得所需的结果?
发布于 2020-05-29 22:58:15
基数R
lapply()不能迭代多个参数。在这种情况下,您可以使用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 df2Tidyverse
如果您对purrr解决方案持开放态度,则可以使用imap()。它使得对象的名称可以方便地使用。那么就不需要编写函数了:
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发布于 2020-05-29 23:23:52
真正的问题是这些名字是从哪里来的?像问题中的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)))因此,我们需要首先创建一个命名列表,或者提供一个名称向量。我们展示了仅使用碱基R的两种情况。
命名列表
首先创建数据框的命名列表,然后使用Map,如下所示:
L <- mget(ls("^df")) # create named list
Map(data.frame, L, name = names(L))未命名列表
或者,如果你只有一个未命名的列表,那么我们可以映射到这个列表和一个名称向量:
my_list <- list(df1, df2) # unnamed list as in question
Map(data.frame, my_list, name = c("df1", "df2"))传递单个数据帧
另一种方法是传递单独的数据帧而不是列表。因为我们没有通过创建一个未命名列表来销毁原始名称,所以我们仍然可以检索它们。在R4.0和更高版本中,可以选择在代码中使用deparse1来代替deparse。
add_names <- function(...) {
mc <- match.call()
Map(data.frame, list(...), names = sapply(mc[-1], deparse))
}
add_names(df1, df2)https://stackoverflow.com/questions/62088163
复制相似问题