我有一个包含一个字符串列的数据表.我想使用strsplit创建另一列作为此列的子集.
dat <- data.table(labels=c('a_1','b_2','c_3','d_4'))
Run Code Online (Sandbox Code Playgroud)
我想要的输出是
label sub_label
a_1 a
b_2 b
c_3 c
d_4 d
Run Code Online (Sandbox Code Playgroud)
我尝试过以下但似乎都没有效果.
dat %>%
mutate(
sub_labels=strsplit(as.character(labels), "_")[[1]][1]
)
# gives a column whose values are all "a"
Run Code Online (Sandbox Code Playgroud)
这个对我来说合乎逻辑,
dat %>%
mutate(
sub_labels=sapply(strsplit(as.character(labels), "_"), function(x) x[[1]][1])
)
Run Code Online (Sandbox Code Playgroud)
给出错误
错误:不知道如何处理类型的pairlist
我看到另一个文章,其中strsplit的输出上的粘贴崩溃工作,所以我不明白为什么匿名函数中的子集正在给出问题.感谢您对此的任何澄清.
Rom*_*ois 20
tidyr::separate 可以帮助:
> dat %>% separate(labels, c("first", "second") )
first second
1: a 1
2: b 2
3: c 3
4: d 4
Run Code Online (Sandbox Code Playgroud)
Gen*_*Rus 10
另一种方法使用purrr's map_chr,我发现它对于我不想打扰分离和合并的应用程序很有用(例如,将结果sprintf与其他字符串一起使用):
tibble(labels=c('a_1','b_2','c_3','d_4')) %>%
mutate(sub_label = stringr::str_split(labels, "_") %>% map_chr(., 1))
Run Code Online (Sandbox Code Playgroud)
这种方法可以比separate我的经验快得多,尤其是当您有更长的数据集时。separate当我使用 100 个字符串时几乎没有击败 map,但在大多数情况下当我使用 1000 个时会落后(不确定这个最大值是怎么回事)。
> microbenchmark::microbenchmark(
+ d.filtered_reads %>% head(1000) %>%
+ mutate(name = stringr::str_split(Header, " ") %>% map_chr(., 1)) %>%
+ select(-Header),
+ d.filtered_reads %>% head(1000) %>%
+ separate(Header, into = c("name","index"), sep = " ") %>%
+ select(-"index")
+ )
Unit: milliseconds
expr
d.filtered_reads %>% head(1000) %>% mutate(name = stringr::str_split(Header, " ") %>% map_chr(., 1)) %>% select(-Header)
d.filtered_reads %>% head(1000) %>% separate(Header, into = c("name", "index"), sep = " ") %>% select(-"index")
min lq mean median uq max neval
5.333891 5.817589 6.292954 5.935706 6.059031 41.530089 100
7.517316 8.031325 8.399471 8.500359 8.647468 9.855612 100
Run Code Online (Sandbox Code Playgroud)
Hen*_*ndy 10
我没有想出这个,我只是在寻找解决方案时偶然发现了这个 github 问题,并认为它比这里的许多答案更简单,特别是避免了额外的map_chr()或tmp_chunks.
# I used data.frame since I don't have data table installed
library(dplyr)
library(stringr)
dat <- data.frame(labels=c('a_1','b_2','c_3','d_4'))
dat %>% mutate(sub_label = str_split(labels, "_", simplify = T)[, 1])
labels sub_label
1 a_1 a
2 b_2 b
3 c_3 c
4 d_4 d
Run Code Online (Sandbox Code Playgroud)
如果我们想一次提取多个列(当然,无需再次运行分割),我们可以将GenesRus的方法与一个临时列结合起来,我们将其与负数select()一起放在管道中:
library(purrr)
library(dplyr)
library(tibble)
library(stringr)
tibble(labels=c('a_1','b_2','c_3','d_4')) %>%
mutate(tmp_chunks = stringr::str_split(labels, stringr::fixed("_"), n = 2)) %>%
mutate(sub_label = map_chr(tmp_chunks, 1),
sub_value = map_chr(tmp_chunks, 2)) %>%
select(-tmp_chunks)
Run Code Online (Sandbox Code Playgroud)
截至 2020 年,性能比separate().
为了完整起见,值得一提的是
map_chr可以接受一个.default参数(以防某些行中缺少分隔符),labels用 negative去掉select()