I assume that you want to spamdata over the spamdata elements and create an indicator whether the string "viagra" found in the subject lines of your letters.
Allows you to configure some dummy data for illustrative purposes:
subjects <- c("Buy my viagra", "Buy my Sildenafil citrate", "UK Lottery Win!!!!!") names(subjects) <- rep("Subject", 3) spamdata <- list(list(Header = subjects[1]), list(Header = subjects[2]), list(Header = subjects[3]))
Then we create a vector of words to hold the result of each iteration of the loop. You do not want to grow words or any other object at each iteration - this will make you copy and slow down your loop. Instead, allocate storage before you begin - here, using the length of the list over which we want to loop:
words <- logical(length = length(spamdata))
You can set up the loop this way
## seq_along() creates a sequence of 1:length(spamdata) for(i in seq_along(spamdata)) { words[ i ] <- grepl("viagra", spamdata[[ i ]]$Header["Subject"]) }
Then we can look at words :
> words [1] TRUE FALSE FALSE
Which corresponds to what we know from the created objects.
Notice how we used i as a place holder for 1 , 2 and 3 - at each iteration of the loop, i takes the next value in the sequence 1 , 2 , 3 , so that we can i) access the i th component of spamdata to get the next the subject line, and ii) access the i th element of words to save the result of the grepl() call.
Note that instead of an implicit loop, we could also use the sapply() or lapply() functions, which create a loop for you, but it might take a little work to write a custom function. Instead of using grepl() directly, we can write a shell:
foo <- function(x) { grepl("viagra", x$Header["Subject"]) }
In the above function, we use x instead of the spamdata list spamdata , because when lapply() and sapply() cross the spamdata list, the individual components (referenced by spamdata[[i]] in the for() loop) are passed to our function as an argument x so we only need to refer to x in the grepl() call.
Here is how we could use our wrapper function foo() in lapply() or sapply() , first lapply() :
> lapply(spamdata, foo) [[1]] [1] TRUE [[2]] [1] FALSE [[3]] [1] FALSE
sapply() will simplify the return object, if possible, as follows:
> sapply(spamdata, foo) [1] TRUE FALSE FALSE
In addition, they work similarly.
Notice that we can make our wrapper function foo() more useful by allowing it to accept an argument specifying the spam word you want to find:
foo <- function(x, string) { grepl(string, x$Header["Subject"]) }
We can pass additional arguments to our functions with lapply() and sapply() as follows:
> sapply(spamdata, foo, string = "viagra") [1] TRUE FALSE FALSE > sapply(spamdata, foo, string = "Lottery") [1] FALSE FALSE TRUE
What you find most useful (the for() or lapply() sapply() , sapply() ) will depend on your programming background and which you will find most familiar. Sometimes for() simpler and easier to use, but perhaps more verbose (which is not always bad!), And lapply() and sapply() quite concise and useful when you don't need to jump through hoops to create a workable wrapper function .