and*_*ece 1 r stringr dplyr 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),
collapse="|"))) %>%
bind_rows()
df
block_order
1 foo|bar|baz
2 baz|bar|foo
3 foo|baz|bar
4 foo|bar|baz
Run Code Online (Sandbox Code Playgroud)
我想为每个字符串生成一个列labels,它|在每行的分隔序列中获取该字符串的位置值.
期望的输出:
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
Run Code Online (Sandbox Code Playgroud)
我一直在尝试dplyr/ purrrsetup中的不同变体,比如这个例子,我map在每个值中label,然后尝试在block_order使用match时获得它的位置str_split:
labels %>%
map(~ df %>%
transmute(!!.x := match(!!.x, str_split(block_order,
"\\|",
simplify=TRUE)))) %>%
bind_cols(df, .)
Run Code Online (Sandbox Code Playgroud)
但这会产生意外的输出:
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
Run Code Online (Sandbox Code Playgroud)
我不确定这些数字代表什么,或者为什么它们都是一样的.
如果有人能帮助我弄清楚(a)如何在dplyr/ purrr框架中实现我想要的输出,以及(b)为什么这里提出的解决方案给出了它的输出,我将非常感激.
我们可以通过分拆"的block_order" |通过,环路list的vectorS使用lapply,获得与指数match,rbind在vectorS和其分配给创建新列
labels <- c("foo", "bar", "baz")
df[labels] <- do.call(rbind, lapply(strsplit(df$block_order, "|",
fixed = TRUE), match, table = labels))
Run Code Online (Sandbox Code Playgroud)
或类似的想法 tidyverse
library(tidyverse)
str_split(df$block_order, "[|]") %>%
map(~ .x %>%
match(table= labels)) %>%
do.call(rbind, .) %>%
as_tibble %>%
set_names(labels) %>%
bind_cols(df, .)
# 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
Run Code Online (Sandbox Code Playgroud)
另一种选择是使用separate_rows,将其重塑为"长"格式并将spread其重新格式化
rownames_to_column(df, 'rn') %>%
separate_rows(block_order) %>%
group_by(rn) %>%
mutate(ind = match(block_order, labels), labels = factor(labels, levels = labels)) %>%
select(-block_order) %>%
spread(labels, ind) %>%
ungroup %>%
select(-rn) %>%
bind_cols(df, .)
Run Code Online (Sandbox Code Playgroud)