@kanaries/graphic-walker 0.3.4 → 0.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/App.d.ts +6 -0
- package/dist/assets/{transform.worker-5d54ff09.js.map → transform.worker-90e4f506.js.map} +1 -1
- package/dist/assets/viewQuery.worker-03404216.js.map +1 -0
- package/dist/components/pivotTable/index.d.ts +12 -0
- package/dist/components/pivotTable/inteface.d.ts +6 -0
- package/dist/components/pivotTable/leftTree.d.ts +10 -0
- package/dist/components/pivotTable/metricTable.d.ts +9 -0
- package/dist/components/pivotTable/store.d.ts +22 -0
- package/dist/components/pivotTable/topTree.d.ts +10 -0
- package/dist/components/pivotTable/utils.d.ts +6 -0
- package/dist/components/visualConfig/index.d.ts +3 -0
- package/dist/config.d.ts +2 -0
- package/dist/fields/aestheticFields.d.ts +2 -2
- package/dist/graphic-walker.es.js +23528 -23139
- package/dist/graphic-walker.es.js.map +1 -1
- package/dist/graphic-walker.umd.js +129 -129
- package/dist/graphic-walker.umd.js.map +1 -1
- package/dist/interfaces.d.ts +7 -1
- package/dist/lib/insights/utils.d.ts +0 -2
- package/dist/lib/interfaces.d.ts +5 -3
- package/dist/store/commonStore.d.ts +2 -0
- package/dist/store/visualSpecStore.d.ts +1 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/vis/react-vega.d.ts +3 -1
- package/dist/vis/spec/encode.d.ts +2 -0
- package/dist/visualSettings/index.d.ts +3 -0
- package/package.json +1 -1
- package/src/App.tsx +11 -1
- package/src/components/pivotTable/index.tsx +119 -0
- package/src/components/pivotTable/inteface.ts +8 -0
- package/src/components/pivotTable/leftTree.tsx +92 -0
- package/src/components/pivotTable/metricTable.tsx +107 -0
- package/src/components/pivotTable/store.tsx +66 -0
- package/src/components/pivotTable/topTree.tsx +77 -0
- package/src/components/pivotTable/utils.ts +141 -0
- package/src/components/visualConfig/index.tsx +76 -0
- package/src/config.ts +5 -1
- package/src/fields/aestheticFields.tsx +25 -4
- package/src/fields/components.tsx +2 -2
- package/src/fields/fieldsContext.tsx +2 -1
- package/src/interfaces.ts +7 -1
- package/src/lib/insights/explainByChildren.ts +11 -3
- package/src/lib/insights/explainBySelection.ts +14 -5
- package/src/lib/insights/explainValue.ts +10 -3
- package/src/lib/insights/utils.ts +0 -4
- package/src/lib/interfaces.ts +1 -3
- package/src/lib/op/aggregate.ts +9 -7
- package/src/locales/en-US.json +13 -3
- package/src/locales/ja-JP.json +188 -178
- package/src/locales/zh-CN.json +13 -3
- package/src/renderer/index.tsx +16 -2
- package/src/renderer/specRenderer.tsx +6 -2
- package/src/store/commonStore.ts +4 -0
- package/src/store/visualSpecStore.ts +14 -2
- package/src/utils/index.ts +8 -1
- package/src/vis/react-vega.tsx +31 -7
- package/src/vis/spec/aggregate.ts +3 -0
- package/src/vis/spec/encode.ts +5 -1
- package/src/vis/spec/view.ts +4 -2
- package/src/visualSettings/index.tsx +28 -4
- package/src/workers/transform.ts +1 -1
- package/dist/assets/viewQuery.worker-ffefc111.js.map +0 -1
package/src/vis/react-vega.tsx
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import React, { useEffect, useState, useMemo, forwardRef, useImperativeHandle, useRef } from 'react';
|
|
2
|
-
import embed from 'vega-embed';
|
|
2
|
+
import embed, { vega } from 'vega-embed';
|
|
3
3
|
import { Subject, Subscription } from 'rxjs'
|
|
4
4
|
import * as op from 'rxjs/operators';
|
|
5
5
|
import type { ScenegraphEvent, View } from 'vega';
|
|
6
6
|
import styled from 'styled-components';
|
|
7
7
|
|
|
8
|
-
import { IViewField, IRow, IStackMode, IDarkMode, IThemeKey } from '../interfaces';
|
|
8
|
+
import { IViewField, IRow, IStackMode, IDarkMode, IThemeKey, IVisualConfig } from '../interfaces';
|
|
9
9
|
import { useTranslation } from 'react-i18next';
|
|
10
10
|
import { getVegaTimeFormatRules } from './temporalFormat';
|
|
11
11
|
import { builtInThemes } from './theme';
|
|
@@ -27,6 +27,7 @@ export interface IReactVegaHandler {
|
|
|
27
27
|
downloadPNG: (filename?: string) => Promise<string[]>;
|
|
28
28
|
}
|
|
29
29
|
interface ReactVegaProps {
|
|
30
|
+
format: IVisualConfig['format'];
|
|
30
31
|
rows: Readonly<IViewField[]>;
|
|
31
32
|
columns: Readonly<IViewField[]>;
|
|
32
33
|
dataSource: IRow[];
|
|
@@ -40,6 +41,7 @@ interface ReactVegaProps {
|
|
|
40
41
|
shape?: IViewField;
|
|
41
42
|
theta?: IViewField;
|
|
42
43
|
radius?: IViewField;
|
|
44
|
+
text?: IViewField;
|
|
43
45
|
details?: Readonly<IViewField[]>;
|
|
44
46
|
showActions: boolean;
|
|
45
47
|
layoutMode: string;
|
|
@@ -88,6 +90,7 @@ const ReactVega = forwardRef<IReactVegaHandler, ReactVegaProps>(function ReactVe
|
|
|
88
90
|
theta,
|
|
89
91
|
radius,
|
|
90
92
|
shape,
|
|
93
|
+
text,
|
|
91
94
|
onGeomClick,
|
|
92
95
|
showActions,
|
|
93
96
|
interactiveScale,
|
|
@@ -96,12 +99,30 @@ const ReactVega = forwardRef<IReactVegaHandler, ReactVegaProps>(function ReactVe
|
|
|
96
99
|
height,
|
|
97
100
|
details = [],
|
|
98
101
|
themeKey = 'vega',
|
|
99
|
-
dark = 'media'
|
|
102
|
+
dark = 'media',
|
|
103
|
+
format
|
|
100
104
|
} = props;
|
|
101
105
|
const [viewPlaceholders, setViewPlaceholders] = useState<React.MutableRefObject<HTMLDivElement>[]>([]);
|
|
102
106
|
const { i18n } = useTranslation();
|
|
103
107
|
const mediaTheme = useCurrentMediaTheme(dark);
|
|
104
108
|
const themeConfig = builtInThemes[themeKey]?.[mediaTheme];
|
|
109
|
+
|
|
110
|
+
const vegaConfig = useMemo(() => {
|
|
111
|
+
const config: any = {
|
|
112
|
+
...themeConfig,
|
|
113
|
+
}
|
|
114
|
+
if (format.normalizedNumberFormat && format.normalizedNumberFormat.length > 0) {
|
|
115
|
+
config.normalizedNumberFormat = format.normalizedNumberFormat;
|
|
116
|
+
}
|
|
117
|
+
if (format.numberFormat && format.numberFormat.length > 0) {
|
|
118
|
+
config.numberFormat = format.numberFormat;
|
|
119
|
+
}
|
|
120
|
+
if (format.timeFormat && format.timeFormat.length > 0) {
|
|
121
|
+
config.timeFormat = format.timeFormat;
|
|
122
|
+
}
|
|
123
|
+
return config;
|
|
124
|
+
}, [themeConfig, format.normalizedNumberFormat, format.numberFormat, format.timeFormat])
|
|
125
|
+
|
|
105
126
|
useEffect(() => {
|
|
106
127
|
const clickSub = geomClick$.subscribe(([values, e]) => {
|
|
107
128
|
if (onGeomClick) {
|
|
@@ -183,6 +204,7 @@ const ReactVega = forwardRef<IReactVegaHandler, ReactVegaProps>(function ReactVe
|
|
|
183
204
|
shape: shape ? shape : NULL_FIELD,
|
|
184
205
|
theta: theta ? theta : NULL_FIELD,
|
|
185
206
|
radius: radius ? radius : NULL_FIELD,
|
|
207
|
+
text: text ? text : NULL_FIELD,
|
|
186
208
|
row: rowFacetField,
|
|
187
209
|
column: colFacetField,
|
|
188
210
|
xOffset: NULL_FIELD,
|
|
@@ -199,7 +221,7 @@ const ReactVega = forwardRef<IReactVegaHandler, ReactVegaProps>(function ReactVe
|
|
|
199
221
|
}
|
|
200
222
|
|
|
201
223
|
if (viewPlaceholders.length > 0 && viewPlaceholders[0].current) {
|
|
202
|
-
embed(viewPlaceholders[0].current, spec, { mode: 'vega-lite', actions: showActions, timeFormatLocale: getVegaTimeFormatRules(i18n.language), config:
|
|
224
|
+
embed(viewPlaceholders[0].current, spec, { mode: 'vega-lite', actions: showActions, timeFormatLocale: getVegaTimeFormatRules(i18n.language), config: vegaConfig }).then(res => {
|
|
203
225
|
vegaRefs.current = [res.view];
|
|
204
226
|
try {
|
|
205
227
|
res.view.addEventListener('click', (e) => {
|
|
@@ -247,6 +269,7 @@ const ReactVega = forwardRef<IReactVegaHandler, ReactVegaProps>(function ReactVe
|
|
|
247
269
|
radius: radius ? radius : NULL_FIELD,
|
|
248
270
|
row: rowFacetField,
|
|
249
271
|
column: colFacetField,
|
|
272
|
+
text: text ? text : NULL_FIELD,
|
|
250
273
|
xOffset: NULL_FIELD,
|
|
251
274
|
yOffset: NULL_FIELD,
|
|
252
275
|
details,
|
|
@@ -263,7 +286,7 @@ const ReactVega = forwardRef<IReactVegaHandler, ReactVegaProps>(function ReactVe
|
|
|
263
286
|
ans.params = commonSpec.params;
|
|
264
287
|
}
|
|
265
288
|
if (node) {
|
|
266
|
-
embed(node, ans, { mode: 'vega-lite', actions: showActions, timeFormatLocale: getVegaTimeFormatRules(i18n.language), config:
|
|
289
|
+
embed(node, ans, { mode: 'vega-lite', actions: showActions, timeFormatLocale: getVegaTimeFormatRules(i18n.language), config: vegaConfig }).then(res => {
|
|
267
290
|
vegaRefs.current.push(res.view);
|
|
268
291
|
const paramStores = (res.vgSpec.data?.map(d => d.name) ?? []).filter(
|
|
269
292
|
name => [BRUSH_SIGNAL_NAME, POINT_SIGNAL_NAME].map(p => `${p}_store`).includes(name)
|
|
@@ -350,8 +373,9 @@ const ReactVega = forwardRef<IReactVegaHandler, ReactVegaProps>(function ReactVe
|
|
|
350
373
|
layoutMode,
|
|
351
374
|
width,
|
|
352
375
|
height,
|
|
353
|
-
|
|
354
|
-
details
|
|
376
|
+
vegaConfig,
|
|
377
|
+
details,
|
|
378
|
+
text
|
|
355
379
|
]);
|
|
356
380
|
|
|
357
381
|
useImperativeHandle(ref, () => ({
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import { COUNT_FIELD_ID } from '../../constants';
|
|
2
2
|
import { IViewField } from '../../interfaces';
|
|
3
|
+
import { getMeaAggKey } from '../../utils';
|
|
3
4
|
|
|
4
5
|
export function channelAggregate(encoding: { [key: string]: any }, fields: IViewField[]) {
|
|
5
6
|
Object.values(encoding).forEach((c) => {
|
|
6
7
|
const targetField = fields.find((f) => f.fid === c.field && !('aggregate' in c));
|
|
7
8
|
if (targetField && targetField.fid === COUNT_FIELD_ID) {
|
|
8
9
|
c.title = 'Count';
|
|
10
|
+
c.field = getMeaAggKey(targetField.fid, targetField.aggName)
|
|
9
11
|
} else if (targetField && targetField.analyticType === 'measure') {
|
|
10
12
|
c.title = `${targetField.aggName}(${targetField.name})`;
|
|
13
|
+
c.field = getMeaAggKey(targetField.fid, targetField.aggName)
|
|
11
14
|
}
|
|
12
15
|
});
|
|
13
16
|
}
|
package/src/vis/spec/encode.ts
CHANGED
|
@@ -15,8 +15,12 @@ export interface IEncodeProps {
|
|
|
15
15
|
theta: IViewField;
|
|
16
16
|
radius: IViewField;
|
|
17
17
|
details: Readonly<IViewField[]>;
|
|
18
|
+
text: IViewField;
|
|
18
19
|
}
|
|
19
|
-
function availableChannels(geomType: string): Set<string> {
|
|
20
|
+
export function availableChannels(geomType: string): Set<string> {
|
|
21
|
+
if (geomType === 'text') {
|
|
22
|
+
return new Set(['text', 'color', 'size', 'x', 'y', 'xOffset', 'yOffset', 'opacity']);
|
|
23
|
+
}
|
|
20
24
|
if (geomType === 'arc') {
|
|
21
25
|
return new Set(['opacity', 'color', 'size', 'theta', 'radius']);
|
|
22
26
|
}
|
package/src/vis/spec/view.ts
CHANGED
|
@@ -21,6 +21,7 @@ export function getSingleView(props: SingleViewProps) {
|
|
|
21
21
|
shape,
|
|
22
22
|
theta,
|
|
23
23
|
radius,
|
|
24
|
+
text,
|
|
24
25
|
row,
|
|
25
26
|
column,
|
|
26
27
|
xOffset,
|
|
@@ -31,7 +32,7 @@ export function getSingleView(props: SingleViewProps) {
|
|
|
31
32
|
geomType,
|
|
32
33
|
hideLegend = false,
|
|
33
34
|
} = props;
|
|
34
|
-
const fields: IViewField[] = [x, y, color, opacity, size, shape, row, column, xOffset, yOffset, theta, radius];
|
|
35
|
+
const fields: IViewField[] = [x, y, color, opacity, size, shape, row, column, xOffset, yOffset, theta, radius, text];
|
|
35
36
|
let markType = geomType;
|
|
36
37
|
let config: any = {};
|
|
37
38
|
if (hideLegend) {
|
|
@@ -60,7 +61,8 @@ export function getSingleView(props: SingleViewProps) {
|
|
|
60
61
|
yOffset,
|
|
61
62
|
theta,
|
|
62
63
|
radius,
|
|
63
|
-
details
|
|
64
|
+
details,
|
|
65
|
+
text
|
|
64
66
|
});
|
|
65
67
|
addTooltipEncode(encoding, details)
|
|
66
68
|
if (defaultAggregated) {
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
ArrowsUpDownIcon,
|
|
19
19
|
LightBulbIcon,
|
|
20
20
|
CodeBracketSquareIcon,
|
|
21
|
+
Cog6ToothIcon,
|
|
21
22
|
} from '@heroicons/react/24/outline';
|
|
22
23
|
import { observer } from 'mobx-react-lite';
|
|
23
24
|
import React, { SVGProps, useCallback, useMemo } from 'react';
|
|
@@ -60,9 +61,11 @@ const FormContainer = styled.div`
|
|
|
60
61
|
interface IVisualSettings {
|
|
61
62
|
darkModePreference: IDarkMode;
|
|
62
63
|
rendererHandler?: React.RefObject<IReactVegaHandler>;
|
|
64
|
+
exclude?: string[];
|
|
65
|
+
extra?: ToolbarItemProps[];
|
|
63
66
|
}
|
|
64
67
|
|
|
65
|
-
const VisualSettings: React.FC<IVisualSettings> = ({ rendererHandler, darkModePreference }) => {
|
|
68
|
+
const VisualSettings: React.FC<IVisualSettings> = ({ rendererHandler, darkModePreference, extra = [], exclude = [] }) => {
|
|
66
69
|
const { vizStore, commonStore } = useGlobalStore();
|
|
67
70
|
const { visualConfig, canUndo, canRedo } = vizStore;
|
|
68
71
|
const { t: tGlobal } = useTranslation();
|
|
@@ -84,7 +87,7 @@ const VisualSettings: React.FC<IVisualSettings> = ({ rendererHandler, darkModePr
|
|
|
84
87
|
const dark = useCurrentMediaTheme(darkModePreference) === 'dark';
|
|
85
88
|
|
|
86
89
|
const items = useMemo<ToolbarItemProps[]>(() => {
|
|
87
|
-
|
|
90
|
+
const builtInItems = [
|
|
88
91
|
{
|
|
89
92
|
key: 'undo',
|
|
90
93
|
label: 'undo (Ctrl + Z)',
|
|
@@ -155,8 +158,10 @@ const VisualSettings: React.FC<IVisualSettings> = ({ rendererHandler, darkModePr
|
|
|
155
158
|
circle: (props: SVGProps<SVGSVGElement>) => <svg stroke="none" fill="currentColor" strokeWidth="1.5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden {...props}><path strokeLinecap="round" strokeLinejoin="round" d="M6,12 A6,6,0,0,1,18,12 A6,6,0,0,1,6,12" /></svg>,
|
|
156
159
|
tick: (props: SVGProps<SVGSVGElement>) => <svg stroke="currentColor" fill="none" strokeWidth="1.5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden {...props}><path strokeLinecap="round" strokeLinejoin="round" d="M5,12h14" /></svg>,
|
|
157
160
|
rect: (props: SVGProps<SVGSVGElement>) => <svg stroke="none" fill="currentColor" strokeWidth="1.5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden {...props}><path strokeLinecap="round" strokeLinejoin="round" d="M5,5v14h14v-14z" /></svg>,
|
|
161
|
+
text: (props: SVGProps<SVGSVGElement>) => <svg stroke="currentColor" fill="currentColor" strokeWidth="1.5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden {...props}><path strokeLinecap="round" strokeLinejoin="round" d="M10.5 21l5.25-11.25L21 21m-9-3h7.5M3 5.621a48.474 48.474 0 016-.371m0 0c1.12 0 2.233.038 3.334.114M9 5.25V3m3.334 2.364C11.176 10.658 7.69 15.08 3 17.502m9.334-12.138c.896.061 1.785.147 2.666.257m-4.589 8.495a18.023 18.023 0 01-3.827-5.802" /></svg>,
|
|
158
162
|
arc: (props: SVGProps<SVGSVGElement>) => <svg stroke="none" fill="currentColor" strokeWidth="1.5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden {...props}><path strokeLinecap="round" strokeLinejoin="round" d="M12,21l-9,-15a12,12,0,0,1,18,0Z" /></svg>,
|
|
159
163
|
boxplot: (props: SVGProps<SVGSVGElement>) => <svg stroke="currentColor" fill="none" strokeWidth="1.5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden {...props}><path strokeLinecap="round" strokeLinejoin="round" d="M7,7v9h10v-9Zm0,4h8M12,7v-6m-3,0h6M12,16v7m-3,0h6" /></svg>,
|
|
164
|
+
table: (props: SVGProps<SVGSVGElement>) => <svg stroke="currentColor" fill="none" strokeWidth="1.5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden {...props}><path strokeLinecap="round" strokeLinejoin="round" d="M3.375 19.5h17.25m-17.25 0a1.125 1.125 0 01-1.125-1.125M3.375 19.5h7.5c.621 0 1.125-.504 1.125-1.125m-9.75 0V5.625m0 12.75v-1.5c0-.621.504-1.125 1.125-1.125m18.375 2.625V5.625m0 12.75c0 .621-.504 1.125-1.125 1.125m1.125-1.125v-1.5c0-.621-.504-1.125-1.125-1.125m0 3.75h-7.5A1.125 1.125 0 0112 18.375m9.75-12.75c0-.621-.504-1.125-1.125-1.125H3.375c-.621 0-1.125.504-1.125 1.125m19.5 0v1.5c0 .621-.504 1.125-1.125 1.125M2.25 5.625v1.5c0 .621.504 1.125 1.125 1.125m0 0h17.25m-17.25 0h7.5c.621 0 1.125.504 1.125 1.125M3.375 8.25c-.621 0-1.125.504-1.125 1.125v1.5c0 .621.504 1.125 1.125 1.125m17.25-3.75h-7.5c-.621 0-1.125.504-1.125 1.125m8.625-1.125c.621 0 1.125.504 1.125 1.125v1.5c0 .621-.504 1.125-1.125 1.125m-17.25 0h7.5m-7.5 0c-.621 0-1.125.504-1.125 1.125v1.5c0 .621.504 1.125 1.125 1.125M12 10.875v-1.5m0 1.5c0 .621-.504 1.125-1.125 1.125M12 10.875c0 .621.504 1.125 1.125 1.125m-2.25 0c.621 0 1.125.504 1.125 1.125M13.125 12h7.5m-7.5 0c-.621 0-1.125.504-1.125 1.125M20.625 12c.621 0 1.125.504 1.125 1.125v1.5c0 .621-.504 1.125-1.125 1.125m-17.25 0h7.5M12 14.625v-1.5m0 1.5c0 .621-.504 1.125-1.125 1.125M12 14.625c0 .621.504 1.125 1.125 1.125m-2.25 0c.621 0 1.125.504 1.125 1.125m0 1.5v-1.5m0 0c0-.621.504-1.125 1.125-1.125m0 0h7.5" /></svg>
|
|
160
165
|
}[g],
|
|
161
166
|
})),
|
|
162
167
|
value: markType,
|
|
@@ -278,6 +283,14 @@ const VisualSettings: React.FC<IVisualSettings> = ({ rendererHandler, darkModePr
|
|
|
278
283
|
</FormContainer>
|
|
279
284
|
),
|
|
280
285
|
},
|
|
286
|
+
{
|
|
287
|
+
key: 'config',
|
|
288
|
+
label: 'config',
|
|
289
|
+
icon: Cog6ToothIcon,
|
|
290
|
+
onClick: () => {
|
|
291
|
+
commonStore.setShowVisualConfigPanel(true);
|
|
292
|
+
}
|
|
293
|
+
},
|
|
281
294
|
{
|
|
282
295
|
key: 'export_code',
|
|
283
296
|
label: t('button.export_code'),
|
|
@@ -285,9 +298,20 @@ const VisualSettings: React.FC<IVisualSettings> = ({ rendererHandler, darkModePr
|
|
|
285
298
|
onClick: () => {
|
|
286
299
|
commonStore.setShowCodeExportPanel(true);
|
|
287
300
|
}
|
|
288
|
-
}
|
|
301
|
+
},
|
|
289
302
|
] as ToolbarItemProps[];
|
|
290
|
-
|
|
303
|
+
|
|
304
|
+
const items = builtInItems.filter(item => typeof item === 'string' || !exclude.includes(item.key));
|
|
305
|
+
|
|
306
|
+
if (extra.length > 0) {
|
|
307
|
+
items.push(
|
|
308
|
+
'-',
|
|
309
|
+
...extra,
|
|
310
|
+
);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
return items;
|
|
314
|
+
}, [vizStore, canUndo, canRedo, defaultAggregated, markType, stack, interactiveScale, sizeMode, width, height, showActions, downloadPNG, downloadSVG, dark, extra, exclude]);
|
|
291
315
|
|
|
292
316
|
return <div style={{ margin: '0.38em 0.28em 0.2em 0.18em' }}>
|
|
293
317
|
<Toolbar
|
package/src/workers/transform.ts
CHANGED
|
@@ -6,7 +6,7 @@ export function transformData(data: IRow[], columns: IField[]) {
|
|
|
6
6
|
let df = dataset2DataFrame(data, columns);
|
|
7
7
|
for (let i = 0; i < computedFields.length; i++) {
|
|
8
8
|
const field = computedFields[i];
|
|
9
|
-
df = execExpression(field.
|
|
9
|
+
df = execExpression(field.expression!, df, columns);
|
|
10
10
|
}
|
|
11
11
|
return dataframe2Dataset(df, columns);
|
|
12
12
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"viewQuery.worker-ffefc111.js","sources":["../src/lib/op/stat.ts","../src/lib/op/aggregate.ts","../src/lib/op/fold.ts","../src/lib/op/bin.ts","../src/lib/viewQuery.ts","../src/workers/viewQuery.worker.js"],"sourcesContent":["export function mean(nums: number[]): number {\n return nums.reduce((a, b) => a + b, 0) / nums.length;\n}\n\nexport function sum(nums: number[]): number {\n return nums.reduce((a, b) => a + b, 0);\n}\n\nexport function median(nums: number[]): number {\n const sorted = nums.sort((a, b) => a - b);\n const mid = Math.floor(sorted.length / 2);\n return sorted.length % 2 === 0 ? (sorted[mid] + sorted[mid - 1]) / 2 : sorted[mid];\n}\n\nexport function variance(nums: number[]): number {\n const m = mean(nums);\n return mean(nums.map((x) => (x - m) ** 2));\n}\n\nexport function stdev(nums: number[]): number {\n return Math.sqrt(variance(nums));\n}\n\nexport function max(nums: number[]): number {\n let ans = -Infinity;\n for (let n of nums) {\n if (n > ans) {\n ans = n;\n }\n }\n return ans;\n}\n\nexport function min(nums: number[]): number {\n let ans = Infinity;\n for (let n of nums) {\n if (n < ans) {\n ans = n;\n }\n }\n return ans;\n}\n\nexport function count(nums: number[]): number {\n return nums.length;\n}\n","import { IRow } from \"../../interfaces\";\nimport { IAggQuery } from \"../interfaces\";\nimport { sum, mean, median, stdev, variance, max, min, count } from \"./stat\";\n\nconst aggregatorMap = {\n sum,\n mean,\n median,\n stdev,\n variance,\n max,\n min,\n count,\n};\n\nconst KEY_JOINER = '___';\n\nexport function aggregate (data: IRow[], query: IAggQuery): IRow[] {\n const { groupBy, agg } = query;\n const ans: Map<string, IRow> = new Map();\n const groups: Map<string, IRow[]> = new Map();\n for (let row of data) {\n const gk = groupBy.map((k) => row[k]).join(KEY_JOINER);\n\n if (!groups.has(gk)) {\n groups.set(gk, []);\n }\n groups.get(gk)?.push(row);\n }\n for (let [gk, subGroup] of groups) {\n if (subGroup.length === 0) {\n continue;\n }\n let aggRow: IRow = {};\n for (let k of groupBy) {\n aggRow[k] = subGroup[0][k];\n }\n for (let meaKey in agg) {\n if (aggRow[meaKey] === undefined) {\n aggRow[meaKey] = 0;\n }\n const values: number[] = subGroup.map((r) => r[meaKey]) ?? [];\n const aggregator = aggregatorMap[agg[meaKey]] ?? sum;\n aggRow[meaKey] = aggregator(values);\n }\n ans.set(gk, aggRow);\n }\n return Array.from(ans.values());\n}","import { IRow } from \"../../interfaces\";\nimport { IFoldQuery } from \"../interfaces\";\n\nexport function fold (data: IRow[], query: IFoldQuery): IRow[] {\n const { foldBy, newFoldKeyCol, newFoldValueCol } = query;\n const ans: IRow[] = [];\n for (let row of data) {\n for (let k of foldBy) {\n const newRow = { ...row };\n newRow[newFoldKeyCol] = k;\n newRow[newFoldValueCol] = row[k];\n delete newRow[k];\n ans.push(newRow);\n }\n }\n return ans;\n}","import { IRow } from \"../../interfaces\";\nimport { IBinQuery } from \"../interfaces\";\n\nexport function bin (dataSource: IRow[], query: IBinQuery): IRow[] {\n const { binBy, newBinCol, binSize } = query;\n let _min = Infinity;\n let _max = -Infinity;\n for (let i = 0; i < dataSource.length; i++) {\n let val = dataSource[i][binBy];\n if (val > _max) _max = val;\n if (val < _min) _min = val;\n }\n const step = (_max - _min) / binSize;\n // const beaStep = Math.max(-Math.round(Math.log10(_max - _min)) + 2, 0)\n return dataSource.map((r) => {\n let bIndex = Math.floor((r[binBy] - _min) / step);\n if (bIndex === binSize) bIndex = binSize - 1;\n return {\n ...r,\n [newBinCol]: [bIndex * step + _min, (bIndex + 1) * step + _min],\n \n // [binFid]: Number(((bIndex * step + _min)).toFixed(beaStep)),\n };\n });\n}","import { IMutField, IRow } from \"../interfaces\";\nimport { aggregate } from \"./op/aggregate\";\nimport { fold } from \"./op/fold\";\nimport { IAggQuery, IBinQuery, IFoldQuery, IRawQuery } from \"./interfaces\";\nimport { bin } from \"./op/bin\";\n\nexport type IViewQuery = IAggQuery | IFoldQuery | IBinQuery | IRawQuery;\n\nexport function queryView (rawData: IRow[], metas: IMutField[], query: IViewQuery) {\n switch (query.op) {\n case 'aggregate':\n return aggregate(rawData, query);\n case 'fold':\n return fold(rawData, query);\n case 'bin':\n return bin(rawData, query);\n case 'raw':\n default:\n return rawData;\n }\n\n}","import { queryView } from '../lib/viewQuery'\nconst main = e => {\n try {\n const { dataSource, metas, query } = e.data;\n const ans = queryView(dataSource, metas, query);\n self.postMessage(ans);\n\n } catch (err) {\n // console.log(err.s)\n // log err stack\n console.error(err.stack);\n self.postMessage(err.stack);\n }\n};\n\nself.addEventListener('message', main, false);\n"],"names":["mean","nums","a","b","sum","median","sorted","mid","variance","m","x","stdev","max","ans","n","min","count","aggregatorMap","KEY_JOINER","aggregate","data","query","groupBy","agg","groups","row","gk","k","_a","subGroup","aggRow","meaKey","values","r","aggregator","fold","foldBy","newFoldKeyCol","newFoldValueCol","newRow","bin","dataSource","binBy","newBinCol","binSize","_min","_max","i","val","step","bIndex","queryView","rawData","metas","main","e","err"],"mappings":"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"}
|