2021-01-29 06:31:58 -05:00
|
|
|
|
|
|
|
[![Arduino CI](https://github.com/RobTillaart/Correlation/workflows/Arduino%20CI/badge.svg)](https://github.com/marketplace/actions/arduino_ci)
|
2021-08-26 11:18:52 -04:00
|
|
|
[![Arduino-lint](https://github.com/RobTillaart/Correlation/actions/workflows/arduino-lint.yml/badge.svg)](https://github.com/RobTillaart/Correlation/actions/workflows/arduino-lint.yml)
|
|
|
|
[![JSON check](https://github.com/RobTillaart/Correlation/actions/workflows/jsoncheck.yml/badge.svg)](https://github.com/RobTillaart/Correlation/actions/workflows/jsoncheck.yml)
|
2021-01-29 06:31:58 -05:00
|
|
|
[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/RobTillaart/Correlation/blob/master/LICENSE)
|
|
|
|
[![GitHub release](https://img.shields.io/github/release/RobTillaart/Correlation.svg?maxAge=3600)](https://github.com/RobTillaart/Correlation/releases)
|
|
|
|
|
|
|
|
|
2020-05-18 08:53:34 -04:00
|
|
|
# Correlation
|
|
|
|
|
2021-01-29 06:31:58 -05:00
|
|
|
Arduino Library to determine linear correlation between X and Y datasets.
|
2020-05-18 08:53:34 -04:00
|
|
|
|
2021-01-29 06:31:58 -05:00
|
|
|
|
|
|
|
## Description
|
2020-05-18 08:53:34 -04:00
|
|
|
|
|
|
|
This library calculates the coefficients of the linear correlation
|
|
|
|
between two (relative small) datasets. The size of these datasets is
|
2021-08-26 11:18:52 -04:00
|
|
|
20 by default. The size can be set in the constructor.
|
2020-05-18 08:53:34 -04:00
|
|
|
|
2021-01-29 06:31:58 -05:00
|
|
|
Please note that the correlation uses about ~50 bytes per instance,
|
|
|
|
and 2 floats == 8 bytes per pair of elements.
|
|
|
|
So ~120 elements will use up 50% of the RAM of an UNO.
|
|
|
|
|
2021-12-14 10:39:48 -05:00
|
|
|
The formula of the correlation is expressed as **Y = A + B \* X**.
|
2021-08-27 10:16:35 -04:00
|
|
|
|
|
|
|
If all points are on a vertical line, the parameter B will be NAN,
|
|
|
|
This will happen if the **sumXi2** is zero or very small.
|
|
|
|
|
2020-05-18 08:53:34 -04:00
|
|
|
Use with care.
|
|
|
|
|
|
|
|
|
2021-01-29 06:31:58 -05:00
|
|
|
## Interface
|
|
|
|
|
|
|
|
|
|
|
|
### Constructor
|
|
|
|
|
2021-12-14 10:39:48 -05:00
|
|
|
- **Correlation(uint8_t size = 20)** allocates the array needed and resets internal admin.
|
|
|
|
Size should be between 1 and 255. Size = 0 will set the size to 20.
|
2021-01-29 06:31:58 -05:00
|
|
|
- **~Correlation()** frees the allocated arrays.
|
2020-05-18 08:53:34 -04:00
|
|
|
|
|
|
|
|
2021-01-29 06:31:58 -05:00
|
|
|
### Base functions
|
2020-05-18 08:53:34 -04:00
|
|
|
|
2021-12-14 10:39:48 -05:00
|
|
|
- **bool add(float x, float y)** adds a pair of **floats** to the internal storage array's.
|
2021-01-29 06:31:58 -05:00
|
|
|
Returns true if the value is added, returns false when internal array is full.
|
2021-08-27 10:16:35 -04:00
|
|
|
When running correlation is set, **add()** will replace the oldest element and return true.
|
|
|
|
Warning: **add()** does not check if the floats are NAN or INFINITE.
|
|
|
|
- **uint8_t count()** returns the amount of items in the internal arrays.
|
|
|
|
This number is always between 0 ..**size()**
|
2021-01-29 06:31:58 -05:00
|
|
|
- **uint8_t size()** returns the size of the internal arrays.
|
2021-12-14 10:39:48 -05:00
|
|
|
- **void clear()** resets the data structures to the start condition (zero elements added).
|
2021-01-29 06:31:58 -05:00
|
|
|
- **bool calculate()** does the math to calculate the correlation parameters A, B and R.
|
|
|
|
This function will be called automatically when needed.
|
|
|
|
You can call it on a more convenient time.
|
|
|
|
Returns false if nothing to calculate **count == 0**
|
2021-08-27 10:16:35 -04:00
|
|
|
- **void setR2Calculation(bool)** enables / disables the calculation of Rsquared.
|
|
|
|
- **bool getR2Calculation()** returns the flag set.
|
|
|
|
- **void setE2Calculation(bool)** enables / disables the calculation of Esquared.
|
|
|
|
- **bool getE2Calculation()** returns the flag set.
|
|
|
|
|
|
|
|
After the calculation the following functions can be called to return the core values.
|
2021-01-29 06:31:58 -05:00
|
|
|
- **float getA()** returns the A parameter of formula **Y = A + B \* X**
|
|
|
|
- **float getB()** returns the B parameter of formula **Y = A + B \* X**
|
2021-08-27 10:16:35 -04:00
|
|
|
- **float getR()** returns the correlation coefficient R which is always between -1 .. 1
|
2021-01-29 06:31:58 -05:00
|
|
|
The closer to 0 the less correlation there is between X and Y.
|
|
|
|
Correlation can be positive or negative.
|
2021-12-14 10:39:48 -05:00
|
|
|
Most often the Rsquared **R x R** is used.
|
2021-08-27 10:16:35 -04:00
|
|
|
- **float getRsquare()** returns **R x R** which is always between 0.. 1.
|
2021-01-29 06:31:58 -05:00
|
|
|
- **float getEsquare()** returns the error squared to get an indication of the
|
2021-08-27 10:16:35 -04:00
|
|
|
quality of the correlation.
|
2022-06-21 02:22:05 -04:00
|
|
|
- **float getAverageX()** returns the average of all elements in the X dataset.
|
|
|
|
- **float getAverageY()** returns the average of all elements in the Y dataset.
|
2021-08-26 11:18:52 -04:00
|
|
|
- **float getEstimateX(float y)** use to calculate the estimated X for a given Y.
|
|
|
|
- **float getEstimateY(float x)** use to calculate the estimated Y for a given X.
|
2020-05-18 08:53:34 -04:00
|
|
|
|
2021-01-29 06:31:58 -05:00
|
|
|
|
2021-08-27 10:16:35 -04:00
|
|
|
#### Correlation Coefficient R
|
|
|
|
|
|
|
|
Indicative description of the correlation
|
|
|
|
|
|
|
|
| R | correlation |
|
|
|
|
|:-------------:|:--------------|
|
|
|
|
| +1.0 | Perfect |
|
|
|
|
| +0.8 to +1.0 | Very strong |
|
|
|
|
| +0.6 to +0.8 | Strong |
|
|
|
|
| +0.4 to +0.6 | Moderate |
|
|
|
|
| +0.2 to +0.4 | Weak |
|
|
|
|
| 0.0 to +0.2 | Very weak |
|
|
|
|
| 0.0 to -0.2 | Very weak |
|
|
|
|
| -0.2 to -0.4 | Weak |
|
|
|
|
| -0.4 to -0.6 | Moderate |
|
|
|
|
| -0.6 to -0.8 | Strong |
|
|
|
|
| -0.8 to -1.0 | Very strong |
|
|
|
|
| -1.0 | Perfect |
|
|
|
|
|
|
|
|
|
2021-01-29 06:31:58 -05:00
|
|
|
### Running correlation
|
|
|
|
|
2021-12-14 10:39:48 -05:00
|
|
|
- **void setRunningCorrelation(bool rc)** sets the internal variable runningMode
|
|
|
|
which allows **add()** to overwrite old elements in the internal arrays.
|
2021-08-27 10:16:35 -04:00
|
|
|
- **bool getRunningCorrelation()** returns the runningMode flag.
|
2021-01-29 06:31:58 -05:00
|
|
|
|
2021-12-14 10:39:48 -05:00
|
|
|
The running correlation will be calculated over the last **count** elements.
|
|
|
|
If the array is full, count will be size.
|
|
|
|
This running correlation allows for more adaptive formula finding e.g. find the
|
|
|
|
relation between temperature and humidity per hour, and how it changes over time.
|
2021-01-29 06:31:58 -05:00
|
|
|
|
|
|
|
|
|
|
|
### Statistical
|
2020-05-18 08:53:34 -04:00
|
|
|
|
2021-01-29 06:31:58 -05:00
|
|
|
These functions give an indication of the "trusted interval" for estimations.
|
|
|
|
The idea is that for **getEstimateX()** the further outside the range defined
|
|
|
|
by **getMinX()** and **getMaxX()**, the less the result can be trusted.
|
|
|
|
It also depends on **R** of course. Idem for **getEstimateY()**
|
2020-05-18 08:53:34 -04:00
|
|
|
|
2021-01-29 06:31:58 -05:00
|
|
|
- **float getMinX()** idem
|
|
|
|
- **float getMaxX()** idem
|
|
|
|
- **float getMinY()** idem
|
|
|
|
- **float getMaxY()** idem
|
2020-05-18 08:53:34 -04:00
|
|
|
|
|
|
|
|
2021-01-29 06:31:58 -05:00
|
|
|
### Debugging / educational
|
2020-05-18 08:53:34 -04:00
|
|
|
|
2021-12-14 10:39:48 -05:00
|
|
|
Normally not used. For all these functions index should be < count!
|
2020-05-18 08:53:34 -04:00
|
|
|
|
2021-12-14 10:39:48 -05:00
|
|
|
- **bool setXY(uint8_t index, float x, float y)** overwrites a pair of values.
|
2021-08-27 10:16:35 -04:00
|
|
|
Returns true if succeeded.
|
2021-12-14 10:39:48 -05:00
|
|
|
- **bool setX(uint8_t index, float x)** overwrites single X.
|
|
|
|
- **bool setY(uint8_t index, float y)** overwrites single Y.
|
|
|
|
- **float getX(uint8_t index)** returns single value.
|
|
|
|
- **float getY(uint8_t index)** returns single value.
|
2022-06-21 02:22:05 -04:00
|
|
|
- **float getSumXY()** returns sum(Xi \* Yi).
|
|
|
|
- **float getSumX2()** returns sum(Xi \* Xi).
|
|
|
|
- **float getSumY2()** returns sum(Yi \* Yi).
|
|
|
|
|
|
|
|
|
|
|
|
### Obsolete in 0.3.0
|
|
|
|
|
|
|
|
To improve readability the following functions are replaced
|
|
|
|
|
|
|
|
- **float getAvgX()** returns average X.
|
|
|
|
- **float getAvgY()** returns average Y.
|
2021-01-29 06:31:58 -05:00
|
|
|
- **float getSumXiYi()** returns sum(Xi \* Yi).
|
2021-12-14 10:39:48 -05:00
|
|
|
- **float getSumXi2()** returns sum(Xi \* Xi).
|
|
|
|
- **float getSumYi2()** returns sum(Yi \* Yi).
|
2021-01-29 06:31:58 -05:00
|
|
|
|
|
|
|
|
|
|
|
## Future
|
|
|
|
|
2022-06-21 02:22:05 -04:00
|
|
|
- Template version?
|
2021-01-29 06:31:58 -05:00
|
|
|
The constructor should get a TYPE parameter, as this
|
2021-08-27 10:16:35 -04:00
|
|
|
allows smaller data types to be analysed taking less memory.
|
2021-12-14 10:39:48 -05:00
|
|
|
- examples
|
|
|
|
- real world if possible.
|
2020-05-18 08:53:34 -04:00
|
|
|
|
|
|
|
|
2022-06-21 02:22:05 -04:00
|
|
|
### 0.3.0
|
|
|
|
|
|
|
|
- fix naming in examples as some function names are replaced.
|
|
|
|
- are the getSUmXiYi indeed worse?
|
|
|
|
|
|
|
|
|
|
|
|
|
2021-01-29 06:31:58 -05:00
|
|
|
## Operation
|
2020-05-18 08:53:34 -04:00
|
|
|
|
|
|
|
See example
|