stl

package module
v1.3.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 11, 2018 License: MIT Imports: 6 Imported by: 0

README

stl GoDoc Build Status Coverage Status Go Report Card

package stl implements Seasonal-Trend Decompositions by LOESS of time series. It is a direct implementation of Cleveland et al (1990), which was written in Fortran '77.

This package does not implement the KD-Tree indexing for nearest neighbour search for the LOESS component as implemented in the original Netlib library. Instead, a straightforwards algorithm is implemented, focusing on clarity and understandability.

There were some parts that were "inlined" and unrolled manually for performance purposes - the tricube function and local neighbour functions for example. The original more mathematical implemetnations have been left in there for future reference.

Additionally, because multiplicative models are common in time series decompositions, Box-Cox transform functions (and generator) have also been provided.

Installation

This package has very minimal dependencies. These are the listing of the dependencies:

This package uses dep to manage dependencies - in particular, at this point, it uses an unstable version of Gorgonia. This will be rectified upon the release of v0.9.0 of Gorgonia.

Automated testing only tests up from Go 1.8 onwards. While I'm fairly confident that this package will work on those lower versions as well

Usage

import (
	"encoding/csv"
	"os"
	"fmt"

	"github.com/chewxy/stl"
)

func main() {
	var data []float64
	f, _ := os.Open("testdata/co2.csv")
	r := csv.NewReader(f)

	r.Read() // read header
	for rec, err := r.Read(); err == nil; rec, err = r.Read() {
		// here we're ignoring errors because we know the file to be correct
		if co2, err := strconv.ParseFloat(rec[0], 64); err == nil {
			data = append(data, co2)
		}
	}

	// The main function: 
	res := stl.Decompose(data, 12, 35, stl.Additive(), stl.WithRobustIter(2), stl.WithIter(2))
	fmt.Printf("%v", res.Seasonal)
	fmt.Printf("%v", res.Trens)
	fmt.Printf("%v", res.Resid)

Licence

This package is licenced with a MIT licence. I thank Rob Hyndman for writing a very excellent guide to STL, both in the R standard lib and in principle.

Documentation

Overview

Package stl implements functions and data structures necessary to perform a Seasonal-Trend decomposition by LOESS, as described by Cleveland et al. (1990).

This library's code was ported over from the original Netlib library which was written in Fortran '77.

Example
package main

import (
	"encoding/csv"
	"fmt"
	"io"
	"os"
	"strconv"

	"github.com/chewxy/stl"
	"github.com/chewxy/tightywhities"
)

const (
	w, h = 80, 10 // width and height of the chart producd
)

func readCheck(a io.Reader, err error) io.Reader {
	if err != nil {
		panic(err)
	}
	return a
}

func check(r stl.Result) stl.Result {
	if r.Err != nil {
		panic(r.Err)
	}
	return r
}

func printResult(res stl.Result) {
	fmt.Println("Data:")
	line := tightywhities.NewLine(nil, res.Data[:w])
	line.Plot(w, h, os.Stdout)
	fmt.Println("\nTrend:")
	line = tightywhities.NewLine(nil, res.Trend[:w])
	line.Plot(w, h, os.Stdout)
	fmt.Println("\nSeasonal:")
	line = tightywhities.NewLine(nil, res.Seasonal[:w])
	line.Plot(w, h, os.Stdout)
	fmt.Println("\nResiduals:")
	line = tightywhities.NewLine(nil, res.Resid[:w])
	line.Plot(w, h, os.Stdout)

}

func main() {
	f := readCheck(os.Open("testdata/co2.csv"))
	r := csv.NewReader(f)
	var data []float64
	r.Read() // read header
	for rec, err := r.Read(); err == nil; rec, err = r.Read() {
		// here we're ignoring errors because we know the file to be correct
		if co2, err := strconv.ParseFloat(rec[0], 64); err == nil {
			data = append(data, co2)
		}
	}
	res := check(stl.Decompose(data, 12, 35, stl.Additive(), stl.WithRobustIter(2), stl.WithIter(2)))
	fmt.Println("ADDITIVE MODEL\n=====================")
	printResult(res)

	// Multiplicative model
	res = check(stl.Decompose(data, 12, 35, stl.Multiplicative(), stl.WithRobustIter(2), stl.WithIter(2)))
	fmt.Println("\nMULTIPLICATIVE MODEL\n=====================")
	printResult(res)

}
Output:

ADDITIVE MODEL
=====================
Data:
│
│                                                               ╭╮          ╭╮
│                                                              ╭╯╰╮        ╭╯╰╮
│+                                      ╭╮         ╭──╮        │  │       ╭╯  ╰╮
│                           ╭─╮        ╭╯╰╮       ╭╯  ╰╮      ╭╯  ╰╮    ╭─╯    │
│                          ╭╯ │       ╭╯  ╰╮     ╭╯    │    ╭─╯    │    │      ╰╮
│  ╭─╮         ╭──╮       ╭╯  ╰╮     ╭╯    │    ╭╯     │   ╭╯      ╰╮  ╭╯       │
│  │ ╰╮       ╭╯  ╰╮     ╭╯    │    ╭╯     ╰╮  ╭╯      ╰╮ ╭╯        │ ╭╯        ╰─
│  ╯  ╰╮    ╭─╯    │   ╭─╯     ╰╮  ╭╯       │ ╭╯        ╰╮│         ╰─╯
│      ╰╮  ╭╯      ╰╮ ╭╯        │ ╭╯        ╰─╯          ╰╯
│       │  │        ╰╮│         ╰─╯
│       ╰──╯         ╰╯

Trend:
│
│+                                   ╭───╮       ╭──╮
│                         ╭───╮    ╭─╯   ╰─╮  ╭──╯  ╰─╮
│                       ╭─╯   ╰─╮╭─╯       ╰──╯       ╰╮
│                      ╭╯       ╰╯                     ╰╮ ╭─────╮
│                     ╭╯                                ╰─╯     ╰╮
│                ╭╮  ╭╯                                          ╰─╮
│             ╭──╯╰──╯                                             ╰╮   ╭───╮
│           ╭─╯                                                     ╰───╯   ╰─╮
│         ╭─╯                                                                 ╰╮
│  ───────╯                                                                    ╰╮
│                                                                               ╰─

Seasonal:
│
│                                                                              ╭──
│+                                                                        ╭────╯
│                                                                     ╭───╯
│                                                                 ╭───╯
│                                                             ╭───╯
│                                                          ╭──╯
│                                                      ╭───╯
│                                                ╭─────╯
│  ─────╮                                   ╭────╯
│       ╰──────╮                    ╭───────╯
│              ╰────────────────────╯

Residuals:
│
│                           ╭╮                                  ╭╮
│                           │╰╮         ╭╮          ╭╮          ││          ╭╮
│               ╭─╮        ╭╯ │        ╭╯╰╮        ╭╯╰╮        ╭╯╰╮        ╭╯╰╮
│+ ╭──╮        ╭╯ │        │  ╰╮       │  │        │  ╰╮       │  │        │  │
│  │  │       ╭╯  ╰╮       │   │      ╭╯  ╰╮      ╭╯   │      ╭╯  ╰╮      ╭╯  ╰╮
│  │  ╰╮     ╭╯    │     ╭─╯   │     ╭╯    │     ╭╯    │     ╭╯    │    ╭─╯    │
│  ╯   │    ╭╯     │    ╭╯     │    ╭╯     │    ╭╯     │    ╭╯     │    │      │
│      ╰╮  ╭╯      ╰╮  ╭╯      ╰╮  ╭╯      ╰╮  ╭╯      ╰╮  ╭╯      ╰╮  ╭╯      ╰╮
│       │  │        │ ╭╯        │  │        │ ╭╯        │ ╭╯        │  │        │
│       ╰╮╭╯        ╰╮│         │ ╭╯        │╭╯         ╰╮│         │ ╭╯        │
│        ╰╯          ╰╯         ╰─╯         ╰╯           ╰╯         ╰─╯         ╰─

MULTIPLICATIVE MODEL
=====================
Data:
│
│                                                               ╭╮          ╭╮
│                                                              ╭╯╰╮        ╭╯╰╮
│+                                      ╭╮         ╭──╮        │  │       ╭╯  ╰╮
│                           ╭─╮        ╭╯╰╮       ╭╯  ╰╮      ╭╯  ╰╮    ╭─╯    │
│                          ╭╯ │       ╭╯  ╰╮     ╭╯    │    ╭─╯    │    │      ╰╮
│  ╭─╮         ╭──╮       ╭╯  ╰╮     ╭╯    │    ╭╯     │   ╭╯      ╰╮  ╭╯       │
│  │ ╰╮       ╭╯  ╰╮     ╭╯    │    ╭╯     ╰╮  ╭╯      ╰╮ ╭╯        │ ╭╯        ╰─
│  ╯  ╰╮    ╭─╯    │   ╭─╯     ╰╮  ╭╯       │ ╭╯        ╰╮│         ╰─╯
│      ╰╮  ╭╯      ╰╮ ╭╯        │ ╭╯        ╰─╯          ╰╯
│       │  │        ╰╮│         ╰─╯
│       ╰──╯         ╰╯

Trend:
│+
│                                                 ╭╮
│                         ╭─╮        ╭────╮     ╭─╯╰─╮
│                        ╭╯ ╰──╮   ╭─╯    ╰─╮ ╭─╯    ╰╮
│                       ╭╯     ╰╮╭─╯        ╰─╯       ╰╮      ╭╮
│                      ╭╯       ╰╯                     ╰──────╯╰╮
│                     ╭╯                                        ╰─╮
│             ╭─────╮╭╯                                           ╰╮      ╭╮
│            ╭╯     ╰╯                                             ╰╮ ╭───╯╰─╮
│           ╭╯                                                      ╰─╯      ╰╮
│        ╭──╯                                                                 ╰╮
│  ──────╯                                                                     ╰──

Seasonal:
│
│                                                                           ╭─────
│+                                                                      ╭───╯
│                                                                   ╭───╯
│                                                               ╭───╯
│                                                           ╭───╯
│                                                        ╭──╯
│                                                   ╭────╯
│                                             ╭─────╯
│  ────────╮                             ╭────╯
│          ╰──────────╮        ╭─────────╯
│                     ╰────────╯

Residuals:
│
│                           ╭╮                                  ╭╮
│                           │╰╮         ╭╮          ╭╮          ││          ╭╮
│               ╭─╮        ╭╯ │         │╰╮        ╭╯╰╮        ╭╯╰╮        ╭╯╰╮
│+ ╭──╮        ╭╯ │        │  ╰╮       ╭╯ │        │  │        │  │        │  │
│  │  │       ╭╯  │        │   │      ╭╯  ╰╮      ╭╯  ╰╮      ╭╯  ╰╮      ╭╯  ╰╮
│  │  ╰╮     ╭╯   ╰╮     ╭─╯   │     ╭╯    │     ╭╯    │     ╭╯    │    ╭─╯    │
│  ╯   │    ╭╯     │    ╭╯     │    ╭╯     │    ╭╯     │    ╭╯     │    │      │
│      ╰╮  ╭╯      ╰╮  ╭╯      ╰╮  ╭╯      ╰╮  ╭╯      ╰╮  ╭╯      ╰╮  ╭╯      ╰╮
│       │  │        │ ╭╯        │  │        │ ╭╯        │  │        │  │        │
│       │ ╭╯        ╰╮│         │ ╭╯        │╭╯         ╰╮╭╯        │ ╭╯        │
│       ╰─╯          ╰╯         ╰─╯         ╰╯           ╰╯         ╰─╯         ╰─

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type BoxCox

type BoxCox func(a []float64) []float64

BoxCox is any function that performs a box cox transform

type Config

type Config struct {
	// Width represents the width of the LOESS smoother in data points
	Width int

	// Jump is the number of points to skip between smoothing,
	Jump int

	// Which weight updating function should be used?
	Fn loess.WeightUpdate
}

Config is a configuration structure

func DefaultLowPass

func DefaultLowPass(periodicity int) Config

DefaultLowPass returns the default configuration for the operation that works on the lowpass component.

func DefaultSeasonal

func DefaultSeasonal(width int) Config

DefaultSeasonal returns the default configuration for the operation that works on the seasonal component.

func DefaultTrend

func DefaultTrend(periodicity, width int) Config

DefaultTrend returns the default configuration for the operation that works on the trend component.

type IsoBoxCox

type IsoBoxCox func(a []float64) []float64

IsoBoxCox is the invese of the BoxCox

type ModelType

type ModelType struct {
	Fwd BoxCox
	Bwd IsoBoxCox
}

ModelType is the type of STL model we would like to perform. A STL model type is usually additive, or multiplicative, however, it can be somewhere in between. This is done by means of a Box-Cox transform (and the reverse when we're done applying STL)

func Additive

func Additive() ModelType

Additive returns a BoxCox transform that does nothing.

func Multiplicative

func Multiplicative() ModelType

Multiplicative returns a BoxCox transform that performs and unsafe transform of the input slice

func UnsafeTransform

func UnsafeTransform(lambda float64) ModelType

UnsafeTransform creates a transformation function that is somewhere between an additive and multiplicative model

type Opt

type Opt func(*state)

Opt is a function that helps build the conf

func WithIter

func WithIter(n int) Opt

WithIter indicates how many iterations to run. The default is 2.

func WithLowpassConfig

func WithLowpassConfig(conf Config) Opt

WithLowpassConfig configures the operation that performs the lowpass filter in the decomposition process

func WithRobustIter

func WithRobustIter(n int) Opt

WithRobustIter indicates how many iterations of "robust" (i.e. outlier removal) to do. The default is 0.

func WithSeasonalConfig

func WithSeasonalConfig(conf Config) Opt

WithSeasonalConfig configures the seasonal component of the decomposition process.

func WithTrendConfig

func WithTrendConfig(conf Config) Opt

WithTrendConfig configures the trend component of the decomposition process.

type Result

type Result struct {
	Data     []float64
	Trend    []float64
	Seasonal []float64
	Resid    []float64
	Err      error
}

Result is the result of a decompositon

func Decompose

func Decompose(X []float64, periodicity, width int, m ModelType, opts ...Opt) Result

Decompose performs a STL decomposition.

Following the R library conventions, this function uses a default of 2 iterations and 0 robust iterations.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL