r语言 - 如何根据日期月份变量 (YYYYMMDD) 添加虚拟变量 Q1、Q2、Q3?



我想创建 4 个虚拟变量,将每个季度称为 Q1、Q2、Q3、Q4,这将取决于日期格式的销售月份。

像这样:

Date         Q1 Q2 Q3 Q4
01/01/2017    1  0  0  0
02/01/2017    0  1  0  0
03/01/2017    0  0  1  0
04/01/2017    0  0  0  1

我尝试使用lubridate包使用month(Date(提取销售月份,然后尝试在这些行上创建虚拟变量Q1,Q2,Q3,Q4(不完全相同的代码,但尝试使用此逻辑来创建变量(:

df$Q1 <- ifelse(month(Date) = *"first month of every quarter"*,1,0)
df$Q2 <- ifelse(month(Date) = *"second month of every quarter"*,1,0)
df$Q3 <- ifelse(month(Date) = *"third month of every quarter"*,1,0)  
df$Q4 <- ifelse(month(Date) = *"fourth month of every quarter"*,1,0)  

但是这种方法无法获得如上所述的矩阵。

请帮助完成相同的工作,或者如果有更聪明的方法可以完成此操作,请告诉我。

这是使用因子和model.matrix的基本 R 方法。最棘手的部分是正确设置季度因子变量的月份。

假设我们从如下所示的字符向量开始。首先,转换为日期向量。

dates<- as.Date(dates, "%m/%d/%Y")

现在,将其放入 data.frame 并使用factor添加一个 Quarter 变量。

dat <- data.frame(Date=dates,
mnthQrtr=factor(as.integer(format(dates, "%m")) %% 3,
levels=c(1:2, 0), labels=c(paste0("MQ", c(1:3)))))

在这里,模运算符返回值 0 到 3,其中 3 对应于季度中的第四个月,因此 levels 参数必须考虑到这一点。

现在,使用model.matrix创建二进制变量,并使用cbind将它们固定在 .

dat <- cbind(dat, model.matrix(~mnthQrtr-1, dat))

这返回

dat
Date mnthQrtr mnthQrtrMQ1 mnthQrtrMQ2 mnthQrtrMQ3
1 2017-01-01      MQ1           1           0           0
2 2017-02-01      MQ2           0           1           0
3 2017-03-01      MQ3           0           0           1
4 2017-04-01      MQ1           1           0           0

数据

dates <- c("01/01/2017", "02/01/2017", "03/01/2017", "04/01/2017")

我们可以使用tidyverse

library(tidyverse)    
df1 %>%
mutate(Qs = paste0("Q", month(mdy(Date))), ind = 1) %>%        
spread(Qs, ind, fill = 0)
#       Date Q1 Q2 Q3 Q4
#1 01/01/2017  1  0  0  0
#2 02/01/2017  0  1  0  0
#3 03/01/2017  0  0  1  0
#4 04/01/2017  0  0  0  1

数据

df1 <- structure(list(Date = c("01/01/2017", "02/01/2017", "03/01/2017", 
"04/01/2017")), .Names = "Date", row.names = c(NA, -4L), 
class = "data.frame")

编辑:这个问题没有明确说明,OP的意图有不同的解释。现在,OP澄清了他在下面的第二个答案之后。

答案 1

问题从这句话开始:我想创建 4 个虚拟变量,将每个季度称为 Q1、Q2、Q3、Q4,这将取决于日期格式的销售月份加上一个示例矩阵。这可以解释为OP想要确定给定日期所属的季度,并以宽格式"以图形方式"显示此季度。

这可以使用dcast()函数重塑和quarter()函数从lubridate实现:

# create sample data
DF <- data.frame(Date = seq(as.Date("2017-01-01"), length.out = 4, by = "3 months"))
# reshape
data.table::dcast(DF, Date ~ paste0("Q", lubridate::quarter(DF$Date)), length, 
value.var = "Date")
Date Q1 Q2 Q3 Q4
1 2017-01-01  1  0  0  0
2 2017-04-01  0  1  0  0
3 2017-07-01  0  0  1  0
4 2017-10-01  0  0  0  1

dcast()功能可从两个软件包获得:reshape2data.table

答案 2

如果 OP 要求每个季度内的月份编号,即第 1 个月、第 2 个月或第 3 个月,这里有一个替代解决方案,它使用toOrdinal包将基数转换为序数

DF <- data.frame(Date = seq(as.Date("2017-01-01"), length.out = 12, by = "1 months"))
month_in_quarter <- function(x) 
sprintf("%s_M_in_Qtr", sapply((month(x) - 1) %% 3 + 1, toOrdinal::toOrdinal))
data.table::dcast(DF, Date ~ month_in_quarter(Date), length, value.var = "Date")
Date 1st_M_in_Qtr 2nd_M_in_Qtr 3rd_M_in_Qtr
1  2017-01-01            1            0            0
2  2017-02-01            0            1            0
3  2017-03-01            0            0            1
4  2017-04-01            1            0            0
5  2017-05-01            0            1            0
6  2017-06-01            0            0            1
7  2017-07-01            1            0            0
8  2017-08-01            0            1            0
9  2017-09-01            0            0            1
10 2017-10-01            1            0            0
11 2017-11-01            0            1            0
12 2017-12-01            0            0            1

另一个使用伟大的dummies包来创建虚拟变量的选项。只需使用zoo包创建"季度"列。

加载包:

require(dummies)
require(zoo)

创建一些测试数据:

df<-data.frame(date =seq(as.Date("2017/1/1"), as.Date("2017/4/1"), "months"))

创建新的季度列,说明日期属于哪个季度:

df$Quarter<-format(as.yearqtr(df$date), "Q%q") 

为分类变量创建虚拟变量:

df<-dummy.data.frame(df, sep="_")

调整列名称以与问题保持一致:

colnames(df)<-gsub("Quarter_", "", colnames(df))

使用 'dt' 和 'get_dummies':

步骤:

  1. 在包含日期的列上使用"dt.quarter"。
  2. 在步骤 1 中创建的列上使用"get_dummies"。

例:

数据:

df = pd.DataFrame(pd.date_range(start = '2017', periods = 4, freq = 'Q'), columns = ['Dates'])
  1. 新建列
df['Quarter'] = df['Dates'].dt.quarter
  1. 傻瓜
pd.get_dummies(df, columns = ['Quarter'])

最新更新