# An R function for performing searches

I am slightly new to writing functions in R. Here I have a basic function that searches for a pattern and returns the indexes of where the occurence occurs given a list dataset

#this functions takes a pattern and prints the indexes for the matches
find_domain <- function(pattern,list) grep(pattern,list,ignore.case=T)


Sometimes during the analysis i found that i need to do that for a larger dataset. The idea is to look for occurence of a domain (pattern) in each of the d7_dataset rows(since each row represents a protein sequence and each column is a domain) such that i can then count the number of sequences that contain or have a given domain(pattern in this case) So i wrote this

seqs <- c()
for (i in 1:nrow(d7_dataset)){
pos <- find_domain("CIDRγ13",d7_dataset[i,])
if (!is.na(pos[1]))
seqs <- c(seqs,1)
}

total_seqs <- sum(seqs)
total_seqs


However this seems like it can be written as a single function so that i can eliminate duplication and simplify it such that it is generic enough to apply to multiple datasets. Any ideas on how to condence it to a single function? In a nutshell, Given a pattern or list of patterns and a dataset(as a dataframe) to search, return the number of sequences(rows in the dataset) that contain the given pattern.

More or less like this

results <– search(a list of patterns to search,dataset)


results should look like

pattern  count
pat1     40
pat2      3
pat3      0
.         .
.         .


It would be very good if the pattern argument would accept a list to search

Thank you

-
 Just a programming note: it is useless (and will slow down your script) to create a function that just calls another function. There is no real advantage in calling find_domain if the only thing it does it's calling grep. You are just adding the overhead of another function call. – nico Jan 5 '11 at 17:47 you are right! this was a dirty approach and just sounded sort of wrong design though it worked. Am glad that i asked! – eastafri Jan 5 '11 at 17:55

If your dataset is a matrix, then grep will work directly:

> set.seed(1)
> bb=matrix(letters[sample(1:20, 100, rep=TRUE)], nrow=20)
> grep("b", bb)
[1] 10 55 56 69 92
> bb[grep("b", bb)]
[1] "b" "b" "b" "b" "b"


If you have multiple patterns, then use ldply from package plyr:

> ldply(c("a", "b", "z"), function(l) data.frame(pattern = l, count = length(grep(l, bb))))
pattern count
1       a     2
2       b     5
3       z     0


Your function search then can look like this

 search <- function(patlist,data) {
if(!is.matrix(data)) data <- as.matrix(data)
ldply(patlist, function(l) data.frame(pattern = l, count = length(grep(l, bb))))
}


Note that this will not work for data.frame. So if that is possible you will need to convert it to the matrix, as I did in the code above.

-
 @mpitkas (+1) Nice one! – chl♦ Jan 5 '11 at 14:13 @mpitkas Ah, and yours is faster (by 0.004, on my fake data set). This the way to go... – chl♦ Jan 5 '11 at 14:18 And sorry to have mispelled your name (two times) :( – chl♦ Jan 5 '11 at 14:23 @chl, thanks to Hadley Wickham :) – mpiktas Jan 5 '11 at 14:32 @chl, no worries, my surname is constantly misspelled by my native language speakers, so my expectations for not misspelling the nickname are really low :) – mpiktas Jan 5 '11 at 14:35

You should first replace your for loop with something like apply(d7_dataset, 1, foo), where foo() is either your function or something along those lines, e.g. gregexpr(). The result of gregexpr() is a list of numeric vectors with attributes similar to regexpr() but giving all matches in each element.

On a related point, there was another function that was proposed as a more user-friendly alternative to gregexpr(): easyGregexpr.

The following example gives you the number of matches for each row when considering a list of three motifs (in a 10x100 matrix):

dd <- replicate(100, replicate(10, paste(sample(letters[1:4], 2),
collapse="")))
pat <- list("aa", "ab", "cd")
foo <- function(d, p) apply(d, 1, function(x) length(grep(p, x)))
lapply(pat, function(x) foo(dd, x))

-
for this purpose you can see the stringr package of H. Wickam – pbneau Jan 5 '11 at 13:56
Thanks for pointing out the rstring library!! Awesome approaches! Thanks! – eastafri Jan 5 '11 at 17:53