559 lines
11 KiB
C++
559 lines
11 KiB
C++
#include "stdafx.h"
|
|
#include "Transformation.h"
|
|
#include "Median.h"
|
|
#include <math.h>
|
|
#include <vector>
|
|
#include <iostream>
|
|
#include <limits>
|
|
|
|
Transformation::Transformation(vector <double> ts)
|
|
{
|
|
setTimeSeries(ts);
|
|
INFINITY = std::numeric_limits<double>::infinity();
|
|
}
|
|
|
|
Transformation::~Transformation()
|
|
{
|
|
}
|
|
|
|
void Transformation::setTimeSeries(vector<double> ts){
|
|
|
|
TimeSeries = ts;
|
|
tsSizeValue = ts.size();
|
|
|
|
tsShiftValue = 0;
|
|
GeometricAverage = 1;
|
|
valueMean = 0;
|
|
|
|
double min = 0;
|
|
|
|
for (int i = 0; i < tsSizeValue; i++)
|
|
{
|
|
if ((TimeSeries[i] < 0) && (TimeSeries[i] < min))
|
|
{
|
|
min = TimeSeries[i];
|
|
}
|
|
|
|
GeometricAverage = GeometricAverage * TimeSeries[i];
|
|
|
|
valueMean += TimeSeries[i];
|
|
|
|
}
|
|
|
|
if (min != 0)
|
|
{
|
|
tsShiftValue = abs(min) + 1;
|
|
}
|
|
|
|
if (tsSizeValue != 0)
|
|
{
|
|
GeometricAverage = pow(GeometricAverage, 1 / tsSizeValue);
|
|
valueMean /= tsSizeValue;
|
|
}
|
|
|
|
}
|
|
|
|
int Transformation::sign(double value)
|
|
{
|
|
if (value >= 0)
|
|
return 1;
|
|
else
|
|
return -1;
|
|
}
|
|
|
|
|
|
double Transformation::lambdaEstimationGuerrero(double param){
|
|
|
|
double result;
|
|
|
|
int begin; // iterator
|
|
int end; // iterator
|
|
double sumRow; // sum row matrix
|
|
double sumSd; // sum for estimation standard deviation
|
|
double meanRat;
|
|
int lengthPeriod = 2;
|
|
|
|
if (seasonalPeriod > lengthPeriod)
|
|
{
|
|
lengthPeriod = seasonalPeriod;
|
|
}
|
|
|
|
int amtlengthPeriod = floor((double)tsSizeValue / lengthPeriod);
|
|
int shift = tsSizeValue - floor((double)amtlengthPeriod * lengthPeriod);
|
|
|
|
vector <double> mean(amtlengthPeriod); // mean row matrix
|
|
vector <double> sd(amtlengthPeriod); // standard deviation
|
|
vector <double> rat(amtlengthPeriod);
|
|
|
|
for (int i = 0; i < amtlengthPeriod; i++)
|
|
{
|
|
begin = shift + i * lengthPeriod;
|
|
end = begin + lengthPeriod;
|
|
|
|
sumRow = 0;
|
|
|
|
for (int row = begin; row < end; row++)
|
|
{
|
|
sumRow += TimeSeries[row];
|
|
}
|
|
|
|
mean[i] = sumRow / lengthPeriod;
|
|
|
|
sumSd = 0;
|
|
|
|
for (int row = begin; row < end; row++)
|
|
{
|
|
sumSd += pow(TimeSeries[row] - mean[i], 2);
|
|
}
|
|
|
|
sd[i] = sqrt(sumSd / (lengthPeriod - 1));
|
|
}
|
|
|
|
for (int i = 0; i < amtlengthPeriod; i++)
|
|
{
|
|
rat[i] = sd[i] / (pow(mean[i], 1 - param));
|
|
}
|
|
|
|
meanRat = 0;
|
|
|
|
for (int i = 0; i < amtlengthPeriod; i++)
|
|
{
|
|
meanRat += rat[i];
|
|
}
|
|
|
|
meanRat /= amtlengthPeriod;
|
|
|
|
sumSd = 0;
|
|
|
|
for (int i = 0; i < amtlengthPeriod; i++)
|
|
{
|
|
sumSd += pow(rat[i] - meanRat, 2);
|
|
}
|
|
|
|
result = sqrt(sumSd / (amtlengthPeriod - 1)) / meanRat;
|
|
|
|
return result;
|
|
}
|
|
|
|
void Transformation::lambdaEstimation(){
|
|
|
|
double cv = INFINITY; //cv - coefficient of variation
|
|
|
|
for (double i = -1; i <= 2; i += 0.01)
|
|
{
|
|
//double i = 0.7;
|
|
double result = lambdaEstimationGuerrero(i);
|
|
if (result < cv)
|
|
{
|
|
cv = result;
|
|
lambda = i;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
vector<double> Transformation::BoxCox(){
|
|
|
|
vector <double> tsTransformation(tsSizeValue);
|
|
|
|
if (lambda == 0)
|
|
{
|
|
for (int i = 0; i < tsSizeValue; i++)
|
|
{
|
|
tsTransformation[i] = log(TimeSeries[i] + tsShiftValue);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int i = 0; i < TimeSeries.size(); i++)
|
|
{
|
|
tsTransformation[i] = (pow(TimeSeries[i] + tsShiftValue, lambda) - 1) / lambda;
|
|
}
|
|
}
|
|
|
|
return tsTransformation;
|
|
}
|
|
|
|
vector<double> Transformation::invBoxCox(){
|
|
|
|
vector <double> tsTransformation(tsSizeValue);
|
|
|
|
if (lambda == 0)
|
|
{
|
|
for (int i = 0; i < tsSizeValue; i++)
|
|
{
|
|
tsTransformation[i] = exp(TimeSeries[i]) - tsShiftValue;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
for (int i = 0; i < TimeSeries.size(); i++)
|
|
{
|
|
tsTransformation[i] = pow((lambda * TimeSeries[i] + 1), 1 / lambda) - tsShiftValue;
|
|
}
|
|
}
|
|
|
|
return tsTransformation;
|
|
}
|
|
|
|
|
|
vector<double> Transformation::ExponentialTransformation(){
|
|
|
|
vector <double> tsTransformation(tsSizeValue);
|
|
|
|
if (lambda != 0)
|
|
{
|
|
for (int i = 0; i < tsSizeValue; i++)
|
|
{
|
|
tsTransformation[i] = (exp(TimeSeries[i] * lambda) - 1) / lambda;
|
|
}
|
|
}
|
|
|
|
return tsTransformation;
|
|
}
|
|
|
|
vector<double> Transformation::invExponentialTransformation(){
|
|
|
|
vector <double> tsTransformation(tsSizeValue);
|
|
|
|
if (lambda != 0)
|
|
{
|
|
for (int i = 0; i < tsSizeValue; i++)
|
|
{
|
|
tsTransformation[i] = log(1 + TimeSeries[i] * lambda) / lambda;
|
|
}
|
|
}
|
|
|
|
return tsTransformation;
|
|
}
|
|
|
|
|
|
vector<double> Transformation::ModulusTransformation(){
|
|
|
|
vector <double> tsTransformation(tsSizeValue);
|
|
|
|
if (lambda == 0)
|
|
{
|
|
for (int i = 0; i < tsSizeValue; i++)
|
|
{
|
|
tsTransformation[i] = sign(TimeSeries[i]) * log(abs(TimeSeries[i]) + 1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int i = 0; i < tsSizeValue; i++)
|
|
{
|
|
tsTransformation[i] = sign(TimeSeries[i]) * (pow(abs(TimeSeries[i]) + 1, lambda) - 1) / lambda;
|
|
}
|
|
}
|
|
|
|
return tsTransformation;
|
|
}
|
|
|
|
vector<double> Transformation::invModulusTransformation(){
|
|
|
|
vector <double> tsTransformation(tsSizeValue);
|
|
|
|
if (lambda == 0)
|
|
{
|
|
for (int i = 0; i < tsSizeValue; i++)
|
|
{
|
|
tsTransformation[i] = sign(TimeSeries[i]) * (exp(abs(TimeSeries[i])) - 1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int i = 0; i < tsSizeValue; i++)
|
|
{
|
|
tsTransformation[i] = pow(TimeSeries[i] * lambda / sign(TimeSeries[i]) + 1, 1 / lambda) - 1;
|
|
}
|
|
}
|
|
|
|
return tsTransformation;
|
|
}
|
|
|
|
|
|
vector<double> Transformation::AsymptoticBoxCox(){
|
|
|
|
vector <double> tsTransformation(tsSizeValue);
|
|
|
|
if (lambda > 0)
|
|
{
|
|
for (int i = 0; i < tsSizeValue; i++)
|
|
{
|
|
tsTransformation[i] = (sign(TimeSeries[i]) * pow(abs(TimeSeries[i]), lambda) - 1) / lambda;
|
|
}
|
|
}
|
|
|
|
return tsTransformation;
|
|
}
|
|
|
|
vector<double> Transformation::invAsymptoticBoxCox(){
|
|
|
|
vector <double> tsTransformation(tsSizeValue);
|
|
|
|
if (lambda > 0)
|
|
{
|
|
for (int i = 0; i < tsSizeValue; i++)
|
|
{
|
|
tsTransformation[i] = pow((TimeSeries[i] * lambda - 1) / sign(TimeSeries[i]), 1 / lambda);
|
|
}
|
|
}
|
|
|
|
return tsTransformation;
|
|
}
|
|
|
|
|
|
vector<double> Transformation::ModifiedBoxCox(){
|
|
|
|
vector <double> tsTransformation(tsSizeValue);
|
|
|
|
for (int i = 0; i < tsSizeValue; i++)
|
|
{
|
|
if ((TimeSeries[i] >= 0) && (lambda != 0))
|
|
{
|
|
tsTransformation[i] = (pow(TimeSeries[i] + 1, lambda) - 1) / lambda;
|
|
}
|
|
else if ((TimeSeries[i] >= 0) && (lambda == 0))
|
|
{
|
|
tsTransformation[i] = log(TimeSeries[i] + 1);
|
|
}
|
|
else if ((TimeSeries[i] < 0) && (lambda != 0))
|
|
{
|
|
tsTransformation[i] = -(pow(-TimeSeries[i] + 1, 2 - lambda) - 1) / (2 - lambda);
|
|
}
|
|
else if ((TimeSeries[i] < 0) && (lambda == 0))
|
|
{
|
|
tsTransformation[i] = -log(-TimeSeries[i] + 1);
|
|
}
|
|
}
|
|
|
|
return tsTransformation;
|
|
}
|
|
|
|
vector<double> Transformation::invModifiedBoxCox(){
|
|
|
|
vector <double> tsTransformation(tsSizeValue);
|
|
|
|
for (int i = 0; i < tsSizeValue; i++)
|
|
{
|
|
if ((TimeSeries[i] >= 0) && (lambda != 0))
|
|
{
|
|
tsTransformation[i] = pow(TimeSeries[i] * lambda + 1, 1 / lambda) - 1;
|
|
}
|
|
else if ((TimeSeries[i] >= 0) && (lambda == 0))
|
|
{
|
|
tsTransformation[i] = exp(TimeSeries[i]) - 1;
|
|
}
|
|
else if ((TimeSeries[i] < 0) && (lambda != 2))
|
|
{
|
|
tsTransformation[i] = -(pow(-(TimeSeries[i] * (2 - lambda) - 1), 1 / (2 - lambda)) - 1);
|
|
}
|
|
else if ((TimeSeries[i] < 0) && (lambda == 2))
|
|
{
|
|
tsTransformation[i] = -exp(-TimeSeries[i]) + 1;
|
|
}
|
|
}
|
|
|
|
return tsTransformation;
|
|
}
|
|
|
|
|
|
vector<double> Transformation::NormalizedBoxCox(){
|
|
|
|
vector <double> tsTransformation(tsSizeValue);
|
|
|
|
if (lambda == 0)
|
|
{
|
|
for (int i = 0; i < tsSizeValue; i++)
|
|
{
|
|
tsTransformation[i] = GeometricAverage * log(TimeSeries[i]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int i = 0; i < tsSizeValue; i++)
|
|
{
|
|
tsTransformation[i] = (pow(TimeSeries[i], lambda) - 1) / (lambda * pow(GeometricAverage, lambda - 1));
|
|
}
|
|
}
|
|
|
|
return tsTransformation;
|
|
}
|
|
|
|
vector<double> Transformation::invNormalizedBoxCox(){
|
|
|
|
vector <double> tsTransformation(tsSizeValue);
|
|
|
|
if (lambda == 0)
|
|
{
|
|
for (int i = 0; i < tsSizeValue; i++)
|
|
{
|
|
tsTransformation[i] = exp(TimeSeries[i] / GeometricAverage);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int i = 0; i < tsSizeValue; i++)
|
|
{
|
|
tsTransformation[i] = pow(TimeSeries[i] * lambda * pow(GeometricAverage, lambda - 1) + 1, 1 / lambda);
|
|
}
|
|
}
|
|
|
|
return tsTransformation;
|
|
|
|
}
|
|
|
|
|
|
vector<double> Transformation::Deseasonalization(int seasonalPeriod){
|
|
|
|
vector <double> tsDeseasonalization(tsSizeValue);
|
|
SeasonalIndex.resize(seasonalPeriod - 1);
|
|
|
|
int tsShift = 0;
|
|
int amtSeasonalPeriod = tsSizeValue / seasonalPeriod;
|
|
|
|
if (tsSizeValue % seasonalPeriod != 0)
|
|
{
|
|
tsShift = tsSizeValue - amtSeasonalPeriod * seasonalPeriod;
|
|
}
|
|
|
|
// считаем средние сезоанальные индексы
|
|
Median *est = new Median();
|
|
SeasonalIndex = est->getValue(TimeSeries, seasonalPeriod);
|
|
|
|
// получаем итог
|
|
for (int i = 0; i < amtSeasonalPeriod; i++)
|
|
{
|
|
int begin = tsShift + i * seasonalPeriod;
|
|
int end = begin + seasonalPeriod;
|
|
|
|
for (int ii = begin; ii < end; ii++)
|
|
{
|
|
tsDeseasonalization[ii] = TimeSeries[ii] / SeasonalIndex[i];
|
|
}
|
|
}
|
|
|
|
return tsDeseasonalization;
|
|
|
|
}
|
|
|
|
vector<double> Transformation::invDeseasonalization(){
|
|
|
|
vector <double> tsDeseasonalization(tsSizeValue);
|
|
|
|
int tsShift = 0;
|
|
int amtSeasonalPeriod = tsSizeValue / seasonalPeriod;
|
|
|
|
if (tsSizeValue % seasonalPeriod != 0)
|
|
{
|
|
tsShift = tsSizeValue - amtSeasonalPeriod * seasonalPeriod - 1;
|
|
}
|
|
|
|
for (int i = 0; i < amtSeasonalPeriod; i++)
|
|
{
|
|
int begin = tsShift + i * seasonalPeriod;
|
|
int end = begin + seasonalPeriod;
|
|
|
|
for (int ii = begin; ii < end; ii++)
|
|
{
|
|
tsDeseasonalization[ii] = TimeSeries[ii] * SeasonalIndex[i];
|
|
}
|
|
}
|
|
|
|
return tsDeseasonalization;
|
|
}
|
|
|
|
vector<double> Transformation::getSeasonalIndex(){
|
|
|
|
return SeasonalIndex;
|
|
}
|
|
|
|
|
|
vector <double> Transformation::Aggregation(int seasonalPeriod){
|
|
|
|
int tsShift = 0;
|
|
int amtSeasonalPeriod = tsSizeValue / seasonalPeriod;
|
|
|
|
vector <double> tsAggregation(amtSeasonalPeriod);
|
|
|
|
if (tsSizeValue % seasonalPeriod != 0)
|
|
{
|
|
tsShift = tsSizeValue - amtSeasonalPeriod * seasonalPeriod;
|
|
}
|
|
|
|
// получаем итог
|
|
for (int i = 0; i < amtSeasonalPeriod; i++)
|
|
{
|
|
int begin = tsShift + i * seasonalPeriod;
|
|
int end = begin + seasonalPeriod;
|
|
|
|
for (int ii = begin; ii < end; ii++)
|
|
{
|
|
tsAggregation[i] += TimeSeries[ii];
|
|
}
|
|
}
|
|
|
|
return tsAggregation;
|
|
|
|
}
|
|
|
|
vector <double> Transformation::invAggregation(){
|
|
|
|
int sumSeasonalPeriod = tsSizeValue * seasonalPeriod;
|
|
|
|
vector <double> tsDeaggregation(sumSeasonalPeriod);
|
|
|
|
// получаем итог
|
|
for (int i = 0; i < tsSizeValue; i++)
|
|
{
|
|
int begin = i * seasonalPeriod;
|
|
int end = begin + seasonalPeriod;
|
|
|
|
for (int ii = begin; ii < end; ii++)
|
|
{
|
|
tsDeaggregation[ii] = TimeSeries[i] / seasonalPeriod;
|
|
}
|
|
}
|
|
|
|
return tsDeaggregation;
|
|
}
|
|
|
|
|
|
vector<double> Transformation::Normalization(){
|
|
|
|
vector <double> tsNormalization(tsSizeValue);
|
|
|
|
valueSd = 0;
|
|
|
|
for (int i = 0; i < tsSizeValue; i++)
|
|
{
|
|
valueSd += pow(TimeSeries[i] - valueMean, 2);
|
|
}
|
|
|
|
valueSd = sqrt(valueSd / (tsSizeValue - 1));
|
|
|
|
for (int i = 0; i < tsSizeValue; i++)
|
|
{
|
|
tsNormalization[i] = (TimeSeries[i] - valueMean) / valueSd;
|
|
}
|
|
|
|
return tsNormalization;
|
|
|
|
}
|
|
|
|
vector <double> Transformation::invNormalization()
|
|
{
|
|
|
|
vector <double> tsNormalization(tsSizeValue);
|
|
|
|
for (int i = 0; i < tsSizeValue; i++)
|
|
{
|
|
tsNormalization[i] = TimeSeries[i] * valueSd + valueMean;
|
|
}
|
|
|
|
return tsNormalization;
|
|
|
|
} |