Skip to content

Commit

Permalink
feat(dashboard): render regression-info with group_by_key
Browse files Browse the repository at this point in the history
  • Loading branch information
GerilLeto committed May 23, 2023
1 parent 35b3adc commit 8a5c596
Show file tree
Hide file tree
Showing 2 changed files with 125 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,15 @@ import { IRegressionChartConf } from '../../type';
// @ts-expect-error type lib for d3-regression
import * as d3Regression from 'd3-regression';
import numbro from 'numbro';
import _ from 'lodash';
import { ReactNode } from 'react';

export type TDescription = {
name: string;
expression: ReactNode;
rSquared: number;
adjustedRSquared: number;
};

/**
* calculate Adjusted RSquared
Expand All @@ -15,11 +24,17 @@ function calculateAdjustedRSquared(r: number, n: number, k: number) {
return 1 - ((1 - r) * (n - 1)) / (n - k - 1);
}

function getLinearDescription(rawData: TVizData, basisData: [number, number][], conf: IRegressionChartConf) {
function getLinearDescription(
name: string,
rawData: TVizData,
basisData: [number, number][],
conf: IRegressionChartConf,
): TDescription {
const { x_axis, y_axis } = conf;
const result = d3Regression.regressionLinear()(basisData);
const { a, b, rSquared } = result;
return {
name,
expression: (
<Group position="center" noWrap spacing={10}>
<Text>{y_axis.name}</Text>
Expand All @@ -40,10 +55,16 @@ function getLinearDescription(rawData: TVizData, basisData: [number, number][],
};
}

function getExponentialDescription(rawData: TVizData, basisData: [number, number][], conf: IRegressionChartConf) {
function getExponentialDescription(
name: string,
rawData: TVizData,
basisData: [number, number][],
conf: IRegressionChartConf,
): TDescription {
const { x_axis, y_axis } = conf;
const { a, b, rSquared } = d3Regression.regressionExp()(basisData);
return {
name,
expression: (
<Group position="center" noWrap spacing={10}>
<Text>{y_axis.name}</Text>
Expand All @@ -68,10 +89,16 @@ function getExponentialDescription(rawData: TVizData, basisData: [number, number
};
}

function getLogarithmicDescription(rawData: TVizData, basisData: [number, number][], conf: IRegressionChartConf) {
function getLogarithmicDescription(
name: string,
rawData: TVizData,
basisData: [number, number][],
conf: IRegressionChartConf,
): TDescription {
const { x_axis, y_axis } = conf;
const { a, b, rSquared } = d3Regression.regressionLog()(basisData);
return {
name,
expression: (
<Group position="center" noWrap spacing={10}>
<Text>{y_axis.name}</Text>
Expand All @@ -96,45 +123,66 @@ function getLogarithmicDescription(rawData: TVizData, basisData: [number, number
};
}

function getPolynomialDescription(rawData: TVizData, basisData: [number, number][], conf: IRegressionChartConf) {
function getPolynomialDescription(
name: string,
rawData: TVizData,
basisData: [number, number][],
conf: IRegressionChartConf,
): TDescription {
const { x_axis, y_axis, regression } = conf;
const result = d3Regression.regressionPoly().order(regression.transform.config.order)(basisData);
const { rSquared } = result;
console.log(result);
return {
name,
expression: '',
rSquared,
adjustedRSquared: calculateAdjustedRSquared(rSquared, rawData.length, 1),
};
}

export function getRegressionDescription(data: TVizData, conf?: IRegressionChartConf) {
if (!conf) {
return {
expression: '',
rSquared: 0,
adjustedRSquared: 0,
};
}
const { regression, x_axis, y_axis } = conf;
const dataSource: [number, number][] = data.map((d) => [d[x_axis.data_key], d[regression.y_axis_data_key]]);
function getDescription(name: string, rawData: TVizData, conf: IRegressionChartConf): TDescription {
const { regression, x_axis } = conf;
const dataSource: [number, number][] = rawData.map((d) => [d[x_axis.data_key], d[regression.y_axis_data_key]]);

if (regression.transform.config.method === 'linear') {
return getLinearDescription(data, dataSource, conf);
return getLinearDescription(name, rawData, dataSource, conf);
}
if (regression.transform.config.method === 'exponential') {
return getExponentialDescription(data, dataSource, conf);
return getExponentialDescription(name, rawData, dataSource, conf);
}

if (regression.transform.config.method === 'logarithmic') {
return getLogarithmicDescription(data, dataSource, conf);
return getLogarithmicDescription(name, rawData, dataSource, conf);
}
if (regression.transform.config.method === 'polynomial') {
return getPolynomialDescription(data, dataSource, conf);
return getPolynomialDescription(name, rawData, dataSource, conf);
}
return {
name,
expression: '',
rSquared: 0,
adjustedRSquared: 0,
};
}

export function getRegressionDescription(data: TVizData, conf?: IRegressionChartConf): TDescription[] {
if (!conf) {
return [
{
name: '',
expression: '',
rSquared: 0,
adjustedRSquared: 0,
},
];
}
if (!conf.regression.group_by_key) {
return [getDescription('', data, conf)];
}

const groupedData = _.groupBy(data, conf.regression.group_by_key);
return Object.entries(groupedData).map(([group, subData]) => {
return getDescription(group, subData, conf);
});
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { Button, HoverCard, Sx, Table, Text } from '@mantine/core';
import { Button, HoverCard, Sx, Table, Tabs, Text } from '@mantine/core';
import { IconInfoCircle } from '@tabler/icons';
import { IRegressionChartConf } from '../../type';
import numbro from 'numbro';
import { useMemo } from 'react';
import { getRegressionDescription } from './desc';
import { TDescription, getRegressionDescription } from './desc';
import { ErrorBoundary } from '~/utils/error-boundary';

const TableSx: Sx = {
marginTop: '10px',
'tbody th, tbody td': {
padding: '7px 10px',
},
Expand All @@ -14,16 +16,64 @@ const TableSx: Sx = {
},
};

function DescriptionContent({ desc }: { desc: TDescription }) {
const { expression, rSquared, adjustedRSquared } = desc;
if (!expression) {
return <Text>Unavailable for this regression method</Text>;
}
return (
<Table fontSize={14} sx={TableSx}>
<tbody>
<tr>
<td colSpan={2}>
<Text align="center">{expression}</Text>
</td>
</tr>
<tr>
<td>R-Sq</td>
<td style={{ textAlign: 'right' }}>{numbro(rSquared).format({ output: 'percent', mantissa: 1 })}</td>
</tr>
<tr>
<td>R-Sq(Adjusted)</td>
<td style={{ textAlign: 'right' }}>{numbro(adjustedRSquared).format({ output: 'percent', mantissa: 1 })}</td>
</tr>
</tbody>
</Table>
);
}

export interface IRegressionDescription {
conf: IRegressionChartConf;
data: TVizData;
}

export function RegressionDescription({ conf, data }: IRegressionDescription) {
const { expression, rSquared, adjustedRSquared } = useMemo(() => {
return getRegressionDescription(data, conf);
}, [conf, data]);
function DescriptionInTabs({ conf, data }: IRegressionDescription) {
const desc = useMemo(() => getRegressionDescription(data, conf), [conf, data]);

if (!conf.regression.group_by_key) {
return <DescriptionContent desc={desc[0]} />;
}
console.log(desc);

return (
<Tabs defaultValue={desc[0]?.name} color="gray">
<Tabs.List grow>
{desc.map((item) => (
<Tabs.Tab key={item.name} value={item.name}>
{item.name}
</Tabs.Tab>
))}
</Tabs.List>
{desc.map((item) => (
<Tabs.Panel key={item.name} value={item.name}>
<DescriptionContent desc={item} />
</Tabs.Panel>
))}
</Tabs>
);
}

export function RegressionDescription({ conf, data }: IRegressionDescription) {
return (
<HoverCard shadow="md" withinPortal zIndex={320}>
<HoverCard.Target>
Expand All @@ -32,31 +82,9 @@ export function RegressionDescription({ conf, data }: IRegressionDescription) {
</Button>
</HoverCard.Target>
<HoverCard.Dropdown>
<Table fontSize={14} sx={TableSx}>
<tbody>
{expression && (
<tr>
<td colSpan={2}>
<Text align="center">{expression}</Text>
</td>
</tr>
)}
{rSquared && (
<>
<tr>
<td>R-Sq</td>
<td style={{ textAlign: 'right' }}>{numbro(rSquared).format({ output: 'percent', mantissa: 1 })}</td>
</tr>
<tr>
<td>R-Sq(Adjusted)</td>
<td style={{ textAlign: 'right' }}>
{numbro(adjustedRSquared).format({ output: 'percent', mantissa: 1 })}
</td>
</tr>
</>
)}
</tbody>
</Table>
<ErrorBoundary>
<DescriptionInTabs conf={conf} data={data} />
</ErrorBoundary>
</HoverCard.Dropdown>
</HoverCard>
);
Expand Down

0 comments on commit 8a5c596

Please sign in to comment.