[英]How do I calculate a monthly rate of change from a daily time series in R?
I'm beginning to get my feet wet with R, and I'm brand new to time series concepts. 我开始用R弄湿自己,我对时间序列概念不熟悉。 Can anyone point me in the right direction to calculate a monthly % change, based on a daily data point? 任何人都可以指出我正确的方向来计算每月的%变化,基于每日数据点? I want the change between the first and last data points of each month. 我想要在每个月的第一个和最后一个数据点之间进行更改。 For example: 例如:
tseries data: tseries数据:
1/1/2000 10.00
...
1/31/2000 10.10
2/1/2000 10.20
...
2/28/2000 11.00
I'm looking for a return data frame of the form: 我正在寻找表单的返回数据框:
1/31/2000 .01
2/28/2000 .0784
Ideally, I'd be able to calculate from the endpoint of the prior month to the endpoint of current month, but I'm supposing partitioning by month is easier as a starting point. 理想情况下,我能够从上个月的端点计算到当月的端点,但我认为按月分区更容易作为起点。 I'm looking at packages zoo and xts, but am still stuck. 我正在看包裹动物园和xts,但我仍然卡住了。 Any takers? 任何接受者? Thanks... 谢谢...
Here's one way to do it using plyr
and ddply
. 这是使用plyr
和ddply
完成它的一种方法。 I use ddply sequentially, first to get the first and last rows of each month, and again to calculate the monthlyReturn. 我按顺序使用ddply,首先获取每个月的第一行和最后一行,然后再次计算每月返回。 (Perhaps using xts or zoo might be easier, I am not sure.) (也许使用xts或动物园可能会更容易,我不确定。)
#Using plyr and the data in df
df$Date <- as.POSIXlt(as.Date(df$Date, "%m/%d/%Y"))
df$Month <- (df$Date$mon + 1) #0 = January
sdf <- df[,-1] #drop the Date Column, ddply doesn't like it
library("plyr")
#this function is called with 2 row data frames
monthlyReturn<- function(df) {
(df$Value[2] - df$Value[1])/(df$Value[1])
}
adf <- ddply(sdf, .(Month), function(x) x[c(1, nrow(x)), ]) #get first and last values for each Month
mon.returns <- ddply(adf, .(Month), monthlyReturn)
Here's the data I used to test it out: 这是我用来测试它的数据:
> df
Date Value
1 1/1/2000 10.0
2 1/31/2000 10.1
3 2/1/2000 10.2
4 2/28/2000 11.0
5 3/1/2000 10.0
6 3/31/2000 24.1
7 5/10/2000 510.0
8 5/22/2000 522.0
9 6/04/2000 604.0
10 7/03/2000 10.1
11 7/30/2000 7.2
12 12/28/2000 11.0
13 12/30/2000 3.0
> mon.returns
Month V1
1 1 0.01000000
2 2 0.07843137
3 3 1.41000000
4 5 0.02352941
5 6 0.00000000
6 7 -0.28712871
7 12 -0.72727273
Hope that helps. 希望有所帮助。
Here is another way to do this(using the quantmod package): 这是另一种方法(使用quantmod包):
This calculates the monthly return from the daily price of AAPL. 这将计算AAPL每日价格的月度回报。
*library(quantmod) # load the quantmod package
getSymbols("AAPL") # download daily price for stock AAPL
monthlyReturn = periodReturn(AAPL,period="monthly")
monthlyReturn2014 = periodReturn(AAPL,period="monthly",subset='2014:') # for 2014*
This is a pretty old thread, but for reference, here comes a data.table
solution using same data as @Ram: 这是一个非常古老的线程,但作为参考,这里有一个使用与@Ram相同数据的data.table
解决方案:
structure(list(Date = structure(c(10957, 10987, 10988, 11015, 11017, 11047, 11087, 11099, 11112, 11141, 11168, 11319, 11321), class = "Date"), Value = c(10, 10.1, 10.2, 11, 10, 24.1, 510, 522, 604, 10.1, 7.2, 11, 3)), .Names = c("Date", "Value"), row.names = c(NA, -13L), class = c("data.table", "data.frame"), .internal.selfref = <pointer: 0x00000000001b0788>)
It's essentially a one-liner that uses the data.table::month
function: 它本质上是一个使用data.table::month
函数的data.table::month
:
library(data.table)
setDT(df)[ , diff(Value) / Value[1], by= .(month(Date))]
This will produce the change, relative to the first recorded day in each month. 这将产生相对于每个月的第一个记录日的变化。 If the change relative to the last day is preferred, then the expression in the middle should be changed to diff(Value) / Vale[2]
. 如果首选相对于最后一天的更改,则应将中间的表达式更改为diff(Value) / Vale[2]
。
1) no packages Try this: 1)没有包试试这个:
DF <- read.table(text = Lines)
fmt <- "%m/%d/%Y"
ym <- format(as.Date(DF$V1, format = fmt), "%Y-%m")
ret <- function(x) diff(range(x))/x[1]
ag <- aggregate(V2 ~ ym, DF, ret)
giving: 赠送:
> ag
ym V2
1 2000-01 0.01000000
2 2000-02 0.07843137
We could convert this to "ts"
class, if desired. 如果需要,我们可以将其转换为"ts"
类。 Assuming no missing months: 假设没有错过的月份:
ts(ag$V2, start = 2000, freq = 12)
giving: 赠送:
Jan Feb
2000 0.01000000 0.07843137
2) It's a bit easier if you use the zoo or xts time series packages. 2)如果你使用zoo或xts时间序列包,这会容易一些。 fmt
and ret
are from above: fmt
和ret
来自上方:
library(zoo)
z <- read.zoo(text = Lines, format = fmt)
z.ret <- aggregate(z, as.yearmon, ret)
giving: 赠送:
> z.ret
Jan 2000 Feb 2000
0.01000000 0.07843137
If you already have a data.frame DF
then the read.zoo
statement could be replaced with z <- read.zoo(DF, format = fmt)
or omit the format
arg if the first column is of "Date"
class. 如果您已经有data.frame DF
则read.zoo
语句可以替换为z <- read.zoo(DF, format = fmt)
,如果第一列是"Date"
类,则省略format
arg。
If "ts"
class were desired then use as.ts(z.ret)
如果需要"ts"
类,则使用as.ts(z.ret)
Note: The input Lines
is: 注意:输入Lines
是:
Lines <- "1/1/2000 10.00
1/31/2000 10.10
2/1/2000 10.20
2/28/2000 11.00"
The ROC function in the TTR package will do this. TTR包中的ROC功能将执行此操作。 You can use to.monthly or endpoints() ( From daily time series to weekly time series in R xts object ) first if you will only be looking at monthly behaviour. 如果您只查看月度行为,则可以首先使用to.monthly或endpoints()( 从每日时间序列到R xts对象中的每周时间序列 )。
library(TTR)
# data.monthly <- to.monthly( data, indexAt='periodEnd' ) # if OHLC data
# OR
data.monthly <- data[ endpoints(data, on="months", k=1), ]
data.roc <- ROC(data.monthly, n = 1, type = "discrete")
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.