如何围绕列表中的两个 lapply 调用对循环进行矢量化
How to vectorize a loop around two lapply calls over a list
我有一个包含两个元素的列表。第一个元素是一个向量,而第二个元素是一个列表。对于第二个元素,每个项目对应于主列表的第一个元素中的项目。最好看例子:
我有一个列表:
mylist = list(c("w","x","y","z"),
list(
c("a", "b"),
c("c"),
c("a", "c", "b"),
c("d","a","e"))
)
这就是我想要的:
want = list(list("a",c("w","y","z")),
list("b",c("w","y")),
list("c",c("x","y")),
list("d",c("z")),
list("e",c("z"))
)
这就是我正确地暴力破解解决方案的方式:
codes.vec =unique(unlist(list(mylist[[2]])))
new.list=NULL
for(i in 1:5){
new.list[[i]] = list(codes.vec[i],
mylist[[1]][as.logical(unlist(lapply(lapply(mylist[[2]],function(x)
stri_detect_fixed(x,codes.vec[i])),sum)))]
)
}
我如何对其进行矢量化以避免循环?我想不通,但我试图包装另一个 *apply() 函数,但我一直收到关于 FUN.VALUE 的错误。目前我的真实数据需要 15 分钟才能解决这个问题,这是不切实际的。
注意:如果有帮助,我的申请是我拥有人口普查数据并且我知道每个区块组所属的所有 ZCTA5 代码(全部或部分)。我想颠覆这个想法并在每个 ZCTA5 中获取块组。简单地说,我想从知道块组“w”在 ZCTA5“a”和“b”中到让 ZCTA 代码“a”具有块组:“w”、“y”、“z”和 ZCTA5 代码“ b”有块组:“w”和“y”。
感谢所有帮助,谢谢!
编辑:变量命名很差
这是一个使用 Map
的解决方案:
df <- do.call(rbind, Map(expand.grid, mylist[[1]], mylist[[2]]))
lapply(split(df, df$Var2), function(x) as.character(x[[1]]))
#> $a
#> [1] "w" "y" "z"
#>
#> $b
#> [1] "w" "y"
#>
#> $c
#> [1] "x" "y"
#>
#> $d
#> [1] "z"
#>
#> $e
#> [1] "z"
我们可以使用 purrr
中的 transpose
library(stringr)
library(dplyr)
library(tidyr)
library(purrr)
# // transpose the list
purrr::transpose(list) %>%
# // loop over the list elements and do a crossing
map_dfr(~ crossing(!!! .) %>%
# // set the names of the columns
set_names(str_c('a', seq_along(.)))) %>%
# // split the first column by the second
with(., split(a1, a2))
#$a
#[1] "w" "y" "z"
#$b
#[1] "w" "y"
#$c
#[1] "x" "y"
#$d
#[1] "z"
#$e
#[1] "z"
您要查找的是 - 忽略 apply 系列
unstack(stack(setNames(mylist[[2]], mylist[[1]])),ind~values)
$a
[1] "w" "y" "z"
$b
[1] "w" "y"
$c
[1] "x" "y"
$d
[1] "z"
$e
[1] "z"
我有一个包含两个元素的列表。第一个元素是一个向量,而第二个元素是一个列表。对于第二个元素,每个项目对应于主列表的第一个元素中的项目。最好看例子:
我有一个列表:
mylist = list(c("w","x","y","z"),
list(
c("a", "b"),
c("c"),
c("a", "c", "b"),
c("d","a","e"))
)
这就是我想要的:
want = list(list("a",c("w","y","z")),
list("b",c("w","y")),
list("c",c("x","y")),
list("d",c("z")),
list("e",c("z"))
)
这就是我正确地暴力破解解决方案的方式:
codes.vec =unique(unlist(list(mylist[[2]])))
new.list=NULL
for(i in 1:5){
new.list[[i]] = list(codes.vec[i],
mylist[[1]][as.logical(unlist(lapply(lapply(mylist[[2]],function(x)
stri_detect_fixed(x,codes.vec[i])),sum)))]
)
}
我如何对其进行矢量化以避免循环?我想不通,但我试图包装另一个 *apply() 函数,但我一直收到关于 FUN.VALUE 的错误。目前我的真实数据需要 15 分钟才能解决这个问题,这是不切实际的。
注意:如果有帮助,我的申请是我拥有人口普查数据并且我知道每个区块组所属的所有 ZCTA5 代码(全部或部分)。我想颠覆这个想法并在每个 ZCTA5 中获取块组。简单地说,我想从知道块组“w”在 ZCTA5“a”和“b”中到让 ZCTA 代码“a”具有块组:“w”、“y”、“z”和 ZCTA5 代码“ b”有块组:“w”和“y”。
感谢所有帮助,谢谢!
编辑:变量命名很差
这是一个使用 Map
的解决方案:
df <- do.call(rbind, Map(expand.grid, mylist[[1]], mylist[[2]]))
lapply(split(df, df$Var2), function(x) as.character(x[[1]]))
#> $a
#> [1] "w" "y" "z"
#>
#> $b
#> [1] "w" "y"
#>
#> $c
#> [1] "x" "y"
#>
#> $d
#> [1] "z"
#>
#> $e
#> [1] "z"
我们可以使用 purrr
transpose
library(stringr)
library(dplyr)
library(tidyr)
library(purrr)
# // transpose the list
purrr::transpose(list) %>%
# // loop over the list elements and do a crossing
map_dfr(~ crossing(!!! .) %>%
# // set the names of the columns
set_names(str_c('a', seq_along(.)))) %>%
# // split the first column by the second
with(., split(a1, a2))
#$a
#[1] "w" "y" "z"
#$b
#[1] "w" "y"
#$c
#[1] "x" "y"
#$d
#[1] "z"
#$e
#[1] "z"
您要查找的是 - 忽略 apply 系列
unstack(stack(setNames(mylist[[2]], mylist[[1]])),ind~values)
$a
[1] "w" "y" "z"
$b
[1] "w" "y"
$c
[1] "x" "y"
$d
[1] "z"
$e
[1] "z"