@nshiab/simple-data-analysis-core 2.0.4 → 2.0.5

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.
Files changed (57) hide show
  1. package/esm/class/SimpleTable.d.ts +202 -8
  2. package/esm/class/SimpleTable.d.ts.map +1 -1
  3. package/esm/class/SimpleTable.js +211 -9
  4. package/esm/methods/addCharacterCount.d.ts +3 -0
  5. package/esm/methods/addCharacterCount.d.ts.map +1 -0
  6. package/esm/methods/addCharacterCount.js +15 -0
  7. package/esm/methods/addGeoNoise.d.ts +7 -0
  8. package/esm/methods/addGeoNoise.d.ts.map +1 -0
  9. package/esm/methods/addGeoNoise.js +135 -0
  10. package/esm/methods/addNoise.d.ts +5 -0
  11. package/esm/methods/addNoise.d.ts.map +1 -0
  12. package/esm/methods/addNoise.js +53 -0
  13. package/esm/methods/addWordCount.d.ts +3 -0
  14. package/esm/methods/addWordCount.d.ts.map +1 -0
  15. package/esm/methods/addWordCount.js +15 -0
  16. package/esm/methods/columnProportions.d.ts +1 -0
  17. package/esm/methods/columnProportions.d.ts.map +1 -1
  18. package/esm/methods/columnProportions.js +7 -2
  19. package/esm/methods/loadArray.d.ts +4 -2
  20. package/esm/methods/loadArray.d.ts.map +1 -1
  21. package/esm/methods/loadArray.js +113 -4
  22. package/esm/methods/loadYahooFinanceData.d.ts +10 -0
  23. package/esm/methods/loadYahooFinanceData.d.ts.map +1 -0
  24. package/esm/methods/loadYahooFinanceData.js +133 -0
  25. package/esm/methods/rowProportions.d.ts +1 -0
  26. package/esm/methods/rowProportions.d.ts.map +1 -1
  27. package/esm/methods/rowProportions.js +5 -1
  28. package/llm.md +291 -14
  29. package/llms.txt +1 -1
  30. package/package.json +1 -1
  31. package/script/class/SimpleTable.d.ts +202 -8
  32. package/script/class/SimpleTable.d.ts.map +1 -1
  33. package/script/class/SimpleTable.js +211 -9
  34. package/script/methods/addCharacterCount.d.ts +3 -0
  35. package/script/methods/addCharacterCount.d.ts.map +1 -0
  36. package/script/methods/addCharacterCount.js +21 -0
  37. package/script/methods/addGeoNoise.d.ts +7 -0
  38. package/script/methods/addGeoNoise.d.ts.map +1 -0
  39. package/script/methods/addGeoNoise.js +141 -0
  40. package/script/methods/addNoise.d.ts +5 -0
  41. package/script/methods/addNoise.d.ts.map +1 -0
  42. package/script/methods/addNoise.js +59 -0
  43. package/script/methods/addWordCount.d.ts +3 -0
  44. package/script/methods/addWordCount.d.ts.map +1 -0
  45. package/script/methods/addWordCount.js +21 -0
  46. package/script/methods/columnProportions.d.ts +1 -0
  47. package/script/methods/columnProportions.d.ts.map +1 -1
  48. package/script/methods/columnProportions.js +7 -2
  49. package/script/methods/loadArray.d.ts +4 -2
  50. package/script/methods/loadArray.d.ts.map +1 -1
  51. package/script/methods/loadArray.js +112 -3
  52. package/script/methods/loadYahooFinanceData.d.ts +10 -0
  53. package/script/methods/loadYahooFinanceData.d.ts.map +1 -0
  54. package/script/methods/loadYahooFinanceData.js +139 -0
  55. package/script/methods/rowProportions.d.ts +1 -0
  56. package/script/methods/rowProportions.d.ts.map +1 -1
  57. package/script/methods/rowProportions.js +5 -1
package/llm.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # The Simple Data Analysis (Core) Library
2
2
 
3
3
  - Package: `@nshiab/simple-data-analysis-core`
