【问题标题】:Multiple loop to create a list of combinations多重循环创建组合列表
【发布时间】:2019-02-21 22:55:27
【问题描述】:

我尝试使用循环来创建一个组合列表,但我没有得到所有的迭代,而且它生成的数字比我预期的要小。 我正在使用的代码:

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 = "/" )
    }}}}

我希望获得一条代码、月份和年份记录(大约 670 条不同的记录),但我只获得了 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"

任何帮助都会很棒!

谢谢!

【问题讨论】:

  • 您能否让您的问题可重现(它几乎可以重现,但缺少codes)。还可以考虑创建一个 minimal 示例。我确信没有必要发布 14 个不同的代码、12 个月……来了解全局。
  • 您的输出中只有一个月 - "12"。你确定你的month 向量是你认为的那样吗?此外,在不使用多个 for 循环的情况下,查看 ?expand.grid 之类的内容可能会很方便。
  • 试试apply(expand.grid(base, codes, month, year), 1, paste, collapse = "/")
  • 我可能弄错了,但你是如何获得多个值的?你不是每次迭代都覆盖html,而不是添加它吗?
  • Markus,我正在尝试使用此循环从该网站收集数据。这些代码是多年来我需要更仔细地查看的“疾病”代码

标签: r loops combinations


【解决方案1】:

您可以使用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"

检查元素的数量

length(out)
#[1] 672

由于base 是一个常量,因此无需将其放入expand.grid

【讨论】:

    【解决方案2】:

    这很好用,记住保存每个迭代而不是覆盖它。

    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
    

    【讨论】:

    • @AngélicaCarreira 没问题,这可行,但其他一些答案更适合效率和简单性,请检查它们,看看它们是否适合您。
    【解决方案3】:

    在我看来,您正在尝试从您的向量创建一个 html 字符串列表。这可以很简单地完成。

    从基础,我们可以使用函数expand.grid创建一个包含所有组合的矩阵

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

    在此之后,我们可以使用应用函数在第一个边距上创建每个字符串(MARGIN = 1 与遍历矩阵的行相同)。对于每一行,我们要执行与您的相同的粘贴

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

    你完成了。基本上,apply 函数代替了循环。请注意,我已将 paste 的 sep = "/" 参数替换为 collapse = "/" 参数。这是因为我正在粘贴一个向量(combs 中的每一行)。因此,我正在折叠矩阵,而不是删除分离。

    【讨论】:

      【解决方案4】:

      您似乎缺少html &lt;- paste(...) 中的索引。按照您的方式,每次迭代都会覆盖之前的 html。

      但是,如果您创建 data.frame 或 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)]
      

      这是个人喜好,但除非非常必要,否则我会尽量避免使用 for 循环。最好不要为对象和基本函数使用相同的名称。例如,month 是一个从日期获取月份的函数。这就是我重命名base、code、month 和year 的原因。

      【讨论】:

      • 地狱阿图罗,我建议使用CJ(base, code, month, year)。这将像 expand.grid 一样扩展基本包中的向量,同时将您的数据转换为 data.table。因此,CJ(base = base, code = code, month = month, year = year)[, html = paste(base, code, month, year, sep = "/")] 将完成同样的工作,但速度更快、效率更高。
      • data.table 我相信它可能必须在 2 行中。
      猜你喜欢
      • 1970-01-01
      • 2013-07-16
      • 1970-01-01
      • 2019-08-12
      • 1970-01-01
      • 2014-01-24
      • 2021-09-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多