使用for循环在R中创建字符串向量

Urs*_*ost 3 for-loop r

我正在尝试使用循环创建日期向量(格式化为字符串而不是日期)for.我已经回顾了其他一些SO问题,例如(如何使用循环创建字符串向量?),但它们没有帮助.我创建了以下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  
               }
Run Code Online (Sandbox Code Playgroud)

但是,它返回一个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"
Run Code Online (Sandbox Code Playgroud)

它必须与我的for()陈述的构造有关,但我无法弄清楚.我确信它非常简单.提前致谢.

Rei*_*son 8

出什么问题了:

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"
Run Code Online (Sandbox Code Playgroud)

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

你的循环问题

主要的问题是,你分配的价值for()功能,start_datesfor()完成的,因此,覆盖所有的努力你的循环一样.这实际上是发生了什么:

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

> foo
NULL
Run Code Online (Sandbox Code Playgroud)

阅读?'for'我们看到这种行为是设计的:

Value:

     ....

     ‘for’, ‘while’ and ‘repeat’ return ‘NULL’ invisibly.
Run Code Online (Sandbox Code Playgroud)

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

for(i in foo) {
  # ... do stuff
  start_dates[j] <- bar
}
Run Code Online (Sandbox Code Playgroud)

解决这个问题,你仍然有问题; j将在2您开始时将第一个日期分配给输出j <- 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])
}
Run Code Online (Sandbox Code Playgroud)

这会给:

> 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"
Run Code Online (Sandbox Code Playgroud)

有时循环遍历向量中的实际值(就像你做的那样)而不是它的索引(正如我刚才所做的那样)是有帮助的,但仅限于特定情况.对于像这里一样的一般操作,这只是一个需要解决的额外复杂功能.也就是说,考虑在使用循环之前在R中进行向量化操作.