# How do I create a for loop to filter through different FDR values?

This is probably a really quick/simple fix but I am a Noob to R programming/programming in general. I am trying to create a for loop that runs the test multiple times with different FDR values (5,10,20). How do I make it run 3 times with different values and then produce 3 different datasets with names like... atac.glmtop.males.opening.fdr5, atac.glmtop.males.opening.fdr10, atac.glmtop.males.opening.fdr20? Also is there a way to make the write.table function work so that it exports files with the fdr5, fdr10, fdr20 in the name?

fdr.nums = c("5","10","20")
fdr.nums.vector = c(5,10,20)

for (i in 1:length(fdr.list)){
atac.glmtop.males.opening.fdr[i] <- topTags(
atac.glmfit.males,
n = nrow(atac.dge$counts), sort.by = "none", adjust.method = "fdr" )$table %>%
tibble::rownames_to_column("peakco") %>%
filter(logFC < 0) %>%
filter(FDR < (fdr.vector[i]/100)) %>%
merge(.,annotated.atac.pbmc.narrow, by="peakco" ) %>%
tibble::column_to_rownames("peakco")

atac.glmtop.males.opening.fdr[i]

write.table(
atac.glmtop.males.fdr[i].opening[,c("chr", "start","end")],
sep = "\t",
quote = FALSE,
row.names = FALSE,
col.names = FALSE
)
write.table(
atac.glmtop.males.fdr[i].opening["GeneName"],
sep = "\t",
quote = FALSE,
row.names = FALSE,
col.names = FALSE
)
}

• I'm voting to close this question as off-topic because it is not about bioinformatics.
– llrs
Jun 28 '18 at 6:54

For loops in most languages can be done in a variety of ways. What you have currently coded, loops over values 1 to 3 by using

for (i in 1:length(fdr.list)){
...
}


However, you probably want to use a different form and loop over each value in that vector using something more like:

for (fdr in fdr.nums.vector){
...
}


This way you have convenient access to the FDR value in each loop via the fdr variable. Which you can then use in constructing your output filenames. Thus your code would become something like:

fdr.nums.vector = c(5,10,20)

for (fdr in fdr.nums.vector){
atac.glmtop.males.opening.fdr[fdr] <- topTags(
atac.glmfit.males,
n = nrow(atac.dge$counts), sort.by = "none", adjust.method = "fdr" )$table %>%
tibble::rownames_to_column("peakco") %>%
filter(logFC < 0) %>%
filter(FDR < (fdr/100)) %>%
merge(.,annotated.atac.pbmc.narrow, by="peakco" ) %>%
tibble::column_to_rownames("peakco")

atac.glmtop.males.opening.fdr[fdr]

write.table(
atac.glmtop.males.fdr[fdr].opening[,c("chr", "start","end")],
sep = "\t",
quote = FALSE,
row.names = FALSE,
col.names = FALSE
)
write.table(
atac.glmtop.males.fdr[fdr].opening["GeneName"],
sep = "\t",
quote = FALSE,
row.names = FALSE,
col.names = FALSE
)
}


# Advancing From for Loops to apply

As a beginner, for loops seem quite logical and easy to understand. However, R has a more powerful way to achieve the same thing through what is called "vectorisation" using the apply function or one of it's relatives lapply, sapply etc. Once you have understood and mastered for loops, you should take a look at apply, especially if you ever need to do a for loop many times or you find yourself doing nested for loops. R is notoriously slow with for loops and apply will likely be many times faster (potentially orders of magnitude). Here are some links for when you are ready to advance from for loops to vectorisation.

• You are right about vectorisation, however, apply is not vectorisation but uses for loops, see this for details: r-bloggers.com/… or the document 'The R Inferno'. Jun 28 '18 at 10:16
• “As a beginner, for loops seem quite logical and easy to understand” — this is really only true for people who are used to imperative programming. Properly taught, a functional-first approach is simpler for beginners. I strongly recommend skipping for loops in teaching and learning (or at least postponing them until much later in a course). Especially since, in R, they require all kinds of special explanations. Jun 28 '18 at 15:58