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

时间:2015-01-28 17:38:14

标签: r for-loop

我正在尝试使用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()声明的构造有关,但我无法弄明白。我确信它非常简单。提前谢谢。

2 个答案:

答案 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"