对整数矩阵的列表列进行子集化
subsetting a list column of integer matrices
背景
我遇到了这样一种情况,即 tibble/dataframe 中的一列由整数矩阵列表组成,这些矩阵具有零行或多行且恰好有 2 列。此列恰好是 stringr::str_locate_all()
调用的输出,因此我认为这是一种常见情况。
我想做的是 select 仅 select 整数矩阵的一列,然后取消嵌套数据框,但我对如何正确执行此操作感到困惑。
例子
这是一个示例(我必须手动创建它,因为 dpasta()
似乎不适用于列表列 tibbles)。无论如何,我的出发点是 mydf:
library(tidyverse)
m1 <- matrix( c(761,784), nrow=1,ncol=2, dimnames = list(c(),c("start","end")) )
m2 <- matrix( integer(0), nrow=0,ncol=2, dimnames = list(c(),c("start","end")) )
m3 <- matrix( c(1001,2300,1010,2310), nrow=2,ncol=2, dimnames = list(c(),c("start","end")) )
mydf <- tibble( item = c("a","b","c"), pos = list(m1,m2,m3))
下面是在 rstudio 查看器中的样子。 这有点误导,因为它暗示 pos 行只是整数向量。它们实际上是 nx2 矩阵,没有任何迹象表明它更复杂。这让我有些困惑,但那不是重点。
我想做的是以第 1 列“开始”为 select 的未嵌套小标题结束。所需的输出将如下所示(取消嵌套后):
mydf_desired <- tibble( item = c("a","c","c"), start_pos = c(761,1001,2300))
请注意,mydf 中的第一行在其 pos 矩阵中只有一行,因此它在所需结果中只有一行。带有 item="b" 的行有一个 0x2 矩阵,所以它没有出现(但如果它也显示为 NA 就没问题了)。 item="c" 的行在 pos 矩阵中有两行,因此它在所需结果中有两行。
我试过的
这看起来很简单,我以前没有嵌套列表列。这里唯一的转折是我必须首先 select “开始”列然后取消嵌套,对吗?我只是 map
pos 列表列到 [1] 来选择第一列(“开始”列)。然后应该是取消嵌套的问题了...
mydf_desired <- mydf %>%
mutate(start_pos = map(pos, ~ .[,1])) %>%
unnest()
#> Error in vec_rbind(!!!x, .ptype = ptype): Internal error in `vec_assign()`: `value` should have been recycled to fit `x`.
#> Warning: `cols` is now required.
#> Please use `cols = c(pos, start_pos)`
不知道“value should have been recycled to fit x
”到底是什么意思,但它也警告我不要在 unnest()
中给出 cols。现在怀疑是关于我给出的东西 unnest()
.
如果我省略 unnest()
我不会得到那个错误...
mydf_desired <- mydf %>%
mutate(start_pos = map(pos, ~ .[,1]))
输出看起来像这样...
看起来不错,我注意到 integer(0)
的 item=b 仍然有一个 pos 条目。但即使我省略了那一行,当我尝试 unnest()
.
时也会出现同样的错误
这就是我难倒的地方。为什么我不能 unnest()
这个标题? value should have been recycled to fit x
错误是什么意思?
一个选项是 filter
行,然后 map
在 list
元素上并从 matrix
中提取列,然后使用 unnest_longer
library(dplyr)
library(purrr)
mydf %>%
filter(lengths(pos) > 0) %>%
transmute(item, start_pos = map(pos, ~ as.vector(.x[,1]))) %>%
unnest_longer(c(start_pos))
# A tibble: 3 x 2
# item start_pos
# <chr> <dbl>
#1 a 761
#2 c 1001
#3 c 2300
另外,可以避免filter
这一步,如果我们转换成tibble
mydf %>%
transmute(item, pos = map(pos, ~ .x[,1] %>%
tibble(start_pos = .))) %>%
unnest(c(pos))
错误出现是因为 unnest
试图取消嵌套 pos
列。您可以明确指定要 unnest
的列以避免错误。
library(dplyr)
library(purrr)
mydf %>% mutate(start_pos = map(pos, ~.[, 1])) %>% unnest(start_pos)
# A tibble: 3 x 3
# item pos start_pos
# <chr> <list> <dbl>
#1 a <dbl[,2] [1 × 2]> 761
#2 c <dbl[,2] [2 × 2]> 1001
#3 c <dbl[,2] [2 × 2]> 2300
如果您想要 NA
用于 "b"
项,您可以使用 unnest_longer
mydf %>%
mutate(start_pos = map(pos, ~.[, 1])) %>%
unnest_longer(start_pos, indices_include = FALSE)
# A tibble: 4 x 3
# item pos start_pos
# <chr> <list> <dbl>
#1 a <dbl[,2] [1 × 2]> 761
#2 b <int[,2] [0 × 2]> NA
#3 c <dbl[,2] [2 × 2]> 1001
#4 c <dbl[,2] [2 × 2]> 2300
或 unnest
与 keep_empty = TRUE
。
mydf %>%
mutate(start_pos = map(pos, ~.[, 1])) %>%
unnest(start_pos, keep_empty = TRUE)
背景
我遇到了这样一种情况,即 tibble/dataframe 中的一列由整数矩阵列表组成,这些矩阵具有零行或多行且恰好有 2 列。此列恰好是 stringr::str_locate_all()
调用的输出,因此我认为这是一种常见情况。
我想做的是 select 仅 select 整数矩阵的一列,然后取消嵌套数据框,但我对如何正确执行此操作感到困惑。
例子
这是一个示例(我必须手动创建它,因为 dpasta()
似乎不适用于列表列 tibbles)。无论如何,我的出发点是 mydf:
library(tidyverse)
m1 <- matrix( c(761,784), nrow=1,ncol=2, dimnames = list(c(),c("start","end")) )
m2 <- matrix( integer(0), nrow=0,ncol=2, dimnames = list(c(),c("start","end")) )
m3 <- matrix( c(1001,2300,1010,2310), nrow=2,ncol=2, dimnames = list(c(),c("start","end")) )
mydf <- tibble( item = c("a","b","c"), pos = list(m1,m2,m3))
下面是在 rstudio 查看器中的样子。 这有点误导,因为它暗示 pos 行只是整数向量。它们实际上是 nx2 矩阵,没有任何迹象表明它更复杂。这让我有些困惑,但那不是重点。
我想做的是以第 1 列“开始”为 select 的未嵌套小标题结束。所需的输出将如下所示(取消嵌套后):
mydf_desired <- tibble( item = c("a","c","c"), start_pos = c(761,1001,2300))
请注意,mydf 中的第一行在其 pos 矩阵中只有一行,因此它在所需结果中只有一行。带有 item="b" 的行有一个 0x2 矩阵,所以它没有出现(但如果它也显示为 NA 就没问题了)。 item="c" 的行在 pos 矩阵中有两行,因此它在所需结果中有两行。
我试过的
这看起来很简单,我以前没有嵌套列表列。这里唯一的转折是我必须首先 select “开始”列然后取消嵌套,对吗?我只是 map
pos 列表列到 [1] 来选择第一列(“开始”列)。然后应该是取消嵌套的问题了...
mydf_desired <- mydf %>%
mutate(start_pos = map(pos, ~ .[,1])) %>%
unnest()
#> Error in vec_rbind(!!!x, .ptype = ptype): Internal error in `vec_assign()`: `value` should have been recycled to fit `x`.
#> Warning: `cols` is now required.
#> Please use `cols = c(pos, start_pos)`
不知道“value should have been recycled to fit x
”到底是什么意思,但它也警告我不要在 unnest()
中给出 cols。现在怀疑是关于我给出的东西 unnest()
.
如果我省略 unnest()
我不会得到那个错误...
mydf_desired <- mydf %>%
mutate(start_pos = map(pos, ~ .[,1]))
输出看起来像这样...
看起来不错,我注意到 integer(0)
的 item=b 仍然有一个 pos 条目。但即使我省略了那一行,当我尝试 unnest()
.
这就是我难倒的地方。为什么我不能 unnest()
这个标题? value should have been recycled to fit x
错误是什么意思?
一个选项是 filter
行,然后 map
在 list
元素上并从 matrix
中提取列,然后使用 unnest_longer
library(dplyr)
library(purrr)
mydf %>%
filter(lengths(pos) > 0) %>%
transmute(item, start_pos = map(pos, ~ as.vector(.x[,1]))) %>%
unnest_longer(c(start_pos))
# A tibble: 3 x 2
# item start_pos
# <chr> <dbl>
#1 a 761
#2 c 1001
#3 c 2300
另外,可以避免filter
这一步,如果我们转换成tibble
mydf %>%
transmute(item, pos = map(pos, ~ .x[,1] %>%
tibble(start_pos = .))) %>%
unnest(c(pos))
错误出现是因为 unnest
试图取消嵌套 pos
列。您可以明确指定要 unnest
的列以避免错误。
library(dplyr)
library(purrr)
mydf %>% mutate(start_pos = map(pos, ~.[, 1])) %>% unnest(start_pos)
# A tibble: 3 x 3
# item pos start_pos
# <chr> <list> <dbl>
#1 a <dbl[,2] [1 × 2]> 761
#2 c <dbl[,2] [2 × 2]> 1001
#3 c <dbl[,2] [2 × 2]> 2300
如果您想要 NA
用于 "b"
项,您可以使用 unnest_longer
mydf %>%
mutate(start_pos = map(pos, ~.[, 1])) %>%
unnest_longer(start_pos, indices_include = FALSE)
# A tibble: 4 x 3
# item pos start_pos
# <chr> <list> <dbl>
#1 a <dbl[,2] [1 × 2]> 761
#2 b <int[,2] [0 × 2]> NA
#3 c <dbl[,2] [2 × 2]> 1001
#4 c <dbl[,2] [2 × 2]> 2300
或 unnest
与 keep_empty = TRUE
。
mydf %>%
mutate(start_pos = map(pos, ~.[, 1])) %>%
unnest(start_pos, keep_empty = TRUE)