如何在列表中的列表中添加列而不丢失其名称?

时间:2018-12-10 18:05:03

标签: r list lapply

我做了几次尝试将特定的列添加到数据帧中。列表中的列表,但是所有*apply()次尝试都未能保留数据帧的名称。

例如列表l

l <- list(alpha=data.frame(1:3), bravo=data.frame(4:6), charly=data.frame(7:9))

> l
$`alpha`
  X1.3
1    1
2    2
3    3

$bravo
  X4.6
1    4
2    5
3    6

$charly
  X7.9
1    7
2    8
3    9

我希望列表名称的首字母作为第二id列。我尝试了这些尝试,这些尝试基本上给了我我想要的东西:

lapply(seq_along(l), function(x) cbind(l[[x]], id=substr(names(l)[x], 1, 1)))
# or
lapply(seq_along(l), function(x) data.frame(l[[x]], id=substr(names(l)[x], 1, 1)))
# [[1]]
# X1.3 id
# 1    1  a
# 2    2  a
# 3    3  a
# 
# [[2]]
# X4.6 id
# 1    4  b
# 2    5  b
# 3    6  b
# 
# [[3]]
# X7.9 id
# 1    7  c
# 2    8  c
# 3    9  c

,但内部列表已丢失其名称。 USE.NAMES=TRUE文档中的选项lapply()无法正常工作。

我也尝试了这两次尝试,但失败的情况更糟。

lapply(seq_along(l), function(x) mapply(cbind, l[[x]], id=substr(names(l)[x], 1, 1), 
                                        SIMPLIFY=FALSE))
rapply(l, function(x) cbind(x, id=substr(names(l)[x], 1, 1)), how="list")

我知道我可以这样做:

l1 <- lapply(seq_along(l), function(x) cbind(l[[x]], id=substr(names(l)[x], 1, 1)))
names(l1) <- names(l)

或执行for循环:

for(i in seq_along(l)) {
  l[[i]] <- data.frame(l[[i]], id=substr(names(l)[i], 1, 1))
}

但是我想知道是否可以改进*apply()解决方案以带来预期的输出,这将是:

$`alpha`
  X1.3 id
1    1  a
2    2  a
3    3  a

$bravo
  X4.6 id
1    4  b
2    5  b
3    6  b

$charly
  X7.9 id
1    7  c
2    8  c
3    9  c

3 个答案:

答案 0 :(得分:5)

尝试 writeFile().then((file){ readFile().then((r){ _localPath.then((path){ var uri='file:///'+path+'/index.html'; flutterWebViewPlugin.launch(uri, rect: new Rect.fromLTWH( 0.0, 400.0, MediaQuery.of(context).size.width, 200.0, ), );

Map

第一个参数是一个函数。 Map(`[<-`, l, "id", value = substr(names(l), 1, 1)) #$alpha # X1.3 id #1 1 a #2 2 a #3 3 a #$bravo # X4.6 id #1 4 b #2 5 b #3 6 b #$charly # X7.9 id #1 7 c #2 8 c #3 9 c 然后将功能“应用于每个...自变量的第一个元素,第二个元素,第三个元素,依此类推。”,请参见Map

答案 1 :(得分:2)

sapply上带有simplify = FALSE的名称。

addId <- function(x) cbind(l[[x]], id = substring(x, 1, 1))
sapply(names(l), addId, simplify = FALSE)

给予:

$`alpha`
  X1.3 id
1    1  a
2    2  a
3    3  a

$bravo
  X4.6 id
1    4  b
2    5  b
3    6  b

$charly
  X7.9 id
1    7  c
2    8  c
3    9  c

或者:

replace(l, TRUE, lapply(names(l), addId))

答案 2 :(得分:2)

如果您不介意从purrr::map系列切换到apply系列,则purrr::imap接受2个参数:正在映射的项目,以及正在映射结束。然后,您可以使用相同的cbind调用,但是现在可以轻松访问数据框的名称。

l <- list(alpha=data.frame(1:3), bravo=data.frame(4:6), charly=data.frame(7:9))

purrr::imap(l, function(df, name) cbind(df, id = substr(name, 1, 1)))
#> $alpha
#>   X1.3 id
#> 1    1  a
#> 2    2  a
#> 3    3  a
#> 
#> $bravo
#>   X4.6 id
#> 1    4  b
#> 2    5  b
#> 3    6  b
#> 
#> $charly
#>   X7.9 id
#> 1    7  c
#> 2    8  c
#> 3    9  c

或者,如果您想填写tidyverse,可以在dplyr::mutate内添加带有imap的列。

library(tidyverse)

imap(l, function(df, name) df %>% mutate(id = str_sub(name, 1, 1)))
#> $alpha
#>   X1.3 id
#> 1    1  a
#> 2    2  a
#> 3    3  a
#> 
#> $bravo
#>   X4.6 id
#> 1    4  b
#> 2    5  b
#> 3    6  b
#> 
#> $charly
#>   X7.9 id
#> 1    7  c
#> 2    8  c
#> 3    9  c

如@markus所述,您也可以使用~.公式符号的缩写形式,而不用拼写出您的函数。在这种情况下,purrr::imap的两个参数变为.x(数据帧)和.y(名称)。看起来像:

purrr::imap(l, ~cbind(.x, id = substr(.y, 1, 1)))