问题描述
我有一个包含“Period”(即四分之一)和“Percent”的 csv。将数据读入 R 后,“Period”列是“chr”,“Percent”列是“num”。我想将季度值更改为日期,因此:
for (i in 1:length(sloos_tighten$Period)) {
sloos_tighten$Period[i] <- paste("Q",substring(sloos_tighten$Period[i],6),"/",1,4),sep = "")
sloos_tighten$Period[i] <- as.Date(as.yearqtr(sloos_tighten$Period[i],format = "Q%q/%Y"))
}
for 循环中的第一行将季度的格式更改为 as.yearqtr 可读,第二行将季度更改为日期。第一行按预期工作,但第二行将日期转换为四位数字。我认为这是因为“Period”的类型为“chr”,但我不知道如何将其更改为日期。我试图创建一个类型为日期的新列,但我找不到任何在线资源来解释它。任何帮助表示赞赏。提前致谢。
> dput(head(sloos_tighten,10))
structure(list(Period = c("1990:2","1990:3","1990:4","1991:1","1991:2","1991:3","1991:4","1992:1","1992:2","1992:3"),`Large and medium` = c(54.4,46.7,54.2,38.6,20,18.6,16.7,10,3.5,-3.4),Small = c(52.7,33.9,40.7,31.6,6.9,8.8,7,-7.1,-1.7)),row.names = c(NA,10L),class = "data.frame")
^导入后的数据是什么样子
解决方法
文字 for
循环在某种意义上很好,但不幸的是这里有两个问题:
-
这里有一个
class
问题:如果$Period
是一个字符串,那么当你用Date
类的东西重新分配它的一个值时,日期会被转换成字符串。这是因为在 Rdata.frame
中,除了少数例外,列中的所有值都必须是相同的类型。这是因为一列(几乎总是)是一个向量,而 R 将向量视为同质的。您可以通过预先分配
Date
类型的向量并对其进行零散分配来解决此问题:newdate <- rep(Sys.Date()[NA],nrow(sloos_tighten)) # just to get the class right for (i in 1:length(sloos_tighten$Period)) { tmp <- paste("Q",substring(sloos_tighten$Period[i],6),"/",1,4),sep = "") newdate[i] <- as.Date(as.yearqtr(tmp,format = "Q%q/%Y")) }
(但是请不要使用这段代码,先看下面的#2。)
-
本身不是问题,而是效率:R 擅长将事情作为一个整体来处理。如果您一步重新分配所有
$Period
,那么一切都会更快。sloos_tighten$Period <- as.Date( paste0(substring(sloos_tighten$Period,substring(sloos_tighten$Period,4)),format = "%q/%Y")
这从
paste(..,sep="")
切换到paste0
,这是一个方便的函数。然后,它删除了前导"Q"
,因为我们实际上并没有保留它,所以为什么要添加它(除了可能是声明性代码)。最后,它一次处理整个字符串向量。
(这是将数据视而不见,因此未经测试。)