我正在尝试使用for
循环创建日期向量(格式为字符串不作为日期)。我已经回顾了其他一些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()
声明的构造有关,但我无法弄明白。我确信它非常简单。提前谢谢。
答案 0 :(得分:7)
有什么问题:
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()
完成时,您将start_dates
函数的值分配给for()
,从而覆盖了循环所做的所有艰苦工作。这实际上是正在发生的事情:
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
}
修复此问题但仍有问题;当您在{/ 1}}开始时将第一个日期分配给输出时,j
将为2
,并在在循环中分配之前将其增加。
如果您使j <- 1
从序列1,2,...,n获取值而不是您想要的实际年份,这会更容易。您可以使用i
将年份向量和编入索引作为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])
}
有时循环遍历向量中的实际值(就像你做的那样)而不是它的索引(正如我刚才所做的那样)是有帮助的,但仅限于特定情况。对于像这里一样的一般操作,这只是一个需要解决的额外复杂功能。也就是说,考虑在使用循环之前在R中进行向量化操作。
答案 1 :(得分: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"