我在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
}
}
答案 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"
)