简体   繁体   中英

Multiple loop to create a list of combinations

I tried to use a loop to create a list of combinations, but I 'm not getting all the iterations and it's generating a smaller number than I expected. The code that I'm using:

base = "http://sigtap.datasus.gov.br/r"
    codes = list(304020060, 304050083, 304010308, 304070017, 304010081, 304020184, 304050040, 304040045, 304010308, 304030074, 304020338, 304020079, 304040134, 304010081)      #14 different codes 
    month = c("01", "02", "03", "04","05","06","07","08", "09", "10", "11","12")
    year = c(2015:2018)


  for (i in base) {
    for(j in codes){
      for (k in month) {
        for (l in year) {
          html <-  paste(i, j, k, l, sep = "/" )
    }}}}

I was expecting to get one record for code, month and year (around 670 different records), but I'm only getting 14:

 [1] "http://sigtap.datasus.gov.br/app/sec/304020060/12/2015"
 [2] "http://sigtap.datasus.gov.br/app/sec/304050083/12/2016"
 [3] "http://sigtap.datasus.gov.br/app/sec/304010308/12/2017"
 [4] "http://sigtap.datasus.gov.br/app/sec/304070017/12/2018"
 [5] "http://sigtap.datasus.gov.br/app/sec/304010081/12/2015"
 [6] "http://sigtap.datasus.gov.br/app/sec/304020184/12/2016"
 [7] "http://sigtap.datasus.gov.br/app/sec/304050040/12/2017"
 [8] "http://sigtap.datasus.gov.br/app/sec/304040045/12/2018"
 [9] "http://sigtap.datasus.gov.br/app/sec/304010308/12/2015"
[10] "http://sigtap.datasus.gov.br/app/sec/304030074/12/2016"
[11] "http://sigtap.datasus.gov.br/app/sec/304020338/12/2017"
[12] "http://sigtap.datasus.gov.br/app/sec/304020079/12/2018"
[13] "http://sigtap.datasus.gov.br/app/sec/304040134/12/2015"
[14] "http://sigtap.datasus.gov.br/app/sec/304010081/12/2016"

Any help would be great!

Thanks!

You can speed your code up using do.call

out <- do.call(paste, c(base, expand.grid(codes, month, year), sep = "/"))
head(out)
#[1] "http://sigtap.datasus.gov.br/r/304020060/01/2015"
#[2] "http://sigtap.datasus.gov.br/r/304050083/01/2015"
#[3] "http://sigtap.datasus.gov.br/r/304010308/01/2015"
#[4] "http://sigtap.datasus.gov.br/r/304070017/01/2015"
#[5] "http://sigtap.datasus.gov.br/r/304010081/01/2015"
#[6] "http://sigtap.datasus.gov.br/r/304020184/01/2015"

Check the number of elements

length(out)
#[1] 672

Since base is a constant there is no need to put it in expand.grid

This works just fine, remember to save each iteration and not overwrite it.

base = "http://sigtap.datasus.gov.br/r"
    codes = list(304020060, 304050083, 304010308, 304070017, 304010081, 304020184, 304050040, 304040045, 304010308, 304030074, 304020338, 304020079, 304040134, 304010081)      #14 different codes 
    month = c("01", "02", "03", "04","05","06","07","08", "09", "10", "11","12")
    year = c(2015:2018)
    html=list()
    iteration=1


  for (i in base) {
    for(j in codes){
      for (k in month) {
        for (l in year) {
          html[[iteration]] <-  paste(i, j, k, l, sep = "/" )
          iteration<-iteration+1

    }}}}

 > length(html)
[1] 672

It seems to me that you are trying to create a list of html strings from your vectors. This can be done quite simply.

From base, we can create a matrix with all combinations using the function expand.grid

combs <- expand.grid(base, codes, month, year)

following this we could create each string using an apply function applying over the first margin ( MARGIN = 1 is the same as iterating over rows of a matrix). For each row we want to perform the same paste as your

html <- apply(combs, 
              MARGIN = 1, 
              FUN = function(x)paste(x, collapse = "/"))

And your done. Basically the apply function takes the place of the loop. Notice that i've replace the sep = "/" argument of paste with a collapse = "/" argument. This is due to the fact that i am pasting a vector (each row in combs ). Thus i am collapsing the matrix, not removing separation.

It seems like you are missing indices in html <- paste(...) . The way you have it, each iteration overwrites the previous html .

However, this would be clearer if you create a data.frame or data.table :

library(data.table)
Base = "http://sigtap.datasus.gov.br/r"
Code = c(304020060, 304050083, 304010308, 304070017, 304010081, 304020184,
          304050040, 304040045, 304010308, 304030074, 304020338, 304020079,
          304040134, 304010081)
Mnth = c(paste0(0, 1:9), 10:12)
Year = c(2015:2018)
Combinations <- data.table(base = rep("http://sigtap.datasus.gov.br", times = 14 * 12 * 4),
                           code = rep(Code, each = 12 * 4),
                           month= rep(Mnth, each = 14 * 4),
                           year = rep(Year, each = 14 * 12))
Combinations[, URL := paste0(base, code, month, year)]

It's personal preference, but I try to avoid for loops unless extremely necessary. It is also good practice to not use the same name for objects and base functions. For example, month is a function that gets the month from a date. That's the reason I renamed base , code , month and year .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM