Skip to content

Commit

Permalink
feat: correlate data series
Browse files Browse the repository at this point in the history
closes #26
  • Loading branch information
Daniel J. Lauk committed Jan 24, 2022
1 parent cb6593d commit 3b11da0
Show file tree
Hide file tree
Showing 2 changed files with 151 additions and 1 deletion.
116 changes: 115 additions & 1 deletion src/transforms.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { transformToLinePlotData } from './transforms'
import { correlateDataSeries, transformToLinePlotData } from './transforms'
import type { Datapoint } from './transforms'

describe('module transforms', () => {
Expand Down Expand Up @@ -136,4 +136,118 @@ describe('module transforms', () => {
expect(output).toEqual(expectedDatapoints)
})
})

describe('correlateDataSeries', () => {
it('returns empty for series A empty', () => {
const seriesX: Datapoint<number>[] = []
const seriesY: Datapoint<number>[] = [
{ x: 10, y: 1 },
{ x: 20, y: 2 },
{ x: 30, y: 3 },
]
const output = correlateDataSeries(seriesX, seriesY)
expect(output).toHaveLength(0)
})

it('returns empty for series B empty', () => {
const seriesX: Datapoint<number>[] = []
const seriesY: Datapoint<number>[] = [
{ x: 10, y: 1 },
{ x: 20, y: 2 },
{ x: 30, y: 3 },
]
const output = correlateDataSeries(seriesX, seriesY)
expect(output).toHaveLength(0)
})

it('returns empty for series A and B empty', () => {
const seriesX: Datapoint<number>[] = []
const seriesY: Datapoint<number>[] = []
const output = correlateDataSeries(seriesX, seriesY)
expect(output).toHaveLength(0)
})

it('returns empty for series A and B having different x', () => {
const seriesX: Datapoint<number>[] = [
{ x: 10, y: 1 },
{ x: 20, y: 2 },
{ x: 30, y: 3 },
]
const seriesY: Datapoint<number>[] = [
{ x: 11, y: 1 },
{ x: 21, y: 2 },
{ x: 31, y: 3 },
]
const output = correlateDataSeries(seriesX, seriesY)
expect(output).toHaveLength(0)
})

it('returns simple correlated result', () => {
const seriesX: Datapoint<number>[] = [
{ x: 10, y: 1 },
{ x: 20, y: 2 },
{ x: 30, y: 3 },
]
const seriesY: Datapoint<number>[] = [
{ x: 10, y: 4 },
{ x: 20, y: 5 },
{ x: 30, y: 6 },
]
const expectedDataPoints = [
{ x: 1, y: 4 },
{ x: 2, y: 5 },
{ x: 3, y: 6 },
]
const output = correlateDataSeries(seriesX, seriesY)
expect(output).toEqual(expectedDataPoints)
})

it('returns partial correlated result', () => {
const seriesX: Datapoint<number>[] = [
{ x: 10, y: 1 },
{ x: 20, y: 2 },
{ x: 30, y: 3 },
]
const seriesY: Datapoint<number>[] = [
{ x: 10, y: 4 },
{ x: 21, y: 5 },
{ x: 30, y: 6 },
]
const expectedDataPoints = [
{ x: 1, y: 4 },
{ x: 3, y: 6 },
]
const output = correlateDataSeries(seriesX, seriesY)
expect(output).toEqual(expectedDataPoints)
})

it('returns multiple datapoints with the same x and different y', () => {
const seriesX: Datapoint<number>[] = [
{ x: 10, y: 1 },
{ x: 20, y: 2 },
{ x: 30, y: 3 },
{ x: 40, y: 2 },
{ x: 50, y: 3 },
{ x: 60, y: 2 },
]
const seriesY: Datapoint<number>[] = [
{ x: 10, y: 4 },
{ x: 20, y: 5 },
{ x: 30, y: 6 },
{ x: 40, y: 7 },
{ x: 50, y: 8 },
{ x: 60, y: 9 },
]
const expectedDataPoints = [
{ x: 1, y: 4 },
{ x: 2, y: 5 },
{ x: 3, y: 6 },
{ x: 2, y: 7 },
{ x: 3, y: 8 },
{ x: 2, y: 9 },
]
const output = correlateDataSeries(seriesX, seriesY)
expect(output).toEqual(expectedDataPoints)
})
})
})
36 changes: 36 additions & 0 deletions src/transforms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,39 @@ export function transformToLinePlotData<Y>(
}
return result
}

export type Correlation<T> = { x: T; y: T }[]

/**
* Correlate two data series X(t) and Y(t).
* For every t in the range try to find a datapoint in each X(t) and Y(t) and pair them up.
*
* result := { (x,y) | x in X(t) and y in Y(t) for the same value of t }
*
* @param seriesX The data points that will become the X values of the correlation
* @param seriesY The data points that will become the Y values of the correlation
* @returns An array of correlated data points
*/
export function correlateDataSeries<T>(
seriesX: Datapoint<T>[],
seriesY: Datapoint<T>[]
): Correlation<T> {
const result: Correlation<T> = []

// initialize lookup map
const lookupY = new Map<number, T>()
for (const pt of seriesY) {
lookupY.set(pt.x, pt.y)
}

// populate correlation
for (const ptX of seriesX) {
const t = ptX.x
const x = ptX.y
const y = lookupY.get(t)
if (y === undefined) continue
result.push({ x, y })
}

return result
}

0 comments on commit 3b11da0

Please sign in to comment.