根据列中部分字符串匹配选择数据框行

156

我想基于数据框中某一列包含的字符串部分匹配选择行,例如,列“x”包含字符串“hsa”。如果使用 sqldf , 如果它有一个类似于like的语法,我会这样做:

select * from <> where x like 'hsa'.

不幸的是,sqldf不支持该语法。

或者类似这样:

selectedRows <- df[ , df$x %like% "hsa-"]

当然这不起作用。

请问有人可以帮我吗?


6
你能否发布一些数据的几行,最好使用类似于 dput(head(conservedData)) 的方式。 - A5C1D2H2I1M1N2O1R2T1
4个回答

214

我注意到您在当前的方法中提到了一个函数%like%。我不知道这是否是来自"data.table"中的%like%,但如果是的话,您可以像下面这样使用它。

请注意,对象不一定是一个data.table(但也请记住,对于data.framedata.table的子集选择方法并不相同):

library(data.table)
mtcars[rownames(mtcars) %like% "Merc", ]
iris[iris$Species %like% "osa", ]
如果您有这个问题,那么可能是您在子集操作时混淆了行和列的位置。
如果您不想加载一个包,可以尝试使用 grep() 函数来搜索您要匹配的字符串。下面是一个例子,使用mtcars数据集,我们匹配所有行名包含“Merc”的行:
mtcars[grep("Merc", rownames(mtcars)), ]
             mpg cyl  disp  hp drat   wt qsec vs am gear carb
# Merc 240D   24.4   4 146.7  62 3.69 3.19 20.0  1  0    4    2
# Merc 230    22.8   4 140.8  95 3.92 3.15 22.9  1  0    4    2
# Merc 280    19.2   6 167.6 123 3.92 3.44 18.3  1  0    4    4
# Merc 280C   17.8   6 167.6 123 3.92 3.44 18.9  1  0    4    4
# Merc 450SE  16.4   8 275.8 180 3.07 4.07 17.4  0  0    3    3
# Merc 450SL  17.3   8 275.8 180 3.07 3.73 17.6  0  0    3    3
# Merc 450SLC 15.2   8 275.8 180 3.07 3.78 18.0  0  0    3    3

另一个示例,使用iris数据集搜索字符串osa

irisSubset <- iris[grep("osa", iris$Species), ]
head(irisSubset)
#   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
# 1          5.1         3.5          1.4         0.2  setosa
# 2          4.9         3.0          1.4         0.2  setosa
# 3          4.7         3.2          1.3         0.2  setosa
# 4          4.6         3.1          1.5         0.2  setosa
# 5          5.0         3.6          1.4         0.2  setosa
# 6          5.4         3.9          1.7         0.4  setosa

尝试以下解决方案:

selectedRows <- conservedData[grep("hsa-", conservedData$miRNA), ]

3
事实上,“grep”一词源于ed命令“g/re/p”(全局/正则表达式/打印),只有掌握正则表达式技巧的大师才能发挥它的真正威力;-):http://en.wikipedia.org/wiki/Grep - Stephan Kolassa
1
“%like%” 的建议非常好!我建议将其放在您的答案顶部。 - Aren Cambre
@ArenCambre,完成了。也许这会帮助我获得另外11票,这样我就可以在年底之前得到一顶新帽子 :-) - A5C1D2H2I1M1N2O1R2T1
很棒的答案!我总是回来看这个! - stats_noob
不知道 **%like%**,太完美了!谢谢 - Vicky Ruiz
显示剩余2条评论

98

尝试使用stringr包中的str_detect()函数,该函数可以检测字符串中模式的存在或缺失。

以下方法还结合了dplyr包中的%>%管道和filter()函数:

library(stringr)
library(dplyr)

CO2 %>%
  filter(str_detect(Treatment, "non"))

   Plant        Type  Treatment conc uptake
1    Qn1      Quebec nonchilled   95   16.0
2    Qn1      Quebec nonchilled  175   30.4
3    Qn1      Quebec nonchilled  250   34.8
4    Qn1      Quebec nonchilled  350   37.2
5    Qn1      Quebec nonchilled  500   35.3
...

这个操作筛选出R自带的CO2数据集中,Treatment变量包含子字符串"non"的行。您可以调整str_detect函数是查找精确匹配还是使用正则表达式——请参阅stringr包的文档。


1
您也可以像这样使用 trc_detect 函数 myDataFrame[str_detect(myDataFrame$key, myKeyPattern),] - Bemipefe
@Bemipefe,你是不是指的是 str_detect 函数而不是 trc_detect 函数? - Martin
1
@Martin 是的,你说得对。那是个打字错误。 - Bemipefe

23

LIKE 在sqlite中应该能正常工作:

require(sqldf)
df <- data.frame(name = c('bob','robert','peter'),id=c(1,2,3))
sqldf("select * from df where name LIKE '%er%'")
    name id
1 robert  2
2  peter  3

SQLDF最适合用于列出数据,但是它无法删除行。 - Suat Atan PhD
1
为什么在这里使用require()加载R包? - rgalbo
因为它不是标准的 R 库,你需要手动安装它,然后使用 require 函数加载。 - bartektartanus

8

另一种选择是简单地使用 grepl 函数:

df[grepl('er', df$name), ]
CO2[grepl('non', CO2$Treatment), ]

df <- data.frame(name = c('bob','robert','peter'),
                 id = c(1,2,3)
                 )

# name id
# 2 robert  2
# 3  peter  3

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