svelteplot 0.7.1-pr-280.15 → 0.7.1-pr-280.16

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.
@@ -17,10 +17,13 @@ type DensityOptions<T> = {
17
17
  */
18
18
  interval?: number | string;
19
19
  /**
20
- *
20
+ * If true, the density values will be trimmed to the range of the data.
21
21
  */
22
22
  trim?: boolean;
23
- weight?: (d: T) => number;
23
+ /**
24
+ * If true, the density values will be cumulative.
25
+ */
26
+ cumulative?: false | 1 | -1;
24
27
  };
25
28
  /**
26
29
  * One-dimensional kernel density estimation
@@ -102,11 +102,12 @@ function roundToTerminating(x, sig = 2) {
102
102
  }
103
103
  function density1d(independent, { data, weight, ...channels }, options = {}) {
104
104
  const densityChannel = independent === 'x' ? 'y' : 'x';
105
- const { kernel, bandwidth, interval, trim, channel } = {
105
+ const { kernel, bandwidth, interval, trim, channel, cumulative } = {
106
106
  kernel: 'epanechnikov',
107
107
  bandwidth: bandwidthSilverman,
108
108
  interval: undefined,
109
109
  trim: false,
110
+ cumulative: false,
110
111
  channel: densityChannel,
111
112
  ...options
112
113
  };
@@ -143,7 +144,7 @@ function density1d(independent, { data, weight, ...channels }, options = {}) {
143
144
  const res = groupFacetsAndZ(resolvedData, channels, (items, groupProps) => {
144
145
  const values = items.map((d) => d[VALUE]);
145
146
  const weights = items.map((d) => d[WEIGHT]);
146
- let kdeValues = kde1d(values, weights, atValues, k, bw)
147
+ let kdeValues = kde1d(values, weights, atValues, k, bw, cumulative)
147
148
  .filter(([x, density]) => x != null && !isNaN(density))
148
149
  .sort((a, b) => a[0] - b[0]);
149
150
  if (!trim) {
@@ -165,16 +166,16 @@ function density1d(independent, { data, weight, ...channels }, options = {}) {
165
166
  [independent]: CHANNELS[independent],
166
167
  [channel]: CHANNELS[densityChannel],
167
168
  ...res,
168
- [ORIGINAL_NAME_KEYS[densityChannel]]: 'Density',
169
+ [ORIGINAL_NAME_KEYS[densityChannel]]: cumulative === false ? 'Density' : 'CDF',
169
170
  [ORIGINAL_NAME_KEYS[independent]]: typeof channels[independent] === 'string' ? channels[independent] : undefined,
170
171
  sort: [{ channel: CHANNELS[independent], order: 'ascending' }],
171
172
  data: outData
172
173
  };
173
174
  }
174
- function kde1d(values, weights, atValues, kernel, bw) {
175
+ function kde1d(values, weights, atValues, kernel, bw, cumulative) {
175
176
  const n = values.length;
176
177
  const weightSum = weights.reduce((a, b) => a + b, 0);
177
- return atValues.map((x) => {
178
+ const densities = atValues.map((x) => {
178
179
  let sum = 0;
179
180
  for (let i = 0; i < n; i++) {
180
181
  const u = (x - values[i]) / bw;
@@ -182,6 +183,38 @@ function kde1d(values, weights, atValues, kernel, bw) {
182
183
  }
183
184
  return [x, sum / (weightSum * bw)];
184
185
  });
186
+ if (!cumulative)
187
+ return densities;
188
+ const totalArea = densities.reduce((acc, curr, i) => {
189
+ if (i === 0)
190
+ return acc;
191
+ const dx = densities[i][0] - densities[i - 1][0];
192
+ return acc + ((densities[i - 1][1] + curr[1]) / 2) * dx;
193
+ }, 0);
194
+ if (totalArea === 0)
195
+ return densities;
196
+ if (cumulative === -1) {
197
+ let area = 0;
198
+ const cdf = new Array(densities.length);
199
+ for (let i = densities.length - 1; i >= 0; i--) {
200
+ if (i < densities.length - 1) {
201
+ const dx = densities[i + 1][0] - densities[i][0];
202
+ area += ((densities[i + 1][1] + densities[i][1]) / 2) * dx;
203
+ }
204
+ cdf[i] = [densities[i][0], area / totalArea];
205
+ }
206
+ return cdf;
207
+ }
208
+ let area = 0;
209
+ const cdf = new Array(densities.length);
210
+ for (let i = 0; i < densities.length; i++) {
211
+ if (i > 0) {
212
+ const dx = densities[i][0] - densities[i - 1][0];
213
+ area += ((densities[i - 1][1] + densities[i][1]) / 2) * dx;
214
+ }
215
+ cdf[i] = [densities[i][0], area / totalArea];
216
+ }
217
+ return cdf;
185
218
  }
186
219
  function maybeKernel(kernel) {
187
220
  if (typeof kernel === 'function')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svelteplot",
3
- "version": "0.7.1-pr-280.15",
3
+ "version": "0.7.1-pr-280.16",
4
4
  "license": "ISC",
5
5
  "author": {
6
6
  "name": "Gregor Aisch",