分析数据的第一部是数据清理。首先可以将数据放在图上,看数据是否存在某些特征会使影响分析的结果。比如通过观察可以确定是否存在缺失值、异常值、时间趋势,以及数据是否平稳。如果存在这些问题,就要通过相应的方法对数据进行修正。处理完之后的数据才可以正式的进入分析。
处理缺失值需要根据数据的具体情况来定:是直接忽略缺失值,还是用插值法(interpolation)来弥补缺失值。Matlab里边缺失值使用NaN来表示的。如果数据里边包含NaN,matlab不会发出警告,而是仍然按照你的编程进行运算。最后导致结果异常。以前计算逆矩阵的时候就遇到过这种情况,因为数据中存在NaN,导致矩阵不可逆。有时候直接从excel里边导入的数据,缺失值是用0来表示的。这个时候在matlab中不再显示NaN。但是在运算过程中有可能产生NaN,导致最后结果异常。
对于缺失值NaN,如果要直接忽略的话,一般是用方程isnan来识别NaN,然后再进行替代。假设矩阵x中包含NaN,有下面几种方法可以去除NaN:
- >>i=find(~isana(x));
- >>x=x(i) %第一个命令首先识别那些不等于NaN的矩阵中要素的编号,然后第二个命令就要求只保留这些编号的要素。
- >>x=x(~isnan(x)); %可以直接去除NaN。
或者:
>>x(isnan(x))=[];
如果要去除包含NaN的行:
>>x(any(isnan(x),2),:)=[];
如要用插值法替代NaN,可以用interp1这个方程,就是一维的插值方程。举个例子:
对于矩阵a=[8 1 6; 3 NaN 7; 4 9 2]。
>>b=a(:,2);
>>times=1:length(b);
>>mask=~isnan(b);
>>c=b;
>>c(~mask)=interp1(times(mask),a(mask),times(~mask));
这是利用matlab的内置方程vq=interp1(x,v,xq)。其中x表示的插值法取值的点,v包含了相应的点的值,xq表示需要插值的点。因此,在使用这个方程之前,要对上述三个方面进行定义。该方程默认的是线性插值法,其他的选项可以参见matlab documentation center。
处理异常值也要求对数据的生成过程有清楚的了解,为什么会有异常值产生。因为异常值也包含了重要的样本信息,因此是否要去掉异常值要慎重考虑。通常定义异常值是与样本标准差的差值大于3个标准差,也就是3 sigma准则。虽然去掉异常值对样本的均值影响很小,但是对标准差的影响很大。去掉异常值,有可能会引起标准差很大的变化,有可能产生更多的异常值。
时间序列的数据在分析之前要进行滤波。Matlab内置的一维滤波方程为:
y=filter(b,a,x)
被滤波的数据为x,滤波子用b和a来描述。滤波使用的是差分方程。举个简单的例子,移动平均滤波。假设移动平均的窗口宽度为4,则
b=[1/4 1/4 1/4 1/4];
a=1;
加载数据
>>loadcount.dat
>>x=count(:,1); %被滤波的数据
>>y=filter(b,a,x);
画图,查看一下滤波的结果:
>>t=1:length(x);
>>plot(t,x,’-.’,t,y,’-‘),gridon;
>>legend(‘OriginalData’, ‘Smoothed Data’, 2);
消除时间序列中的趋势也是常用的数据清理方法。消除趋势使用的是matlab的内置方程:
y=detrend(x)
其中x是要被去除趋势的数据。方法是首先用最小二乘拟合数据,得出一个线性的方程,然后从原始数据中减去拟合值。
所举的例子是消除股票市场数据中的线性趋势(不是说趋势一定是线性的,但是仅以消除线性趋势为例):
- >>loadpredict_ret_data.mat
- >>sdata(any(isnan(sdata),2),:)=[]; %sdata中存在NaN,需要消除
- >>t=length(sdata);
- >>plot(t, sdata,’+’); %先观察一下原始数据
- >>legend(‘OriginalData’, 1);
- >>xlabel(‘Time(days)’);
- >>ylabel(‘StockPrice (dollars)’);
- >>detrend_sdata=detrend(sdata);
- >>figure;
- >>plot(detrend_sdata,’-‘); %观察去除线性趋势后的数据,基本上是以0为中心。
- >>legend(‘DetrendedData’, 2);
- >>xlabel(‘Time(days)’);
- >>ylabel(‘DetrendedStock Price (dollars)’);