创建新列以指示列名在另一个字符串向量中的位置(使用dplyr、purrr和stringr)

创建新列以指示列名在另一个字符串向量中的位置(使用dplyr、purrr和stringr),r,dplyr,stringr,purrr,R,Dplyr,Stringr,Purrr,鉴于此示例数据: require(stringr) require(tidyverse) labels <- c("foo", "bar", "baz") n_rows <- 4 df <- 1:n_rows %>% map(~ data.frame( block_order=paste(sample(labels, size=length(labels), replace=FALSE), collaps

鉴于此示例数据:

require(stringr)
require(tidyverse)

labels <- c("foo", "bar", "baz")
n_rows <- 4

df <- 1:n_rows %>%
  map(~ data.frame(
      block_order=paste(sample(labels, size=length(labels), replace=FALSE),
                        collapse="|"))) %>%
  bind_rows()

df
  block_order
1 foo|bar|baz
2 baz|bar|foo
3 foo|baz|bar
4 foo|bar|baz
我一直在尝试dplyr/purrr设置中的不同变体,如下面的示例,其中我映射标签的每个值,然后尝试使用str_split上的匹配以块_顺序获取其位置:

但这会产生意想不到的结果:

  block_order foo bar baz
1 foo|bar|baz   1   2   3
2 baz|bar|foo   3   2   1
3 foo|baz|bar   1   3   2
4 foo|bar|baz   1   2   3
  block_order foo bar baz
1 foo|bar|baz   1   5   2
2 baz|bar|foo   1   5   2
3 foo|baz|bar   1   5   2
4 foo|bar|baz   1   5   2
我真的不确定这些数字代表什么,或者为什么它们都是一样的


如果有人能帮我弄清楚a如何在dplyr/purrr框架中实现我想要的输出,b为什么这里提出的解决方案给出了它所需要的输出,我将非常感激。

我们可以按|分割“块顺序”,使用lappy循环向量列表,使用match获得索引,r查找向量并指定它以创建新列

labels <- c("foo", "bar", "baz")
df[labels] <- do.call(rbind, lapply(strsplit(df$block_order, "|",
         fixed = TRUE), match, table = labels))
另一种选择是使用单独的_行,将其重塑为“长”格式,然后将其展开


我们可以将“block_order”按|分割,使用lappy循环遍历向量列表,使用match获得索引,rbind向量并分配给它以创建新列

labels <- c("foo", "bar", "baz")
df[labels] <- do.call(rbind, lapply(strsplit(df$block_order, "|",
         fixed = TRUE), match, table = labels))
另一种选择是使用单独的_行,将其重塑为“长”格式,然后将其展开


我认为这可能有效:

library(tidyr)
library(purrr)
position_counter <- function(...) {
  row = list(...)
  row %>% map(~which(row == .)) %>% setNames(row)
}

df %>%
  separate(block_order, labels) %>% 
  pmap_df(position_counter)

我认为这可能有效:

library(tidyr)
library(purrr)
position_counter <- function(...) {
  row = list(...)
  row %>% map(~which(row == .)) %>% setNames(row)
}

df %>%
  separate(block_order, labels) %>% 
  pmap_df(position_counter)

除非出于其他原因需要,否则如果您只需为标签的每个值标识第一个匹配的位置(regexpr将为您提供),就不必完全拆分字符串。在标签上映射将为标签中的每个字符串提供一个列表,其中包含一个元素,因此这是一个快速迭代,然后您可以对其进行pmap排序以获得索引。使用*_dfr版本将结果简化为数据帧,并与原始数据绑定

图书馆管理员 第47集 标签% pmap\u dfr~set\u namesas.listrankc…,标签%>% bind_colsdf。 >一个tibble:10x4 >积木订单foo bar baz > >1巴兹|福|酒吧2。3.1. >2巴兹|巴|福3。2.1. >3巴|福|巴2。1.3. >4巴兹|福|酒吧2。3.1. >5福|巴|巴1。2.3. >6巴兹|福|酒吧2。3.1. >7福巴1号。3.2. >8巴|巴|福3。1.2. >9巴兹|福|酒吧2。3.1. >10福|巴|巴1。2.3.
如果您更喜欢stringr/stringi而不是基本正则表达式,您可以通过将regexpr调用更改为str_locatedf$block_order、.x[,start]或stringi::stri_locate_first_固定在相同的排列中来实现相同的功能。

除非出于其他原因,如果只为每个标签值标识第一个匹配项的位置(regexpr将为您提供),则不必完全拆分字符串。在标签上映射将为标签中的每个字符串提供一个列表,其中包含一个元素,因此这是一个快速迭代,然后您可以对其进行pmap排序以获得索引。使用*_dfr版本将结果简化为数据帧,并与原始数据绑定

图书馆管理员 第47集 标签% pmap\u dfr~set\u namesas.listrankc…,标签%>% bind_colsdf。 >一个tibble:10x4 >积木订单foo bar baz > >1巴兹|福|酒吧2。3.1. >2巴兹|巴|福3。2.1. >3巴|福|巴2。1.3. >4巴兹|福|酒吧2。3.1. >5福|巴|巴1。2.3. >6巴兹|福|酒吧2。3.1. >7福巴1号。3.2. >8巴|巴|福3。1.2. >9巴兹|福|酒吧2。3.1. >10福|巴|巴1。2.3.
如果您更喜欢stringr/stringi而不是基本正则表达式,您可以通过将regexpr调用更改为str_locatedf$block_order、.x[,start]或stringi::stri_locate_first_,以相同的方式固定。

Whoa。这是一些先进的科技。你能解释一下pmap/set_名称/等级吗,或者链接到集合名称/等级的简化示例?regexpr的映射按块顺序为该标签生成第一个匹配字符索引的向量列表。pmap在这些向量上并行迭代,对每个三元组进行排序,将它们从索引(例如c5、1、9)转换为等级c2、1、3。set_names和as.list是这样的,因此结果可以通过pmap的*_dfr版本被绑定到一个数据帧中,该版本可以处理命名列表。这是一些先进的科技。你能解释一下pmap/set_名称/等级吗,或者链接到集合名称/等级的简化示例?regexpr的映射按块顺序为该标签生成第一个匹配字符索引的向量列表。pmap在这些向量上并行迭代,对每个三元组进行排序,将它们从索引(例如c5、1、9)转换为等级c2、1、3。set_names和as.list的作用是,pmap的*_-dfr版本可以将结果绑定到数据帧中,该版本可以处理命名列表。
library(tidyr)
library(purrr)
position_counter <- function(...) {
  row = list(...)
  row %>% map(~which(row == .)) %>% setNames(row)
}

df %>%
  separate(block_order, labels) %>% 
  pmap_df(position_counter)