2、原始数据 原始文件我已经整理好了,记录了*万科*,*国农科技*,*世纪星源*和*深振业A*这四只股票从2014年一季度到2017年三季度,利润表里“营业总收入”的数据(单位:万元)。每只个股有15条记录,合计60行数据。数据结构如下:##'data.frame': 60obs.of 3variables:## $季度 :chr "2017-09-30""2017-06-30"...## $名称 :chr "万科""万科""万科""万科"...## $营业总收入:int 1171005069810481858923...以万科为例,具体内容如下:data[data$名称=="万科",]## 季度名称营业总收入##1 2017-09-30万科 11710050##2 2017-06-30万科 6981048##3 2017-03-31万科 1858923##4 2016-12-31万科 24047724##5 2016-09-30万科 11705480##6 2016-06-30万科 7479529##7 2016-03-31万科 1461131##8 2015-12-31万科 19554913##9 2015-09-30万科 7959621##102015-06-30万科 5026680##112015-03-31万科 889434##122014-12-31万科 14638800##132014-09-30万科 6313959##142014-06-30万科 4096190##152014-03-31万科 949722我们看到,每只个股按照时间倒序排列,营业总收入是一个累计值。比如,表中显示万科在2017年3季度的营业收入为11710050(万元),2季度的营业收入为6981048(万元),那么万科2017年3季度的营业收入世纪发生额为11710050-6981048=4729002万元。我们的目的是在原始数据的基础之上,再加一列,把单季度的发生额加在后面。3、处理过程3.1、数据切分原始数据里有4只股票,他们的数据结构是一致的,处理方法也一致,为了方便处理,把原始数据从数据框切成列表。在dataframe上使用split,可以将dataframe按照指定的条件切成一个个列表。示例如下:data<-split(data,data$名称) #数据类型class(data)##[1]"list"#列表名称names(data)##[1]"国农科技""深振业A" "世纪星源""万科"#第一个列表内容data[[1]]## 季度 名称营业总收入##162017-09-30国农科技 7100##172017-06-30国农科技 2929##182017-03-31国农科技 1087##192016-12-31国农科技 28767##202016-09-30国农科技 21757##212016-06-30国农科技 10215##222016-03-31国农科技 1348##232015-12-31国农科技 12045##242015-09-30国农科技 8889##252015-06-30国农科技 5955##262015-03-31国农科技 2094##272014-12-31国农科技 8061##282014-09-30国农科技 4842##292014-06-30国农科技 2743##302014-03-31国农科技 1130这样数据从dataframe切分成了4个列表,分别对应每一只个股。3.2、数据处理df<-data[[1]]df$季度<-as.Date(df$季度)df<-as.xts(df[-c(1,2)],order.by=df$季度)class(df)##[1]"xts""zoo"df## 营业总收入##2014-03-31 1130##2014-06-30 2743##2014-09-30 4842##2014-12-31 8061##2015-03-31 2094##2015-06-30 5955##2015-09-30 8889##2015-12-31 12045##2016-03-31 1348##2016-06-30 10215##2016-09-30 21757##2016-12-31 28767##2017-03-31 1087##2017-06-30 2929##2017-09-30 7100时间序列只能处理数值型的数据,数据转化成时间序列后,原来数据框中的日期和名称都消失了。要在后面在加上去。现在开始计算单季数据,只要拿当前的值减去上期的值即可。在时间序列了,可以使用DIFF差分函数来实现,diff(x,n),表示将当前值减去N个周期前的值。默认n=1.将处理后的数据合并会原来的数据。并把日期加上去。datadiff<-diff(df)datanew<-as.data.frame(merge(df,datadiff))datanew<-cbind(row.names(datanew),datanew)colnames(datanew)<-c("季度","营业总收入","营业总收入单季")datanew##季度营业总收入营业总收入单季##2014-03-31 1130 NA##2014-06-30 2743 1613##2014-09-30 4842 2099##2014-12-31 8061 3219##2015-03-31 2094 -5967##2015-06-30 5955 3861##2015-09-30 8889 2934##2015-12-31 12045 3156##2016-03-31 1348 -10697##2016-06-30 10215 8867##2016-09-30 21757 11542##2016-12-31 28767 7010##2017-03-31 1087 -27680##2017-06-30 2929 1842##2017-09-30 7100 4171注意到这个结果还有一个问题,一个是一季度的数据不需要减去上期值,一季度的单季数值等于累计值。所以数据还要处理一下。#quarter方法来自lubridate包,可以传入文本判断季度datanew[quarter(datanew$季度)==1,3]=datanew[quarter(datanew$季度)==1,2]DataPrc<-function(x){#转成时间序列x$季度<-as.Date(x$季度)StkNam<-as.character(x$名称[1])x<-as.xts(x[-c(1,2)],order.by=x$季度)#利用差分计算单期值并合并x.diff<-diff(x)x.new<-as.data.frame(merge(x,x.diff))x.new<-cbind(row.names(x.new),StkNam,x.new)colnames(x.new)<-c("季度","名称","营业总收入","营业总收入单季")#处理特殊情况#quarter方法来自lubridate包,可以传入文本判断季度x.new[quarter(x.new$季度)==1,4]=x.new[quarter(x.new$季度)==1,3]x.new}stkdata<-lapply(data,DataPrc)stkdata##$国农科技## 季度 名称营业总收入营业总收入单季##2014-03-312014-03-31国农科技 1130 1130##2014-06-302014-06-30国农科技 2743 1613##2014-09-302014-09-30国农科技 4842 2099##2014-12-312014-12-31国农科技 8061 3219##2015-03-312015-03-31国农科技 2094 2094##2015-06-302015-06-30国农科技 5955 3861##2015-09-302015-09-30国农科技 8889 2934##2015-12-312015-12-31国农科技 12045 3156##2016-03-312016-03-31国农科技 1348 1348##2016-06-302016-06-30国农科技 10215 8867##2016-09-302016-09-30国农科技 21757 11542##2016-12-312016-12-31国农科技 28767 7010##2017-03-312017-03-31国农科技 1087 1087##2017-06-302017-06-30国农科技 2929 1842##2017-09-302017-09-30国农科技 7100 4171##$深振业A## 季度 名称营业总收入营业总收入单季##2014-03-312014-03-31深振业A 26292 26292##2014-06-302014-06-30深振业A 49149 22857##2014-09-302014-09-30深振业A 64985 15836##2014-12-312014-12-31深振业A 232873 167888##2015-03-312015-03-31深振业A 138923 138923##2015-06-302015-06-30深振业A 202261 63338##2015-09-302015-09-30深振业A 230546 28285##2015-12-312015-12-31深振业A 365431 134885##2016-03-312016-03-31深振业A 38249 38249##2016-06-302016-06-30深振业A 86869 48620##2016-09-302016-09-30深振业A 114571 27702##2016-12-312016-12-31深振业A 335883 221312##2017-03-312017-03-31深振业A 116791 116791##2017-06-302017-06-30深振业A 186960 70169##2017-09-302017-09-30深振业A 231926 44966####$世纪星源## 季度 名称营业总收入营业总收入单季##2014-03-312014-03-31世纪星源 1218 1218##2014-06-302014-06-30世纪星源 2386 1168##2014-09-302014-09-30世纪星源 3585 1199##2014-12-312014-12-31世纪星源 5278 1693##2015-03-312015-03-31世纪星源 1349 1349##2015-06-302015-06-30世纪星源 3629 2280##2015-09-302015-09-30世纪星源 4576 947##2015-12-312015-12-31世纪星源 8413 3837##2016-03-312016-03-31世纪星源 4342 4342##2016-06-302016-06-30世纪星源 18995 14653##2016-09-302016-09-30世纪星源 35050 16055##2016-12-312016-12-31世纪星源 48186 13136##2017-03-312017-03-31世纪星源 7145 7145##2017-06-302017-06-30世纪星源 20360 13215##2017-09-302017-09-30世纪星源 31423 11063##$万科## 季度名称营业总收入营业总收入单季##2014-03-312014-03-31万科 949722 949722##2014-06-302014-06-30万科 4096190 3146468##2014-09-302014-09-30万科 6313959 2217769##2014-12-312014-12-31万科 14638800 8324841##2015-03-312015-03-31万科 889434 889434##2015-06-302015-06-30万科 5026680 4137246##2015-09-302015-09-30万科 7959621 2932941##2015-12-312015-12-31万科 19554913 11595292##2016-03-312016-03-31万科 1461131 1461131##2016-06-302016-06-30万科 7479529 6018398##2016-09-302016-09-30万科 11705480 4225951##2016-12-312016-12-31万科 24047724 12342244##2017-03-312017-03-31万科 1858923 1858923##2017-06-302017-06-30万科 6981048 5122125##2017-09-302017-09-30万科 11710050 47290024、合并以上结果显示数据都是列表,把它们合成一个数据框。方便后续处理。你当然可以选择使用循环将列表合并,但R里处理循环的效率实在无法恭维。这里有个更好的办法,代码如下:result<-do.call(rbind,stkdata)rownames(result)<-NULLhead(result[result$名称=="世纪星源",],2)#季度 名称营业总收入营业总收入单季##2014-03-31世纪星源 1218 1218##2014-06-30世纪星源 2386 1168do.call()是告诉列表一个函数,让列表里的所有元素来执行这个函数。将其用于列表合并,效果比循环好太多。这样,我们就把数据整理完毕了。这种差分的数据处理方法,在很多场景都有应用。比如运营上拿到了一系列周期上的指标数值,都同时会看看同比、环比的增减情况。这些数据使用传统的数据结构,使用传统的数据处理方法,计算脚本都是很复杂的,而把数据转化成时间序列后,这些处理的过程都可以用简单的方法解决。另外,在使用R进行数据分析时,应该利用这种向量化语言的特点,用向量化的方法处理数据。