如何使用 `tempdisagg` 包中的 `td` 命令将每月数据分解为每日数据频率?
Posted
技术标签:
【中文标题】如何使用 `tempdisagg` 包中的 `td` 命令将每月数据分解为每日数据频率?【英文标题】:How can I use the `td` command from the `tempdisagg` package to disaggregate monthly data into daily data frequency? 【发布时间】:2020-04-12 12:27:54 【问题描述】:我有一个每月频率数据,我试图将其分解为每日频率数据。
所以我使用R中tempdisagg
包中的td
命令,使用下面的代码:
dat=ts(data[,2])
result=td(dat~1, conversion = "average", to = "day", method = "chow-lin-maxlog")
然后我收到以下错误消息:
Error in td(dat ~ 1, conversion = "average", to = "day", method = "chow-lin-maxlog") : 'to' argument: unknown character string
我用于dat
的数据如下:
> dput(head(dat))
c(82.47703009, 84.63094431, 70.00659987, 78.81135651, 74.749746,82.95638213)
所以虽然这个数据dat
是每月频率,但开始和结束还没有反映这一点。
实际上,开始日期是 1/1997,结束日期是 9/2019。
我可以帮助我将这个月度数据dat
分解为每日频率数据吗?
【问题讨论】:
Eric,你能提供可用格式的数据吗?请不要发布代码/数据/错误的图像:它不能被复制或搜索 (SEO),它会破坏屏幕阅读器,并且它可能不适合某些移动设备。参考:meta.***.com/a/285557/3358272(和xkcd.com/2116)。请直接包含数据(例如,dput(head(x))
或 data.frame(...)
)。谢谢!
我添加了 dput(head(x)) 东西。现在可以了吗?
这很奇怪。如果我做dput(ts(head(1:50)))
,那么我会得到structure(1:6, .Tsp = c(1, 6, 1), class = "ts")
。您的图像表明您的 dat
是时间序列,但您的 c(...)
不是。这两个dat
s 是一样的吗?
是的,这两个数据是一样的。数据和dat不同。
当我查看tempdisagg.pdf
时,我在任何地方都找不到"daily"
,而to=
说它支持“作为字符串的高频目的地频率(“季度”或“每月") 或标量(例如 2、4、7、12)"。哪里建议支持to="daily"
?你可以试试to=1
吗? (除此之外我真的帮不上什么忙。我不太了解这个包,以为我可以提供一般帮助。)
【参考方案1】:
看起来 tempdisagg 包不允许每月到每天的分解。来自td()
帮助文件的“to”参数:
作为字符串(“季度”或“月度”)或标量(例如 2、4、7、12)的高频目标频率。如果输入序列是 ts 对象,则如果没有给出指示符,则该参数是必需的。如果输入序列是向量,to 必须是表示频率比的标量。
您的错误消息“'to' argument: unknown character string”是因为 to =
参数只接受 ' Quarterly' 或 'monthly' 作为字符串。
这里有一些关于将每月数据分解为每日统计数据堆栈交换的讨论:https://stats.stackexchange.com/questions/258810/disaggregate-monthly-forecasts-into-daily-data
经过一番搜索,似乎没有人一直使用按月到每日分类的数据。 tempdisagg
包似乎能够完成大多数其他人认为可能的事情——每年到每季度或每月,以及一致的甚至倍数的时间段。
埃里克,我在下面添加了一个脚本,据我了解,该脚本应该说明您正在尝试做的事情。
这里我们使用真实定价数据从每日价格 -> 每月价格 -> 每月回报 -> 平均每日回报。
library(quantmod)
library(xts)
library(zoo)
library(tidyverse)
library(lubridate)
# Get price data to use as an example
getSymbols('MSFT')
#This data has more information than we want, remove unwanted columns:
msft <- Ad(MSFT)
#Add new column that acts as an 'indexed price' rather than
# actual price data. This is to show that calculated returns
# don't depend on real prices, data indexed to a value is fine.
msft$indexed <- scale(msft$MSFT.Adjusted, center = FALSE)
#split into two datasets
msft2 <- msft$indexed
msft$indexed <- NULL
#msft contains only closing data, msft2 only contains scaled data (not actual prices)
# move from daily data to monthly, to replicate the question's situation.
a <- monthlyReturn(msft)
b <- monthlyReturn(msft2)
#prove returns based on rescaled(indexed) data and price data is the same:
all.equal(a,b)
# subset to a single year
a <- a['2019']
b <- b['2019']
#add column with days in each month
a$dim <- days_in_month(a)
a$day_avg <- a$monthly.returns / a$dim ## <- This must've been left out
day_avgs <- data.frame(day_avg = rep(a$day_avg, a$dim))
# daily averages timesereis from monthly returns.
z <- zoo(day_avgs$day_avg,
seq(from = as.Date("2019-01-01"),
to = as.Date("2019-12-31"),
by = 1)) %>%
as.xts()
#chart showing they are the same:
PerformanceAnalytics::charts.PerformanceSummary(cbind(a$monthly.returns, z))
这里是三个图表,显示 1. 仅每月回报,2. 每月回报的日平均值,3. 两者一起。由于它们是相同的,因此第三张图像中的过度绘图仅显示了一个。
【讨论】:
就我而言,每月数字是平均值,而不是您的问题帖子询问的总和。例如,我的数据显示 1 月份的平均值为 4%。如果我想转换为每日数据,我目前正在考虑在 1 月 1 日立即使用这 4%,依此类推。但不确定这样做是否仍然可以。 请问您对此案是否有任何想法(正如我发布的问题所询问的那样)? 从您发布的数据中不清楚您有费率,它看起来像价格。您在评论中提到,您 1 月份的平均利率确实为 0.04。如果您要从月平均费率 -> 日平均费率出发,普遍接受的原则是月费率 / 30(我认为)。对于您在 1 月份提到的 0.04 (4%),每日费率为 0.04/30 或 ~.001315。如果你能为我澄清你的问题,那可能会有所帮助。您有价格数据或费率数据吗?你期待的结果是什么?无论哪种方式, id 看起来都不像 tempdisagg 是解决方案。 我发布的数据是以100为基准的月度指数。因为是索引,所以不加起来。 好的。如果您对百分比数据(回报)感兴趣并且拥有定期时间序列中的价格数据,您可以使用quantmod::monthlyReturn
或PerformanceAnalytics::Return.calculate
获取(每月)回报。从那里如果您需要假设每日回报,您可以使用上述(评论)方法。【参考方案2】:
使用 tempdisagg 1.0,可以轻松地将月度数据分解为每日数据,使总和或平均值与月度序列保持一致。
post 更详细地解释了新功能。
A bit of trickery 还可以从每月转换为每周。
这是一个可重现的示例,使用原始帖子的前六个月:
x <- tsbox::ts_tbl(ts(c(82.47703009, 84.63094431, 70.00659987, 78.81135651, 74.749746, 82.95638213), start = 2020, frequency = 12))
x
#> # A tibble: 6 x 2
#> time value
#> <date> <dbl>
#> 1 2020-01-01 82.5
#> 2 2020-02-01 84.6
#> 3 2020-03-01 70.0
#> 4 2020-04-01 78.8
#> 5 2020-05-01 74.7
#> 6 2020-06-01 83.0
library(tempdisagg)
packageVersion("tempdisagg")
#> [1] '1.0'
m <- td(x ~ 1, to = "daily", method = "fast", conversion = "average")
predict(m)
#> # A tibble: 182 x 2
#> time value
#> <date> <dbl>
#> 1 2020-01-01 80.6
#> 2 2020-01-02 80.7
#> 3 2020-01-03 80.7
#> 4 2020-01-04 80.7
#> 5 2020-01-05 80.8
#> 6 2020-01-06 80.8
#> 7 2020-01-07 80.9
#> 8 2020-01-08 81.0
#> 9 2020-01-09 81.1
#> 10 2020-01-10 81.2
#> # … with 172 more rows
由reprex package (v2.0.0) 于 2021 年 7 月 15 日创建
【讨论】:
以上是关于如何使用 `tempdisagg` 包中的 `td` 命令将每月数据分解为每日数据频率?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用jQuery将Class添加到表内每个tr中的第一个td