我有一个1600万行的数据帧,我希望在现有列Month的基础上添加一列。如果月份是3、4或5,则列"季节"将是春季等。
for (i in 1:nrow(df)) {
if (df$Month[[i]] %in% c(3,4,5)) {
df$Season[[i]] <- "Spring"
} else if (df$Month[[i]] %in% c(6,7,8)) {
df$Season[[i]] <- "Summer"
} else if (df$Month[[i]] %in% c(9,10,11)) {
df$Season[[i]] <- "Autumn"
} else if (df$Month[[i]] %in% c(12,1,2)) {
df$Season[[i]] <- "Winter"
}
}
然而,它要花很长时间才能完成。我能做什么?
一种更简单、更快的方法是创建一个月份和季节的数据框架,然后将其连接到父数据框架。
像这样:
seasons<-data.frame(Month=1:12, Season=c("Winter", "Winter", rep("Spring", 3), rep("Summer", 3), rep("Autumn", 3), "Winter"))
answer <- dplyr::left_join(df, seasons)
这是假设两个数据帧都具有匹配的列名";月份";。
我预计for
循环的性能将提高1000倍左右。
这更符合@Dave2e的线条,但带有碱基R:
Season=c("Winter", "Winter", rep("Spring", 3),
rep("Summer", 3), rep("Autumn", 3), "Winter")
df<-data.frame(month=sample(1:12,10,replace=T)) #Sample data
df$season<-Season[df$month]
df
# month season
#1 8 Summer
#2 8 Summer
#3 5 Spring
#4 7 Summer
#5 2 Winter
#6 4 Spring
#7 12 Winter
#8 7 Summer
#9 11 Autumn
#10 1 Winter
这一方法明显快于for
循环方法。
使用for
循环(1000行(:
#user system elapsed
#0.02 0.00 0.02
使用矢量化方法(1000行(:
#user system elapsed
# 0 0 0
使用system.time
计算。
考虑到只有1000行,这种差异可能看起来微不足道。然而,随着行数的增加(在OP的情况下,为1600万(,差异变得非常大