Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@visactor/vdataset",
"comment": "set boxplot whisker as actual bound value(Q1 - N*IQR) or fixed value && add alpha option of regression function",
"type": "none"
}
],
"packageName": "@visactor/vdataset"
}
70 changes: 70 additions & 0 deletions packages/vdataset/__tests__/boxplot.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,74 @@ describe('boxplot transform', () => {
expect(ids).toContain('a');
expect(ids).toContain('b');
});

test('whisker should be fixed not ranged by latset value', () => {
const data = [
{
v: -1
},
{
v: 3
},
{
v: 3
},
{
v: 3
},
{
v: 3
},
{
v: 3
},
{
v: 3
},
{
v: 3
},
{
v: 3
},
{
v: 3
},
{
v: 3
},
{
v: 3
},
{
v: 3
},
{
v: 3
},
{
v: 4
},
{
v: 4
},
{
v: 7
},
{
v: 8
},
{
v: 9
},
{
v: 10
}
];
const out: any = boxplot(data, { field: 'v' });
expect(out.length).toBe(1);
const o = out[0];
expect(o.lowerWhisker).toBe(1.5);
expect(o.upperWhisker).toBe(5.5);
});
});
22 changes: 3 additions & 19 deletions packages/vdataset/src/transform/boxplot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,25 +146,9 @@ export const boxplot: Transform = (data: Array<object>, options?: IBoxplotOption
const lowerBound = isArray(whiskers) ? quantileSorted(sorted, whiskers[0]) : q1 - whiskers * iqr;
const upperBound = isArray(whiskers) ? quantileSorted(sorted, whiskers[1]) : q3 + whiskers * iqr;

// whiskers are the most extreme data points inside the bounds
let lowerWhisker = dataMin;
for (let i = 0; i < sorted.length; i++) {
if (sorted[i] >= lowerBound) {
lowerWhisker = sorted[i];
break;
}
}
let upperWhisker = dataMax;
for (let i = sorted.length - 1; i >= 0; i--) {
if (sorted[i] <= upperBound) {
upperWhisker = sorted[i];
break;
}
}

const outliers: number[] = [];
for (let i = 0; i < sorted.length; i++) {
if (sorted[i] < lowerWhisker || sorted[i] > upperWhisker) {
if (sorted[i] < lowerBound || sorted[i] > upperBound) {
outliers.push(sorted[i]);
}
}
Expand All @@ -191,8 +175,8 @@ export const boxplot: Transform = (data: Array<object>, options?: IBoxplotOption
obj[iqrName] = iqr;
obj[minName] = dataMin;
obj[maxName] = dataMax;
obj[lowerWhiskerName] = lowerWhisker;
obj[upperWhiskerName] = upperWhisker;
obj[lowerWhiskerName] = lowerBound;
obj[upperWhiskerName] = upperBound;
obj[outliersName] = outliers;
if (includeValues) {
obj[valuesName] = rawValues.get(key) || [];
Expand Down
12 changes: 10 additions & 2 deletions packages/vutils/src/common/regression-linear.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,15 @@ export function rSquared(
return sst === 0 ? 0 : 1 - ssr / sst;
}

export function regressionLinear(data: any[], x: (d: any) => number = d => d.x, y: (d: any) => number = d => d.y) {
export function regressionLinear(
data: any[],
x: (d: any) => number = d => d.x,
y: (d: any) => number = d => d.y,
options?: {
alpha?: number;
}
) {
const alpha = options?.alpha ?? 0.05;
// accumulate online means (sufficient statistics)
let n = 0;
let meanX = 0;
Expand Down Expand Up @@ -95,7 +103,7 @@ export function regressionLinear(data: any[], x: (d: any) => number = d => d.x,
return out;
}

function confidenceInterval(N: number = 50, alpha: number = 0.05) {
function confidenceInterval(N: number = 50) {
const out: { x: number; mean: number; lower: number; upper: number; predLower: number; predUpper: number }[] = [];
if (comps.n === 0 || N <= 0) {
return out;
Expand Down
5 changes: 3 additions & 2 deletions packages/vutils/src/common/regression-logistic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@ export function regressionLogistic(
data: any[],
x: (d: any) => number = d => d.x,
y: (d: any) => number = d => d.y,
options?: { maxIteration?: number; tol?: number }
options?: { maxIteration?: number; tol?: number; alpha?: number }
) {
const maxIter = options?.maxIteration ?? 25;
const tol = options?.tol ?? 1e-6;
const alpha = options?.alpha ?? 0.05;
// build arrays
const xs: number[] = [];
const ys: number[] = [];
Expand Down Expand Up @@ -120,7 +121,7 @@ export function regressionLogistic(
return out;
}

function confidenceInterval(N: number = 50, alpha: number = 0.05) {
function confidenceInterval(N: number = 50) {
const out: { x: number; mean: number; lower: number; upper: number; predLower: number; predUpper: number }[] = [];

if (N <= 0) {
Expand Down
5 changes: 3 additions & 2 deletions packages/vutils/src/common/regression-lowess.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,11 @@ export function regressionLowess(
data: any[],
x: (d: any) => number = d => d.x,
y: (d: any) => number = d => d.y,
options: { span?: number; degree?: 1 | 0; iterations?: number } = {}
options: { span?: number; degree?: 1 | 0; iterations?: number; alpha?: number } = {}
) {
const span = options.span || 0.3;
const degree = options.degree === 0 ? 0 : 1;
const alpha = options?.alpha ?? 0.05;
const iterations = options.iterations == null ? 2 : options.iterations;

const ptsX: number[] = [];
Expand Down Expand Up @@ -170,7 +171,7 @@ export function regressionLowess(
return out;
}

function confidenceInterval(N: number = 50, alpha: number = 0.05) {
function confidenceInterval(N: number = 50) {
const out: { x: number; mean: number; lower: number; upper: number; predLower: number; predUpper: number }[] = [];

if (N <= 0) {
Expand Down
5 changes: 3 additions & 2 deletions packages/vutils/src/common/regression-polynomial.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,13 @@ export function regressionPolynomial(
data: any[],
x: (d: any) => number = d => d.x,
y: (d: any) => number = d => d.y,
options: { degree?: number } = {}
options: { degree?: number; alpah?: number } = {}
) {
let degree = options.degree ?? 0;
if (degree < 0) {
degree = 0;
}
const alpha = options.alpah ?? 0.5;
const m = degree + 1;
const sums: number[] = new Array(2 * degree + 1).fill(0);

Expand Down Expand Up @@ -171,7 +172,7 @@ export function regressionPolynomial(
}
return out;
},
confidenceInterval(N: number = 50, alpha: number = 0.05) {
confidenceInterval(N: number = 50) {
const out: { x: number; mean: number; lower: number; upper: number; predLower: number; predUpper: number }[] = [];

if (N <= 0) {
Expand Down
Loading