【问题标题】:Create vector of character strings in R using for loop使用for循环在R中创建字符串向量
【发布时间】:2015-01-28 17:38:13
【问题描述】:

我正在尝试使用for 循环创建一个日期向量(格式化为字符串not 作为日期)。我已经查看了其他一些 SO 问题,例如 (How to create a vector of character strings using a loop?),但它们没有帮助。我创建了以下for 循环:

start_dates <- c("1993-12-01")
j <- 1
start_dates <- for(i in 1994:as.numeric(format(Sys.Date(), "%Y"))){
                   date <- sprintf("%s-01-01", i)
                   j <- j + 1
                   start_dates[j] <- date  
               }

但是,它返回一个NULL (empty) 向量start_dates。当我手动增加i 索引时,它可以工作。例如:

> years <- 1994:as.numeric(format(Sys.Date(), "%Y"))
> start_dates <- c("1993-12-01")
> j <- 1
> i <- years[1]
> date <- sprintf("%s-01-01", i)
> j <- j + 1
> start_dates[j] <- date
> start_dates
[1] "1993-12-01" "1994-01-01"
> i <- years[2]
> date <- sprintf("%s-01-01", i)
> j <- j + 1
> start_dates[j] <- date
> start_dates
[1] "1993-12-01" "1994-01-01" "1995-01-01"

这一定与我的for() 语句的构造有关,但我想不通。我敢肯定这非常简单。提前致谢。

【问题讨论】:

    标签: r for-loop


    【解决方案1】:

    有什么问题:

    sprintf("%s-01-01", 1994:2015)
    
    > sprintf("%s-01-01", 1994:2015)
     [1] "1994-01-01" "1995-01-01" "1996-01-01" "1997-01-01" "1998-01-01"
     [6] "1999-01-01" "2000-01-01" "2001-01-01" "2002-01-01" "2003-01-01"
    [11] "2004-01-01" "2005-01-01" "2006-01-01" "2007-01-01" "2008-01-01"
    [16] "2009-01-01" "2010-01-01" "2011-01-01" "2012-01-01" "2013-01-01"
    [21] "2014-01-01" "2015-01-01"
    

    sprintf() 完全矢量化,利用这一点。

    你的循环有问题

    主要问题是当for() 完成时,您将for() 函数的值分配给start_dates,因此覆盖了循环所做的所有艰苦工作。这实际上就是正在发生的事情:

    j <- 1
    foo <- for (i in 1:10) {
      j <- j + 1
    }
    foo
    
    > foo
    NULL
    

    阅读?'for',我们发现这种行为是设计使然:

    Value:
    
         ....
    
         ‘for’, ‘while’ and ‘repeat’ return ‘NULL’ invisibly.
    

    解决方法:不要分配for()的返回值。因此模板可能是:

    for(i in foo) {
      # ... do stuff
      start_dates[j] <- bar
    }
    

    解决这个问题,你仍然有问题; j 将是 2 在您以 j &lt;- 1 开头并在循环中分配之前将第一个日期分配给输出时增加它之前

    如果您让i 从序列 1、2、...、n 中获取值,而不是您想要的实际年份,这会更容易。您也可以使用i 来索引年份向量 作为start_dates 元素的索引。

    不是说你应该这样循环,但是,如果你也想要...

    years <- seq.int(1994, 2015)
    start_dates <- numeric(length = length(years))
    for (i in seq_along(years)) {
      start_dates[i] <- sprintf("%s-01-01", years[i])
    }
    

    这会给:

    > start_dates
     [1] "1994-01-01" "1995-01-01" "1996-01-01" "1997-01-01" "1998-01-01"
     [6] "1999-01-01" "2000-01-01" "2001-01-01" "2002-01-01" "2003-01-01"
    [11] "2004-01-01" "2005-01-01" "2006-01-01" "2007-01-01" "2008-01-01"
    [16] "2009-01-01" "2010-01-01" "2011-01-01" "2012-01-01" "2013-01-01"
    [21] "2014-01-01" "2015-01-01"
    

    有时循环遍历向量中的实际值(就像您所做的那样)而不是它的索引(就像我刚才所做的那样)是有帮助的,但仅在特定情况下。对于您在此处进行的一般操作,这只是您需要解决的额外复杂问题。也就是说,在使用循环之前,请考虑在 R 中进行矢量化操作。

    【讨论】:

    • 很好的建议。让它变得比它需要的更难。 @LyzanderR 直接解决了我的编程错误,但你的对于我的特定问题来说是一个更好的解决方案。谢谢。
    • 我同意乌苏斯。这个很好的解决方案。
    • 我也注意到了真正的错误;查看我的编辑,但主要是不要for() 调用的结果分配给start_dates,这只会抹去你在循环运行时所做的一切。
    【解决方案2】:

    您不应该将循环分配给变量。做:

    start_dates <- c("1993-12-01")
    j <- 1
    for(i in 1994:as.numeric(format(Sys.Date(), "%Y"))){ #use the for-loop on its own. Don't assign it to a variable
      date <- sprintf("%s-01-01", i )
      j <- j + 1
      start_dates[j] <- date  
    }
    

    你很好:

    > start_dates
     [1] "1993-12-01" "1994-01-01" "1995-01-01" "1996-01-01" "1997-01-01" "1998-01-01" "1999-01-01" "2000-01-01" "2001-01-01"
    [10] "2002-01-01" "2003-01-01" "2004-01-01" "2005-01-01" "2006-01-01" "2007-01-01" "2008-01-01" "2009-01-01" "2010-01-01"
    [19] "2011-01-01" "2012-01-01" "2013-01-01" "2014-01-01" "2015-01-01"
    

    【讨论】:

    • 没关系。它发生在每个人身上:)
    • 注意 j 仍将关闭 1,因为第一次迭代将使用 j = 2,因为在分配完成之前增加了 j。在循环外设置j &lt;- 0 或交换循环代码的最后两行将纠正此问题。
    • @GavinSimpson 我认为这是 OP 故意这样做的,因为他希望值 c("1993-12-01") 成为他列表中的第一个元素,除非我弄错了。
    • 我明白了;那么,还有另一个问题:永远不要在 R 循环中增长对象 :-)(是的,我错过了初始分配,抱歉。)
    • @GavinSimpson 没关系。我也不确定。无论如何,你的答案是一个很好且内容丰富的答案。
    猜你喜欢
    • 1970-01-01
    • 2015-11-23
    • 1970-01-01
    • 2013-04-14
    • 2013-01-08
    • 1970-01-01
    • 2018-02-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多