4
- - Version: `2.0.4`
4
+ - Version: `2.0.5`
5
5
 
6
6
  To install the library with Deno, use:
7
7
 
@@ -762,8 +762,9 @@ await table.setTypes({
762
762
 
763
763
  #### `loadArray`
764
764
 
765
- Loads an array of JavaScript objects into the table. This method queues the
766
- load; it runs when an async observer method (like `getData()` or `log()`) is
765
+ Loads an array of JavaScript objects into the table. Types can also be specified
766
+ for individual columns instead of inferred from their values. This method queues
767
+ the load; it runs when an async observer method (like `getData()` or `log()`) is
767
768
  awaited, or when `run()` is called.
768
769
 
769
770
  JavaScript `Date` values are inferred as DuckDB `TIMESTAMP` values. Their
@@ -774,13 +775,17 @@ offset originally used to construct it. String values remain `VARCHAR`; use
774
775
  ##### Signature
775
776
 
776
777
  ```typescript
777
- loadArray(rows: Record<string, unknown>[]): this;
778
+ loadArray(rows: Record<string, unknown>[], options?: { columnTypes?: Record<string, "integer" | "float" | "number" | "string" | "date" | "time" | "datetime" | "datetimeTz" | "bigint" | "double" | "varchar" | "timestamp" | "timestamp with time zone" | "boolean" | "INTEGER" | "BIGINT" | "DOUBLE" | "VARCHAR" | "BOOLEAN" | "DATE" | "TIME" | "TIMESTAMP" | "TIMESTAMP WITH TIME ZONE" | FLOAT[${number}] | float[${number}]> }): this;
778
779
  ```
779
780
 
780
781
  ##### Parameters
781
782
 
782
783
  - **`rows`**: An array of objects, where each object represents a row and its
783
784
  properties represent columns.
785
+ - **`options`**: Options for loading the array, captured when called.
786
+ - **`options.columnTypes`**: Types for specific columns; omitted columns are
787
+ inferred. Values must be compatible with the selected type without losing
788
+ information.
784
789
 
785
790
  ##### Returns
786
791
 
@@ -797,6 +802,14 @@ const data = [
797
802
  await table.loadArray(data).log();
798
803
  ```
799
804
 
805
+ ```ts
806
+ // Specify a numeric type for an all-null column
807
+ await table.loadArray(
808
+ [{ name: "A", value: null }, { name: "B", value: null }],
809
+ { columnTypes: { value: "DOUBLE" } },
810
+ ).log();
811
+ ```
812
+
800
813
  ```ts
801
814
  // The offset determines the instant; the loaded TIMESTAMP is returned as
802
815
  // the equivalent UTC JavaScript Date.
@@ -979,6 +992,78 @@ await table
979
992
  .log();
980
993
  ```
981
994
 
995
+ #### `loadYahooFinanceData`
996
+
997
+ Downloads historical market data from Yahoo Finance and loads it into this table
998
+ as `datetime`, `open`, `high`, `low`, `close`, `adjustedClose`, and `volume`
999
+ columns. `datetime` contains Yahoo's timestamps as JavaScript `Date` values.
1000
+ Unavailable values are preserved as `null`.
1001
+
1002
+ All range boundaries are evaluated in UTC. Use ISO date-time strings ending in
1003
+ `Z`. Yahoo trading sessions may occur on a different UTC date from their
1004
+ exchange-local date, so choose the range appropriate for the market and
1005
+ interval. Avoid numeric constructors such as `new Date(2025, 2, 15)`, which use
1006
+ the runtime's local timezone.
1007
+
1008
+ This method uses an undocumented Yahoo Finance endpoint and is not affiliated
1009
+ with or endorsed by Yahoo. It is provided for educational, research, and
1010
+ journalistic purposes. Before using it, review Yahoo's terms and any applicable
1011
+ data-provider restrictions.
1012
+
1013
+ The method queues the download and load; they run when an async observer method
1014
+ (like `getData()` or `log()`) is awaited, or when `run()` is called.
1015
+
1016
+ ##### Signature
1017
+
1018
+ ```typescript
1019
+ loadYahooFinanceData(symbol: string, startDate: Date, endDate: Date, interval: "1d" | "1h" | "1m"): this;
1020
+ ```
1021
+
1022
+ ##### Parameters
1023
+
1024
+ - **`symbol`**: The stock or index symbol, such as `"AAPL"` or `"^GSPTSE"`.
1025
+ - **`startDate`**: The inclusive UTC start of the requested range.
1026
+ - **`endDate`**: The inclusive UTC end of the requested range. The UTC day,
1027
+ hour, or minute containing this instant is included, according to `interval`.
1028
+ - **`interval`**: The interval between observations: daily, hourly, or every
1029
+ minute.
1030
+
1031
+ ##### Returns
1032
+
1033
+ The table, so methods can be chained.
1034
+
1035
+ ##### Throws
1036
+
1037
+ - **`RangeError`**: If either date is invalid or `endDate` is before
1038
+ `startDate`.
1039
+ - **`Error`**: If Yahoo rejects the request or returns no data.
1040
+
1041
+ ##### Examples
1042
+
1043
+ ```ts
1044
+ // Request daily observations using explicit UTC boundaries.
1045
+ await table
1046
+ .loadYahooFinanceData(
1047
+ "^GSPTSE",
1048
+ new Date("2025-03-01T00:00:00Z"),
1049
+ new Date("2025-03-15T00:00:00Z"),
1050
+ "1d",
1051
+ )
1052
+ .log();
1053
+ ```
1054
+
1055
+ ```ts
1056
+ // Include the UTC hours from 13:00 through 16:00.
1057
+ await table
1058
+ .loadYahooFinanceData(
1059
+ "AAPL",
1060
+ new Date("2025-03-14T13:00:00Z"),
1061
+ new Date("2025-03-14T16:00:00Z"),
1062
+ "1h",
1063
+ )
1064
+ .log();
1065
+ ```
1066
+
982
1067
  #### `loadGeoData`
983
1068
 
984
1069
  Loads geospatial data from an external file or URL into the table.
@@ -3888,6 +3973,54 @@ await table.round(["columnA", "columnB"], { decimals: 1, method: "ceiling" })
3888
3973
  await table.round("column1", 2).log();
3889
3974
  ```
3890
3975
 
3976
+ #### `addNoise`
3977
+
3978
+ Adds independently generated uniform random noise to numeric values in one or
3979
+ more columns. Each changed value receives an offset between `-max` and `max`.
3980
+ Selected integer and decimal columns become `DOUBLE` columns so fractional noise
3981
+ is retained. This method adds random jitter; it does not provide anonymization
3982
+ or differential privacy guarantees.
3983
+
3984
+ This method queues the operation; it runs when an async observer method (like
3985
+ `getData()` or `log()`) is awaited, or when `run()` is called.
3986
+
3987
+ ##### Signature
3988
+
3989
+ ```typescript
3990
+ addNoise(columns: string | string[], max: number, options?: { onlyDuplicates?: boolean }): this;
3991
+ ```
3992
+
3993
+ ##### Parameters
3994
+
3995
+ - **`columns`**: The numeric column name or array of numeric column names to
3996
+ which noise will be added. When multiple columns are provided, each value
3997
+ receives an independent random offset.
3998
+ - **`max`**: The maximum absolute offset, expressed in each column's units. Must
3999
+ be a finite number greater than or equal to `0`.
4000
+ - **`options`**: An optional object with configuration options:
4001
+ - **`options.onlyDuplicates`**: If `true`, adds noise only to values that occur
4002
+ more than once in their column. Each selected column is evaluated
4003
+ independently, and every occurrence of a duplicated value is changed. Defaults
4004
+ to `false`.
4005
+
4006
+ ##### Returns
4007
+
4008
+ The table, so methods can be chained.
4009
+
4010
+ ##### Examples
4011
+
4012
+ ```ts
4013
+ // Add an offset between -0.01 and 0.01 to every value
4014
+ await table.addNoise("measurement", 0.01).log();
4015
+ ```
4016
+
4017
+ ```ts
4018
+ // Add noise independently to duplicated x values and duplicated y values
4019
+ await table.addNoise(["x", "y"], 0.1, {
4020
+ onlyDuplicates: true,
4021
+ }).log();
4022
+ ```
4023
+
3891
4024
  #### `updateColumn`
3892
4025
 
3893
4026
  Updates values in a specified column using a SQL expression.
@@ -4089,7 +4222,7 @@ each row, adding new columns for these proportions.
4089
4222
  ##### Signature
4090
4223
 
4091
4224
  ```typescript
4092
- rowProportions(columns: string[], options?: { suffix?: string; decimals?: number }): this;
4225
+ rowProportions(columns: string[], options?: { suffix?: string; base?: number; decimals?: number }): this;
4093
4226
  ```
4094
4227
 
4095
4228
  ##### Parameters
@@ -4099,6 +4232,8 @@ rowProportions(columns: string[], options?: { suffix?: string; decimals?: number
4099
4232
  - **`options`**: An optional object with configuration options:
4100
4233
  - **`options.suffix`**: A string suffix to append to the names of the new
4101
4234
  columns storing the computed proportions. Defaults to `"Perc"`.
4235
+ - **`options.base`**: A finite positive value that the proportions in each row
4236
+ sum to before rounding. Defaults to `1`.
4102
4237
  - **`options.decimals`**: The number of decimal places to round the computed
4103
4238
  proportions. Defaults to `undefined` (no rounding).
4104
4239
 
@@ -4141,6 +4276,14 @@ The table will then look like this:
4141
4276
  | 2022 | 354 | 278 | 56 | 0.51 | 0.4 | 0.08 |
4142
4277
  | 2023 | 856 | 321 | 221 | 0.61 | 0.23 | 0.16 |
4143
4278
 
4279
+ ```ts
4280
+ // Compute percentages that sum to 100 on each row before rounding
4281
+ await table.rowProportions(["Men", "Women", "NonBinary"], {
4282
+ base: 100,
4283
+ decimals: 1,
4284
+ }).log();
4285
+ ```
4286
+
4144
4287
  This method queues the operation; it runs when an async observer method (like
4145
4288
  `getData()` or `log()`) is awaited, or when `run()` is called.
4146
4289
 
@@ -4216,7 +4359,7 @@ This method queues the operation; it runs when an async observer method (like
4216
4359
  ##### Signature
4217
4360
 
4218
4361
  ```typescript
4219
- columnProportions(column: string, newColumn: string, options?: { by?: string | string[]; decimals?: number }): this;
4362
+ columnProportions(column: string, newColumn: string, options?: { by?: string | string[]; base?: number; decimals?: number }): this;
4220
4363
  ```
4221
4364
 
4222
4365
  ##### Parameters
@@ -4229,6 +4372,8 @@ columnProportions(column: string, newColumn: string, options?: { by?: string | s
4229
4372
  - **`options`**: An optional object with configuration options:
4230
4373
  - **`options.by`**: The column name or an array of column names to partition by.
4231
4374
  Proportions are calculated independently within each group.
4375
+ - **`options.base`**: A finite positive value that the proportions in the column
4376
+ or each group sum to before rounding. Defaults to `1`.
4232
4377
  - **`options.decimals`**: The number of decimal places to round the computed
4233
4378
  proportions. Defaults to `undefined` (no rounding).
4234
4379
 
@@ -4249,6 +4394,14 @@ await table.columnProportions("column1", "perc", { by: "column2", decimals: 2 })
4249
4394
  .log();
4250
4395
  ```
4251
4396
 
4397
+ ```ts
4398
+ // Compute percentages that sum to 100 before rounding
4399
+ await table.columnProportions("sales", "sales_percentage", {
4400
+ base: 100,
4401
+ decimals: 1,
4402
+ }).log();
4403
+ ```
4404
+
4252
4405
  ```ts
4253
4406
  // Compute proportions for 'sales' by 'region' and 'product_type'
4254
4407
  await table.columnProportions("sales", "sales_proportion", {
@@ -4956,18 +5109,14 @@ The table, so methods can be chained.
4956
5109
  ##### Examples
4957
5110
 
4958
5111
  ```ts
4959
- // Count words correctly across multilingual article text.
4960
- const segmenter = new Intl.Segmenter(undefined, { granularity: "word" });
5112
+ // Extract hostnames with JavaScript's URL parser.
4961
5113
  const table = await sdb
4962
5114
  .newTable()
4963
- .loadData("articles.csv")
5115
+ .loadData("websites.csv")
4964
5116
  .updateWithJS((rows) => {
4965
5117
  return rows.map((row) => ({
4966
5118
  ...row,
4967
- wordCount: typeof row.text === "string"
4968
- ? [...segmenter.segment(row.text)].filter((part) => part.isWordLike)
4969
- .length
4970
- : null,
5119
+ hostname: typeof row.url === "string" ? new URL(row.url).hostname : null,
4971
5120
  }));
4972
5121
  })
4973
5122
  .log();
@@ -5155,9 +5304,81 @@ const columnCount = await table.getColumnCount();
5155
5304
  console.log(columnCount); // e.g., 3
5156
5305
  ```
5157
5306
 
5307
+ #### `addCharacterCount`
5308
+
5309
+ Adds a new column containing the number of characters in each string in the
5310
+ specified column. Counts are based on Unicode code points, not grapheme
5311
+ clusters. A user-perceived character composed of multiple code points, such as
5312
+ some emoji or decomposed accented letters, counts as multiple characters. `NULL`
5313
+ input values produce `NULL` counts.
5314
+
5315
+ This method queues the operation; it runs when an async observer method (like
5316
+ `getData()` or `log()`) is awaited, or when `run()` is called.
5317
+
5318
+ ##### Signature
5319
+
5320
+ ```typescript
5321
+ addCharacterCount(column: string, newColumn: string): this;
5322
+ ```
5323
+
5324
+ ##### Parameters
5325
+
5326
+ - **`column`**: The name of the column containing the strings to count.
5327
+ - **`newColumn`**: The name of the new column where the character counts will be
5328
+ stored.
5329
+
5330
+ ##### Returns
5331
+
5332
+ The table, so methods can be chained.
5333
+
5334
+ ##### Examples
5335
+
5336
+ ```ts
5337
+ // Add a character count for each value in the 'name' column
5338
+ await table.addCharacterCount("name", "nameCharacterCount").log();
5339
+ ```
5340
+
5341
+ #### `addWordCount`
5342
+
5343
+ Adds a new column containing the word count for each string in the specified
5344
+ column. A word is any contiguous sequence of non-whitespace characters. Spaces,
5345
+ tabs, and line breaks separate words. Punctuation is not removed, so a
5346
+ standalone punctuation sequence counts as a word. Text without whitespace counts
5347
+ as one word, regardless of language. Empty or whitespace-only strings produce
5348
+ `0`, and `NULL` input values produce `NULL` counts.
5349
+
5350
+ This method queues the operation; it runs when an async observer method (like
5351
+ `getData()` or `log()`) is awaited, or when `run()` is called.
5352
+
5353
+ ##### Signature
5354
+
5355
+ ```typescript
5356
+ addWordCount(column: string, newColumn: string): this;
5357
+ ```
5358
+
5359
+ ##### Parameters
5360
+
5361
+ - **`column`**: The name of the column containing the strings to count.
5362
+ - **`newColumn`**: The name of the new column where the word counts will be
5363
+ stored.
5364
+
5365
+ ##### Returns
5366
+
5367
+ The table, so methods can be chained.
5368
+
5369
+ ##### Examples
5370
+
5371
+ ```ts
5372
+ // Add a word count for each value in the 'article' column
5373
+ await table.addWordCount("article", "wordCount").log();
5374
+ ```
5375
+
5158
5376
  #### `getCharacterCount`
5159
5377
 
5160
- Returns the total number of characters in a column storing strings.
5378
+ Returns the total number of characters in a column storing strings. Counts are
5379
+ based on Unicode code points, not grapheme clusters. A user-perceived character
5380
+ composed of multiple code points, such as some emoji or decomposed accented
5381
+ letters, counts as multiple characters.
5161
5382
 
5162
5383
  ##### Signature
5163
5384
 
@@ -6318,6 +6539,62 @@ await table.flipCoordinates().log();
6318
6539
  await table.flipCoordinates("myGeom").log();
6319
6540
  ```
6320
6541
 
6542
+ #### `addGeoNoise`
6543
+
6544
+ Moves EPSG:4326 point geometries to random locations within a maximum
6545
+ great-circle distance of their original positions.
6546
+
6547
+ Points are sampled uniformly within the requested distance using the spherical
6548
+ direct geodesic (destination-point) formula and the same spherical Earth model
6549
+ as DuckDB's `ST_Distance_Sphere()`. This accounts for longitude scale changing
6550
+ with latitude. This method adds random jitter; it does not provide anonymization
6551
+ or differential privacy guarantees.
6552
+
6553
+ This method supports only `POINT` geometries in `EPSG:4326`. Null and empty
6554
+ geometries are preserved. It queues the operation; the operation runs when an
6555
+ async observer method (like `getData()` or `log()`) is awaited, or when `run()`
6556
+ is called.
6557
+
6558
+ ##### Signature
6559
+
6560
+ ```typescript
6561
+ addGeoNoise(maxDistance: number, options?: { column?: string; unit?: "m" | "km"; onlyDuplicates?: boolean }): this;
6562
+ ```
6563
+
6564
+ ##### Parameters
6565
+
6566
+ - **`maxDistance`**: The maximum great-circle displacement in the selected unit.
6567
+ Must be a finite number greater than or equal to `0` and no greater than half
6568
+ Earth's circumference.
6569
+ - **`options`**: An optional object with configuration options:
6570
+ - **`options.column`**: The name of the EPSG:4326 point geometry column. If
6571
+ omitted, the method will automatically attempt to find a geometry column.
6572
+ - **`options.unit`**: The unit of `maxDistance`: `"m"` for metres or `"km"` for
6573
+ kilometres. Defaults to `"m"`.
6574
+ - **`options.onlyDuplicates`**: If `true`, moves only points whose complete
6575
+ original geometry occurs more than once in the selected geometry column. Every
6576
+ point in a duplicated group is moved. Defaults to `false`.
6577
+
6578
+ ##### Returns
6579
+
6580
+ The table, so methods can be chained.
6581
+
6582
+ ##### Examples
6583
+
6584
+ ```ts
6585
+ // Move every point by no more than 500 metres
6586
+ await table.addGeoNoise(500).log();
6587
+ ```
6588
+
6589
+ ```ts
6590
+ // Separate duplicated points by up to 0.1 kilometres
6591
+ await table.addGeoNoise(0.1, {
6592
+ column: "geom",
6593
+ unit: "km",
6594
+ onlyDuplicates: true,
6595
+ }).log();
6596
+ ```
6597
+
6321
6598
  #### `reducePrecision`
6322
6599
 
6323
6600
  Reduces the precision of geometries in a specified column to a given number of
package/llms.txt CHANGED
@@ -3,7 +3,7 @@
3
3
  > Lightweight DuckDB-powered TypeScript library for tabular, SQL, CSV, Parquet, and geospatial data analysis on Deno, Node.js, and Bun.
4
4
 
5
5
  - Package: `@nshiab/simple-data-analysis-core`
6
- - Version: `2.0.4`
6
+ - Version: `2.0.5`
7
7
 
8
8
  Install with Deno: `deno add jsr:@nshiab/simple-data-analysis-core`
9
9
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nshiab/simple-data-analysis-core",
3
- "version": "2.0.4",
3
+ "version": "2.0.5",
4
4
  "description": "Lightweight DuckDB-powered TypeScript library for tabular, SQL, CSV, Parquet, and geospatial data analysis on Deno, Node.js, and Bun.",
5
5
  "keywords": [
6
6
  "data-analysis",