2
$\begingroup$

I am trying to assign different window sizes to my SNPs dataset to identify regions under selection.

this is the head of my data

head(snp_ids)
   snp_id   chr  pos
Chr01__912    1  912
Chr01__944    1  944
Chr01__1107   1 1107
Chr01__1118   1 1118
Chr01__1146   1 1146
Chr01__1160   1 1160

class(snp_ids)
data.frame

I have chosen 4 different window sizes, win_size <- c(15000, 30000, 50000, 100000). I have assigned each of these different window sizes to my snp_ids dataset to identify how many SNPs are distributed within each window by looping through each window size

for (i in 1:length(win_size)){
  windows <- sapply(snp_ids$pos, function(x) (ceiling(x/win_size[i])))
}
$\endgroup$
3
  • 1
    $\begingroup$ I would like to help, but do not completely follow. I am not sure what you're trying to do. Furthermore, if you want help with code, you should provide a minimal data set to work with (for us to test it). $\endgroup$
    – benn
    Nov 20, 2017 at 20:07
  • 1
    $\begingroup$ How are you getting 1.2 for window_30000? $\endgroup$
    – zx8754
    Nov 21, 2017 at 8:27
  • $\begingroup$ @Anna To help others you can post your own answer to the question. But please do not include it in the question body (unless they are unsuccessful attempts) $\endgroup$
    – llrs
    Nov 30, 2017 at 8:49

2 Answers 2

4
$\begingroup$

Not clear what we are trying to do, but here is the solution using lapply that should replicate your existing forloop.

# example input data
snp_ids <- read.table(text = "
snp_id  chr  pos
Chr01__912   1  912
Chr01__944   1  944
Chr01__1107  1 1107
Chr01__1118  1 1118
Chr01__1146  1 1146
Chr01__1160  1 1160", header = TRUE)

# window sizes to loop through
win_size <- c(15000, 30000, 50000, 100000)

res <- cbind(snp_ids,
             data.frame(
               lapply(setNames(win_size, paste("window", win_size, sep = "_")), function(w)
                 as.numeric(paste(snp_ids$chr, ceiling(snp_ids$pos/w), sep = "."))
               )))

# result
res
#        snp_id chr  pos window_15000 window_30000 window_50000 window_1e.05
# 1  Chr01__912   1  912          1.1          1.1          1.1          1.1
# 2  Chr01__944   1  944          1.1          1.1          1.1          1.1
# 3 Chr01__1107   1 1107          1.1          1.1          1.1          1.1
# 4 Chr01__1118   1 1118          1.1          1.1          1.1          1.1
# 5 Chr01__1146   1 1146          1.1          1.1          1.1          1.1
# 6 Chr01__1160   1 1160          1.1          1.1          1.1          1.1

Edit: If we really want to use forloop, then try below:

for (i in win_size){
  windows <- ceiling(snp_ids$pos/i)
  snp_ids[, paste0("window_", i)] <- as.numeric(paste(snp_ids$chr, windows, sep = "."))
}
$\endgroup$
2
  • $\begingroup$ thanks so much @zx8754. I have edited my post a bit and hope it is more understandable. Your code worked for me. But, as I am learning R programming I wanted to know is there any other way that I could fix my own code above? Thanks so much for your help. $\endgroup$
    – Anna1364
    Nov 21, 2017 at 20:12
  • $\begingroup$ @Anna1364 See edit, yes we could use forloop but I prefer apply family. $\endgroup$
    – zx8754
    Nov 21, 2017 at 21:43
2
$\begingroup$

This explicitly doesn't use apply() or lapply(), but rather the dplyr package. This is probably easier to read and debug:

library("dplyr")
snp_ids %>% mutate(window_15000=as.numeric(paste(chr, ceiling(pos/15000), sep=".")),
                   window_30000=as.numeric(paste(chr, ceiling(pos/30000), sep=".")),
                   window_50000=as.numeric(paste(chr, ceiling(pos/50000), sep=".")),
                   window_100000=as.numeric(paste(chr, ceiling(pos/100000), sep=".")))
$\endgroup$
5
  • 1
    $\begingroup$ This is a bit manual, don't you think? $\endgroup$
    – zx8754
    Nov 21, 2017 at 11:24
  • 1
    $\begingroup$ Manual and clear is easier to debug and understand 6 months later (one could also put most of that in a function to make it shorter). $\endgroup$
    – Devon Ryan
    Nov 21, 2017 at 11:26
  • $\begingroup$ Of course, personal preferences. But if there were 100 windows, that change by 500 bases for each window in 6 month time. $\endgroup$
    – zx8754
    Nov 21, 2017 at 11:45
  • 1
    $\begingroup$ Manual isn’t the problem — having duplication is. If I had to write this code, five times out of ten (at least!) I’d make a typo in at least one of the numbers, leading to mismatches between the column names and their actual values. That’s why we automate. (I’m saying “I” but what I really mean is “the average, competent programmer”; this class of mistakes is incredibly common). $\endgroup$ Nov 22, 2017 at 16:24
  • $\begingroup$ A couple lines of code duplication is a nonissue. If someone neede to add a hundred columns then sure, but for three then trivial intelligibility is more useful. $\endgroup$
    – Devon Ryan
    Nov 22, 2017 at 16:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.