如何基于字符串字符来对向量进行子集化?

7

我有一个由"ZZZ1Z01Z0ZZ0", "1001ZZ0Z00Z0"等条目组成的向量,我想根据以下条件对该向量进行子集提取:

  1. 第三个字符是 Z
  2. 第三个和第七个字符都是 Z
  3. 第三个和第七个字符都是 Z,并且没有其他字符是 Z

我尝试使用strsplit和grep,但我无法找到一种基于字符串上的字符位置限制我的条件的方法。 有什么建议吗?

非常感谢!


1
这些向量的长度总是相同的,只包含0、1和Z吗?我不知道这些东西是如何工作的,我只能提供一个正则表达式 :) - sinni800
3个回答

12

您可以使用正则表达式实现此目标(有关正则表达式的详细信息,请参见 ?regexp)。

grep 返回匹配项的位置,并在未找到匹配项时返回零长度向量。您可能希望改用 grepl,因为它返回一个逻辑向量,可用于子集操作。

z <- c("ZZZ1Z01Z0ZZ0", "1001ZZ0Z00Z0")
# 3rd character is Z ("^" is start of string, "." is any character)
grep("^..Z", z)
# 3rd and 7th characters are Z
grep("^..Z...Z", z)
# 3rd and 7th characters are Z, no other characters are Z
# "[]" defines a "character class" and "^" in a character class negates the match
# "{n}" repeats the preceding match n times, "+" repeats is one or more times
grep("^[^Z]{2}Z[^Z]{3}Z[^Z]+", z)

你为什么会考虑用其他方式来做呢? - IRTFM
非常感谢您的帮助。我已经开始尝试使用正则表达式,它们真是太棒了!简直不敢相信我以前怎么没接触过这个。谢谢! - Rafael Maia

4
扩展Josh的回答,您想要
your_dataset <- data.frame(
  z = c("ZZZ1Z01Z0ZZ0", "1001ZZ0Z00Z0")
)
regexes <- c("^..Z", "^..Z...Z", "^[^Z]{2}Z[^Z]{3}Z[^Z]+")

lapply(regexes, function(rx)
{
  subset(your_dataset, grepl(rx, z))
})

还可以考虑使用 stringr 包中的 str_detect(z, rx) 替换 grepl(rx, z)。这样代码不仅更易读,而且几乎没有任何区别。


2
你可以使用substr命令提取特定字符来完成前两个步骤,而无需使用正则表达式。
# Grab the third character in each element and compare it to Z
substr(z, 3, 3) == "Z"
# Check if the 3rd and 7th characters are both Z
(substr(z, 3, 3) == "Z") & (substr(z, 7, 7) == "Z")  

然而,Joshua提供的正则表达式方法更加灵活,在使用substr方法实现你所需的第三个限制时会很麻烦。正则表达式对于像第三个限制这样的问题更加适用,并学习如何使用它们永远不是一个坏主意。


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