dplyr mutate + unlist问题

3
我想从数据框中提取字符的一部分。
d<-data.frame(a=c("aa_bb_cc", "ddd_eee_fff", "sss_rrr_eee"))

我希望在新列中获取"bb"、"eee"和"rrr"这部分内容。当使用下面的结构时,它可以正常工作:

unlist(str_split(d$a[1],"_"))[2]
unlist(str_split(d$a[2],"_"))[2]

所以我将其应用到 mutate (dplyr) 中:

t<-d %>% mutate(new1=(unlist(str_split(a,"_"))[2])) 

但是结果在所有情况下都是"bb"。我做错了什么?

总是有趣的函数word,即stringr::word(d$a, 2, sep = '_') - Sotos
4个回答

3
当您执行

d %>% mutate(new1=(unlist(str_split(a,"_"))[2]))

它在 str_split 中传递了一个 a 列。因此,这相当于

unlist(str_split(d$a, "_"))
#[1] "aa"  "bb"  "cc"  "ddd" "eee" "fff" "sss" "rrr" "eee"

现在当你对其进行子集操作并获取第二个元素时,它会返回

unlist(str_split(d$a, "_"))[2]
#[1] "bb"

因此,该值被分配给所有情况。
为了解决这个问题,您可以添加操作rowwise,以获得所需的输出,因为它将单独为每一行传递a的值到str_split
library(tidyverse)

d %>%
  rowwise() %>%
  mutate(new1= unlist(str_split(a,"_"))[2])

#      a      new1 
#    <fct>    <chr>
#1 aa_bb_cc    bb   
#2 ddd_eee_fff eee  
#3 sss_rrr_eee rrr  

另一个更安全的选项是使用separate,根据定界符将字符串分成不同的列,并选择相关的列。

d %>%
  separate(a, into = c("one", "two", "three"), sep = "_", remove = FALSE) %>%
  select(a, two)

#            a two
#1    aa_bb_cc  bb
#2 ddd_eee_fff eee
#3 sss_rrr_eee rrr

显然,您也可以使用基本的 R 选项,使用 sapplystrsplit

sapply(strsplit(as.character(d$a), "_"), "[[", 2)
#[1] "bb"  "eee" "rrr"

0
d1 <- as.data.frame(unlist(str_split_fixed(d$a,"_", n =3)))

希望这个能够正常工作。

0
也许这是开始使用(高度可定制的)正则表达式的好借口:
d[["new"]] <- gsub(".*_(.*)_.*", "\\1", d[["a"]])
d
            a new
1    aa_bb_cc  bb
2 ddd_eee_fff eee
3 sss_rrr_eee rrr

0
我们可以使用 str_extract
library(tidyverse)
d %>% 
   mutate(new = str_extract(a, "(?<=_)[^_]+"))
#            a new
#1    aa_bb_cc  bb
#2 ddd_eee_fff eee
#3 sss_rrr_eee rrr

或者使用 base R

d$new <- read.table(text = as.character(d$a), header = FALSE, sep="_")[,2]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接