【问题标题】:Extracting rows based on more than two partial strings that must all be part of the string基于两个以上的部分字符串提取行,这些部分字符串必须都是字符串的一部分
【发布时间】:2021-12-08 06:44:11
【问题描述】:

我想提取必须包含两个或多个部分字符串的行。例如,假设我有以下data.table

df <- data.table(player = c('A', 'B', 'C', 'D', 'E', 'F', 'G'),
                 position = c('S Guard', 'P Guaaard', 'P Guard', 'S Forward',
                            'P Forward', 'Center', 'Center'),
                 points = c(28, 17, 19, 14, 23, 26, 5))

我知道我可以使用部分字符串Guard 提取行

df[grep("Gua|rd", df$position), ]

如果我希望字符串同时包含Gua rd,该怎么办?试过了

df[grep("Gua&rd", df$position), ]

无论有无空格,但都不起作用。

编辑更多信息

我实际上正在处理相对较大的数据集,并且我在一个中使用字符串从另一个中提取数据,如下所示:

df1 <- data.frame(player = c('A', 'B', 'C', 'D', 'E', 'F', 'G'),
                 position1 = c('S Guard', 'P Guard', 'P Guard', 'S Forward',
                            'P Forward', 'Center', 'Center'),
                 position2 = c('S Grd', 'P Guard', 'P rdGua', 'S Forward',
                             'P Forward', 'Center', 'Center'))

df2 <- data.table(player = c('A', 'B', 'C', 'D', 'E', 'F', 'G'),
                 points = c(28, 17, 19, 14, 23, 26, 5))

df2[df1[,3] %like% "Gua|rd",c(1,2)]

因此顺序无关紧要,即如果使用&amp; 代替|GuardrdGua 应该返回true。

【问题讨论】:

  • 我相信有人会给你一个巧妙的正则表达式答案,但与此同时,这将起作用:df[grepl("Gua", df$position) &amp; grepl("rd", df$position), ]
  • 我看到您对我的答案提出的修改,并附有以下评论 “问题中给出的列表语法,而不是数据框语法。”。我拒绝了那个编辑。澄清一下:您也可以在 data.frames 上使用列表语法,我个人更喜欢列表语法。

标签: r dplyr grep data.table


【解决方案1】:

如果您将| 替换为.*,您将获得所需的结果。除了grep(或grepl),您还可以使用like from

.* 表示“Gua”和“rd”之间允许每个字符。

两种选择:

# option 1
df[grep("Gua.*rd", position)]

# option 2
df[like(position, "Gua.*rd")]

两者都给出:

   player  position points
1:      A   S Guard     28
2:      B P Guaaard     17
3:      C   P Guard     19

因为您使用的是-package,所以您不需要方括号之间的df$ 部分。


针对额外信息,您可以通过以下方式实现:

df2[df1[[3]] %like% "(Gua.*rd)|(rd.*Gua)"]

给出:

   player points
1:      B     17
2:      C     19

grep/grepl 替代方案:

df2[grepl("(Gua.*rd)|(rd.*Gua)", df1[[3]])]

【讨论】:

  • 甚至df[position %like% "Gua.*rd"]
【解决方案2】:

这可能有点矫枉过正,但如果您不知道顺序并希望避免多次grep() 调用,您可以这样做:

# Helper function
grepAnd <- function(vect, strings) {
  grep(
    do.call(sprintf, c(strrep('(?=.*%s)', length(strings)), as.list(strings))), 
    vect, 
    perl = TRUE
  )
}

inp <- c('Gua', 'rd')
df[grepAnd(position, inp)]

#    player  position points
# 1:      A   S Guard     28
# 2:      B P Guaaard     17
# 3:      C   P Guard     19

# Works even though the arguments are reversed
inp <- rev(inp)
df[grepAnd(position, inp)]
#    player  position points
# 1:      A   S Guard     28
# 2:      B P Guaaard     17
# 3:      C   P Guard     19


# Can search for more than two patterns
inp <- c(inp, 'P')
df[grepAnd(position, inp)]
#    player  position points
# 1:      B P Guaaard     17
# 2:      C   P Guard     19

【讨论】:

    猜你喜欢
    • 2020-12-18
    • 1970-01-01
    • 2021-02-21
    • 2013-10-02
    • 2022-01-15
    相关资源
    最近更新 更多