用R中的矢量化函数用if语句替换for循环

时间:2019-05-28 16:08:02

标签: r for-loop apply

我在for循环中遇到了一些麻烦,该循环包含许多条件并运行了很长时间(由于数据帧的大小)。因此,我想用apply系列的矢量化功能代替它。我有一个格式为month / year的变量,并且想定义一个year变量,具体取决于月份是小于还是等于10(十月),即被定义为非常年份,或者大于10,即是年份+ 1(例如09/2001 = 2001,而12/2001 = 2002)。日期变量包含一些NA。下面,我给出了数据框的简化版本,包括我应用的for循环。对于矢量化功能的任何提示将不胜感激。

示例数据集:

d <- data.frame("10/2010")
names(d) <- "data"
d$data <- as.character(d$data)
d <- rbind(d, "11/2010","12/2009","08/2008", NA)

循环:

d$ano <- NA
for(i in 1:length(d$data)){
  month <- as.numeric(substring(d$data[i],1,2))
  if(!is.na(d$data[i]) & month <=10){
    d$ano[i] <- substring(d$data[i],4,7)
  }
  if(!is.na(d$data[i]) & month >10){
      d$ano[i] <- as.numeric(substring(d$data[i],4,7))+1
  }
}

3 个答案:

答案 0 :(得分:2)

您可以执行此操作,例如与ifelse

d$ano <- as.numeric(substring(d$data,4,7)) + ifelse(as.numeric(substring(d$data,1,2)) <= 10, 0, 1)

或根据Andrew Gustar的评论,使用TRUE为1且FALSE为0的事实:

d$ano <- as.numeric(substring(d$data,4,7)) + (as.numeric(substring(d$data,1,2)) > 10)

答案 1 :(得分:1)

1)将其转换为yearmon类,表示年和月为年份+ 1月1日+ 2月1/12 + 3月2/12年+1/12以此类推。然后加上2个月,即2/12,然后加上年份。

library(zoo)

transform(d, ano = as.integer(as.yearmon(data, format = "%m/%Y") + 2/12))

给予:

     data  ano
1 10/2010 2010
2 11/2010 2011
3 12/2009 2010
4 08/2008 2008
5    <NA>   NA

2)或者,也可以使用POSIXlt在基数R中完成此操作,并指出在这种情况下,我们必须向year组件添加偏移量1900,向{{1} } 零件。在这种情况下,如果mon + 1超过10,则在年份中加1。

mon

3)另一个基本的R解决方案是使用transform(d, ano = with(as.POSIXlt(paste(data, 1), format = "%m/%Y %d"), year + 1900 + (mon + 1 > 10))) 读取data并从中操纵月份和年份:

read.table

答案 2 :(得分:1)

dplyr / tidyr解决方案:

library(tidyverse)

dat %>%
  separate(data, c('month', 'year'), '/', convert = T) %>%
  transmute(ano = year + (month > 10)) %>%
  bind_cols(dat, .)

#      data  ano
# 1 10/2010 2010
# 2 11/2010 2011
# 3 12/2009 2010
# 4 08/2008 2008
# 5    <NA>   NA

数据:

dat <- structure(
  list(data = c("10/2010", "11/2010", "12/2009", "08/2008", NA)),
  row.names = c(NA,-5L),
  class = "data.frame"
  )