-
Notifications
You must be signed in to change notification settings - Fork 649
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: sample function --------- Co-authored-by: xuying.xu <[email protected]>
- Loading branch information
1 parent
8fa1e63
commit 57ef157
Showing
13 changed files
with
422 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
# Logs | ||
logs | ||
*.log | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
|
||
# lock | ||
package-lock.json | ||
|
||
# Runtime data | ||
pids | ||
*.pid | ||
*.seed | ||
*.pid.lock | ||
|
||
# Directory for instrumented libs generated by jscoverage/JSCover | ||
lib-cov | ||
|
||
# Coverage directory used by tools like istanbul | ||
coverage | ||
|
||
# nyc test coverage | ||
.nyc_output | ||
|
||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) | ||
.grunt | ||
|
||
# Bower dependency directory (https://bower.io/) | ||
bower_components | ||
|
||
# node-waf configuration | ||
.lock-wscript | ||
|
||
# Compiled binary addons (http://nodejs.org/api/addons.html) | ||
build/Release | ||
|
||
# Dependency directories | ||
node_modules/ | ||
jspm_packages/ | ||
|
||
# Typescript v1 declaration files | ||
typings/ | ||
|
||
# Optional npm cache directory | ||
.npm | ||
|
||
# Optional eslint cache | ||
.eslintcache | ||
|
||
# Optional REPL history | ||
.node_repl_history | ||
|
||
# Output of 'npm pack' | ||
*.tgz | ||
|
||
# Yarn Integrity file | ||
.yarn-integrity | ||
|
||
# dotenv environment variables file | ||
.env | ||
|
||
.DS_Store | ||
|
||
# npmignore - content above this line is automatically generated and modifications may be omitted | ||
# see npmjs.com/npmignore for more details. | ||
test | ||
|
||
*.sw* | ||
*.un~ | ||
.idea | ||
bin | ||
demos | ||
docs | ||
temp | ||
webpack-dev.config.js | ||
webpack.config.js | ||
examples | ||
site | ||
gatsby-browser.js | ||
gatsby-config.js | ||
.cache | ||
public |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
# Change Log |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
MIT LICENSE | ||
|
||
Copyright (c) 2015-present Alipay.com, https://www.alipay.com/ | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining | ||
a copy of this software and associated documentation files (the | ||
"Software"), to deal in the Software without restriction, including | ||
without limitation the rights to use, copy, modify, merge, publish, | ||
distribute, sublicense, and/or sell copies of the Software, and to | ||
permit persons to whom the Software is furnished to do so, subject to | ||
the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be | ||
included in all copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | ||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | ||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | ||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
F2 的 算法库 | ||
|
||
常用算法扩展包 | ||
|
||
## Usage | ||
|
||
```jsx | ||
import dataSample from '@antv/f2-algorithm'; | ||
|
||
const sampleData = dataSample({ | ||
data, | ||
sampling: 'nearest', | ||
rate: 7, | ||
}); | ||
|
||
<Canvas pixelRatio={1}> | ||
<Chart data={sampleData}> | ||
<Line x="date" y="value" /> | ||
</Chart> | ||
</Canvas>; | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
{ | ||
"name": "f2-algorithm", | ||
"version": "5.0.0", | ||
"description": "F2 algorithm extension", | ||
"main": "lib/index.js", | ||
"module": "es/index.js", | ||
"types": "es/index.d.ts", | ||
"sideEffects": false, | ||
"keywords": [ | ||
"antv", | ||
"f2", | ||
"chart", | ||
"charts", | ||
"mobile", | ||
"visualization", | ||
"react", | ||
"sample" | ||
], | ||
"dependencies": { | ||
"@babel/runtime": "^7.12.5", | ||
"tslib": "^2.3.1" | ||
}, | ||
"devDependencies": { | ||
"@antv/f2": "^5.0.27", | ||
"@antv/f-test-utils": "^1.0.1", | ||
"jest-mock-random": "~1.1.1" | ||
}, | ||
"homepage": "https://f2.antv.vision/zh/", | ||
"author": "https://github.com/orgs/antvis/people", | ||
"license": "MIT", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/antvis/f2" | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/antvis/f2/issues" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
import lttbDownSample from './lttbDownSample'; | ||
import rateDownSample from './rateDownSample'; | ||
|
||
export { lttbDownSample, rateDownSample }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
/** | ||
* Large data down sampling using largest-triangle-three-buckets. | ||
* A B C | ||
* | ||
* 桶:包含数据子区间的有序集。 | ||
* @param {string} data | ||
* @param {number} rate | ||
* * @param {number} dimension | ||
*/ | ||
|
||
export interface OptionsProps { | ||
/*周期 */ | ||
rate: number; | ||
dimension: string; | ||
} | ||
|
||
export default function lttbDownSample(data, options?: OptionsProps) { | ||
const { rate = 5, dimension = 'value' } = options; | ||
const len = data.length; | ||
const targetCount = len / rate; | ||
if (targetCount >= len || targetCount === 0) { | ||
return data; | ||
} | ||
|
||
const sampled = []; | ||
let sampledIndex = 0; | ||
// Bucket size | ||
const bucketSize = Math.floor((len - 2) / (targetCount - 2)); | ||
|
||
// A is the first point in the triangle | ||
let a = 0, | ||
maxAreaPoint, | ||
maxArea, | ||
area, | ||
// B Bucket | ||
nextA; | ||
|
||
sampled[sampledIndex++] = data[a]; | ||
|
||
for (let i = 1; i < len - 1; i += bucketSize) { | ||
// Calculate point average for C bucket | ||
let avgRangeStart = Math.min(i + bucketSize, len - 1); | ||
const avgRangeEnd = Math.min(i + 2 * bucketSize, len); | ||
|
||
const avgX = (avgRangeEnd + avgRangeStart) / 2; | ||
let avgY = 0; | ||
const avgLength = avgRangeEnd - avgRangeStart; | ||
for (; avgRangeStart < avgRangeEnd; avgRangeStart++) { | ||
avgY += Number(data[avgRangeStart][dimension]); | ||
} | ||
// 桶的平均数 | ||
avgY /= avgLength; | ||
|
||
// Get the range for B bucket | ||
const rangeTo = Math.min(i + bucketSize, len); | ||
|
||
// Point a | ||
const pointA_x = i - 1; | ||
const pointA_y = Number(data[a][dimension]); | ||
maxArea = area = -1; | ||
|
||
for (let rangeOffs = i; rangeOffs < rangeTo; rangeOffs++) { | ||
// Calculate triangle area over three buckets | ||
area = | ||
Math.abs( | ||
(pointA_x - avgX) * (Number(data[rangeOffs][dimension]) - pointA_y) - | ||
(pointA_x - rangeOffs) * (avgY - pointA_y) | ||
) * 0.5; | ||
if (area > maxArea) { | ||
maxArea = area; | ||
maxAreaPoint = data[rangeOffs]; | ||
nextA = rangeOffs; | ||
} | ||
} | ||
|
||
sampled[sampledIndex++] = maxAreaPoint; | ||
a = nextA; // T | ||
} | ||
sampled[sampledIndex++] = data[len - 1]; | ||
return sampled; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
import { isString, isFunction } from '@antv/util'; | ||
|
||
/** | ||
* data down sampling | ||
* 常见统计采样,最大最小固定点等 | ||
* @param {string} data | ||
* @param {number} targetCount | ||
* @param {string} sampler | ||
*/ | ||
|
||
function downSample(data, rate, sampler, dimension) { | ||
const sampled = []; | ||
let sampledIndex = 0; | ||
const len = data.length; | ||
let frameSize = Math.floor(rate); | ||
|
||
for (let i = 0; i < len; i += frameSize) { | ||
// Last frame | ||
frameSize = frameSize > len - i ? len - i : frameSize; | ||
const frameValues = []; | ||
|
||
for (let k = 0; k < frameSize; k++) { | ||
frameValues[k] = data[k + i]; | ||
} | ||
|
||
const value = sampler(frameValues, dimension); | ||
sampled[sampledIndex++] = value; | ||
} | ||
|
||
return sampled; | ||
} | ||
|
||
const samplers = { | ||
max: (frame, dimension) => { | ||
const max = -Infinity; | ||
let maxData; | ||
for (let i = 0; i < frame.length; i++) { | ||
frame[i][dimension] > max && (maxData = frame[i]); | ||
} | ||
return maxData || NaN; | ||
}, | ||
min: (frame, dimension) => { | ||
const min = Infinity; | ||
let minData; | ||
for (let i = 0; i < frame.length; i++) { | ||
frame[i][dimension] < min && (minData = frame[i]); | ||
} | ||
return minData || NaN; | ||
}, | ||
// TODO 中位数 median | ||
nearest: (frame) => { | ||
return frame[0]; | ||
}, | ||
}; | ||
|
||
export interface OptionsProps { | ||
sampling: 'nearest' | 'max' | 'min' | Function; | ||
/* 周期 */ | ||
rate: number; | ||
dimension: string; | ||
} | ||
|
||
export default function rateDownSample(data, options?: OptionsProps) { | ||
const { sampling = 'nearest', rate = 5, dimension = 'value' } = options; | ||
let sampler; | ||
if (isFinite(rate) && rate > 1) { | ||
if (isString(sampling)) { | ||
sampler = samplers[sampling]; | ||
} else if (isFunction(sampling)) { | ||
sampler = sampling; | ||
} | ||
|
||
return downSample(data, rate, sampler, dimension); | ||
} | ||
return data; | ||
} |
Binary file added
BIN
+8.13 KB
...lgorithm/test/__image_snapshots__/sample-test-tsx-sample-lttb-sample-1-snap.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+6.75 KB
...rithm/test/__image_snapshots__/sample-test-tsx-sample-nearest-sample-1-snap.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+8.24 KB
...lgorithm/test/__image_snapshots__/sample-test-tsx-sample-origin-data-1-snap.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.