将长度为零的字符向量处理为空字符串

3

举个例子,看下面提取Twitter账户的操作。目标是获得一个类似于tweets的字符串,只包含用逗号隔开的账户名。使用str_replace_all函数替换没有匹配到的内容时会返回空向量,这可能会在后续操作中导致一些意想不到的错误。

library(purrr)
library(stringr)

tweets <- c(
  "",
  "This tweet has no handles",
  "This is a tweet for @you",
  "This is another tweet for @you and @me",
  "This, @bla, is another tweet for @me and @you"
)


mention_rx <- "@\\w+"

这是我的第一次尝试:

map_chr(tweets, ~str_c(str_extract_all(.x, mention_rx)[[1]], collapse = ", "))
#> Error: Result 1 must be a single string, not a character vector of length 0

然后我尝试了一些东西:

mentions <- map(tweets, ~str_c(str_extract_all(.x, mention_rx)[[1]], collapse = ", "))

mentions
#> [[1]]
#> character(0)
#> 
#> [[2]]
#> character(0)
#> 
#> [[3]]
#> [1] "@you"
#> 
#> [[4]]
#> [1] "@you, @me"
#> 
#> [[5]]
#> [1] "@bla, @me, @you"

as.character(mentions)
#> [1] "character(0)"    "character(0)"    "@you"            "@you, @me"      
#> [5] "@bla, @me, @you"

直到我意识到 paste 也可以在这里使用:

map_chr(tweets, ~paste(str_extract_all(.x, mention_rx)[[1]], collapse = ", "))
#> ""                ""                "@you"            "@you, @me"       "@bla, @me, @you"

我的问题是:

  • 有没有更优雅的方法来解决这个问题?
  • 为什么 str_c 和带有相同 collapse 参数的 paste 表现不同?
  • 为什么 as.charactermap_chr 不能把长度为零的字符向量识别为空字符串,但 paste 可以?

我在以下参考资料中找到了一些很好的内容:str(i)_cpaste,以及它们之间的区别;但它们都没有涉及空字符串的情况。

1个回答

2

您不需要对tweets进行map映射,str_extract_all可以处理向量。

library(stringr)
str_extract_all(tweets, mention_rx)

#[[1]]
#character(0)

#[[2]]
#character(0)

#[[3]]
#[1] "@you"

#[[4]]
#[1] "@you" "@me" 

#[[5]]
#[1] "@bla" "@me"  "@you"

现在,如果您需要一个逗号分隔的字符串,那么您可以使用map
purrr::map_chr(str_extract_all(tweets, mention_rx), toString)
#[1] ""    ""      "@you"     "@you, @me"      "@bla, @me, @you"

为了回答“为什么”的问题,我们可以查看pastestr_c函数的文档。
?paste中得知:
向量参数将根据需要进行循环使用,长度为零的参数将被循环使用为""。
?str_c中得知:
零长度参数将被删除。
因此,默认情况下,str_c会删除零长度参数,这使得输出成为一个0长度字符串,这对于map_chr无法工作,但对于map可以工作,因为map返回一个列表。
map(tweets, ~str_c(str_extract_all(.x, mention_rx)[[1]], collapse = ", "))

#[[1]]
#character(0)

#[[2]]
#character(0)

#[[3]]
 #[1] "@you"

#[[4]]
#[1] "@you, @me"

#[[5]]
#[1] "@bla, @me, @you"

嘿Ronak,非常感谢!我一直在处理不同数量的模式和字符串,所以我太习惯于使用stringr函数进行映射...即使在那种情况下,我也不确定是否有正当理由。你对“为什么”问题可能的答案有任何线索吗? - Fons MA
1
@FonsMA 更新了答案并加入了一些解释。希望对您有所帮助。 - Ronak Shah

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