@tidyjs/tidy 2.5.2 → 2.6.1

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 (245) hide show
  1. package/dist/es/addRows.js.map +1 -1
  2. package/dist/es/arrange.js +9 -5
  3. package/dist/es/arrange.js.map +1 -1
  4. package/dist/es/complete.js.map +1 -1
  5. package/dist/es/count.js +6 -2
  6. package/dist/es/count.js.map +1 -1
  7. package/dist/es/debug.js +4 -2
  8. package/dist/es/debug.js.map +1 -1
  9. package/dist/es/distinct.js +3 -3
  10. package/dist/es/distinct.js.map +1 -1
  11. package/dist/es/expand.js +18 -13
  12. package/dist/es/expand.js.map +1 -1
  13. package/dist/es/fill.js +10 -3
  14. package/dist/es/fill.js.map +1 -1
  15. package/dist/es/filter.js.map +1 -1
  16. package/dist/es/fullJoin.js +23 -20
  17. package/dist/es/fullJoin.js.map +1 -1
  18. package/dist/es/groupBy.js +56 -28
  19. package/dist/es/groupBy.js.map +1 -1
  20. package/dist/es/helpers/assignGroupKeys.js +4 -4
  21. package/dist/es/helpers/assignGroupKeys.js.map +1 -1
  22. package/dist/es/helpers/groupMap.js +2 -2
  23. package/dist/es/helpers/groupMap.js.map +1 -1
  24. package/dist/es/helpers/groupTraversal.js +5 -4
  25. package/dist/es/helpers/groupTraversal.js.map +1 -1
  26. package/dist/es/helpers/identity.js.map +1 -1
  27. package/dist/es/helpers/isObject.js.map +1 -1
  28. package/dist/es/helpers/keysFromItems.js +1 -2
  29. package/dist/es/helpers/keysFromItems.js.map +1 -1
  30. package/dist/es/helpers/singleOrArray.js.map +1 -1
  31. package/dist/es/helpers/summation.js +11 -3
  32. package/dist/es/helpers/summation.js.map +1 -1
  33. package/dist/es/innerJoin.js +37 -12
  34. package/dist/es/innerJoin.js.map +1 -1
  35. package/dist/es/item/rate.js +2 -3
  36. package/dist/es/item/rate.js.map +1 -1
  37. package/dist/es/leftJoin.js +13 -8
  38. package/dist/es/leftJoin.js.map +1 -1
  39. package/dist/es/map.js.map +1 -1
  40. package/dist/es/math/math.js.map +1 -1
  41. package/dist/es/mutate.js +1 -1
  42. package/dist/es/mutate.js.map +1 -1
  43. package/dist/es/mutateWithSummary.js +1 -1
  44. package/dist/es/mutateWithSummary.js.map +1 -1
  45. package/dist/es/pivotLonger.js +31 -7
  46. package/dist/es/pivotLonger.js.map +1 -1
  47. package/dist/es/pivotWider.js +24 -19
  48. package/dist/es/pivotWider.js.map +1 -1
  49. package/dist/es/rename.js.map +1 -1
  50. package/dist/es/replaceNully.js +1 -1
  51. package/dist/es/replaceNully.js.map +1 -1
  52. package/dist/es/select.js +3 -3
  53. package/dist/es/select.js.map +1 -1
  54. package/dist/es/selectors/contains.js.map +1 -1
  55. package/dist/es/selectors/endsWith.js.map +1 -1
  56. package/dist/es/selectors/everything.js.map +1 -1
  57. package/dist/es/selectors/matches.js.map +1 -1
  58. package/dist/es/selectors/negate.js +2 -2
  59. package/dist/es/selectors/negate.js.map +1 -1
  60. package/dist/es/selectors/numRange.js.map +1 -1
  61. package/dist/es/selectors/startsWith.js.map +1 -1
  62. package/dist/es/sequences/fullSeq.js +5 -1
  63. package/dist/es/sequences/fullSeq.js.map +1 -1
  64. package/dist/es/slice.js +2 -3
  65. package/dist/es/slice.js.map +1 -1
  66. package/dist/es/summarize.js +6 -4
  67. package/dist/es/summarize.js.map +1 -1
  68. package/dist/es/summary/deviation.js.map +1 -1
  69. package/dist/es/summary/first.js.map +1 -1
  70. package/dist/es/summary/last.js.map +1 -1
  71. package/dist/es/summary/max.js.map +1 -1
  72. package/dist/es/summary/mean.js.map +1 -1
  73. package/dist/es/summary/meanRate.js.map +1 -1
  74. package/dist/es/summary/median.js.map +1 -1
  75. package/dist/es/summary/min.js.map +1 -1
  76. package/dist/es/summary/n.js.map +1 -1
  77. package/dist/es/summary/nDistinct.js +2 -2
  78. package/dist/es/summary/nDistinct.js.map +1 -1
  79. package/dist/es/summary/sum.js.map +1 -1
  80. package/dist/es/summary/variance.js.map +1 -1
  81. package/dist/es/tally.js +4 -2
  82. package/dist/es/tally.js.map +1 -1
  83. package/dist/es/tidy.js.map +1 -1
  84. package/dist/es/total.js.map +1 -1
  85. package/dist/es/transmute.js.map +1 -1
  86. package/dist/es/vector/cumsum.js.map +1 -1
  87. package/dist/es/vector/lag.js +1 -1
  88. package/dist/es/vector/lag.js.map +1 -1
  89. package/dist/es/vector/lead.js +1 -1
  90. package/dist/es/vector/lead.js.map +1 -1
  91. package/dist/es/vector/roll.js +1 -1
  92. package/dist/es/vector/roll.js.map +1 -1
  93. package/dist/es/vector/rowNumber.js.map +1 -1
  94. package/dist/es/when.js +1 -2
  95. package/dist/es/when.js.map +1 -1
  96. package/dist/lib/addRows.js +0 -2
  97. package/dist/lib/addRows.js.map +1 -1
  98. package/dist/lib/arrange.js +9 -7
  99. package/dist/lib/arrange.js.map +1 -1
  100. package/dist/lib/complete.js +0 -2
  101. package/dist/lib/complete.js.map +1 -1
  102. package/dist/lib/count.js +6 -4
  103. package/dist/lib/count.js.map +1 -1
  104. package/dist/lib/debug.js +4 -4
  105. package/dist/lib/debug.js.map +1 -1
  106. package/dist/lib/distinct.js +3 -5
  107. package/dist/lib/distinct.js.map +1 -1
  108. package/dist/lib/expand.js +18 -15
  109. package/dist/lib/expand.js.map +1 -1
  110. package/dist/lib/fill.js +10 -5
  111. package/dist/lib/fill.js.map +1 -1
  112. package/dist/lib/filter.js +0 -2
  113. package/dist/lib/filter.js.map +1 -1
  114. package/dist/lib/fullJoin.js +22 -21
  115. package/dist/lib/fullJoin.js.map +1 -1
  116. package/dist/lib/groupBy.js +56 -30
  117. package/dist/lib/groupBy.js.map +1 -1
  118. package/dist/lib/helpers/assignGroupKeys.js +4 -6
  119. package/dist/lib/helpers/assignGroupKeys.js.map +1 -1
  120. package/dist/lib/helpers/groupMap.js +2 -4
  121. package/dist/lib/helpers/groupMap.js.map +1 -1
  122. package/dist/lib/helpers/groupTraversal.js +5 -6
  123. package/dist/lib/helpers/groupTraversal.js.map +1 -1
  124. package/dist/lib/helpers/identity.js +0 -2
  125. package/dist/lib/helpers/identity.js.map +1 -1
  126. package/dist/lib/helpers/isObject.js +0 -2
  127. package/dist/lib/helpers/isObject.js.map +1 -1
  128. package/dist/lib/helpers/keysFromItems.js +1 -4
  129. package/dist/lib/helpers/keysFromItems.js.map +1 -1
  130. package/dist/lib/helpers/singleOrArray.js +0 -2
  131. package/dist/lib/helpers/singleOrArray.js.map +1 -1
  132. package/dist/lib/helpers/summation.js +10 -4
  133. package/dist/lib/helpers/summation.js.map +1 -1
  134. package/dist/lib/index.js +0 -2
  135. package/dist/lib/index.js.map +1 -1
  136. package/dist/lib/innerJoin.js +38 -14
  137. package/dist/lib/innerJoin.js.map +1 -1
  138. package/dist/lib/item/rate.js +2 -5
  139. package/dist/lib/item/rate.js.map +1 -1
  140. package/dist/lib/leftJoin.js +12 -9
  141. package/dist/lib/leftJoin.js.map +1 -1
  142. package/dist/lib/map.js +0 -2
  143. package/dist/lib/map.js.map +1 -1
  144. package/dist/lib/math/math.js +0 -2
  145. package/dist/lib/math/math.js.map +1 -1
  146. package/dist/lib/mutate.js +1 -3
  147. package/dist/lib/mutate.js.map +1 -1
  148. package/dist/lib/mutateWithSummary.js +1 -3
  149. package/dist/lib/mutateWithSummary.js.map +1 -1
  150. package/dist/lib/pivotLonger.js +31 -9
  151. package/dist/lib/pivotLonger.js.map +1 -1
  152. package/dist/lib/pivotWider.js +24 -21
  153. package/dist/lib/pivotWider.js.map +1 -1
  154. package/dist/lib/rename.js +0 -2
  155. package/dist/lib/rename.js.map +1 -1
  156. package/dist/lib/replaceNully.js +1 -3
  157. package/dist/lib/replaceNully.js.map +1 -1
  158. package/dist/lib/select.js +3 -5
  159. package/dist/lib/select.js.map +1 -1
  160. package/dist/lib/selectors/contains.js +0 -2
  161. package/dist/lib/selectors/contains.js.map +1 -1
  162. package/dist/lib/selectors/endsWith.js +0 -2
  163. package/dist/lib/selectors/endsWith.js.map +1 -1
  164. package/dist/lib/selectors/everything.js +0 -2
  165. package/dist/lib/selectors/everything.js.map +1 -1
  166. package/dist/lib/selectors/matches.js +0 -2
  167. package/dist/lib/selectors/matches.js.map +1 -1
  168. package/dist/lib/selectors/negate.js +2 -4
  169. package/dist/lib/selectors/negate.js.map +1 -1
  170. package/dist/lib/selectors/numRange.js +0 -2
  171. package/dist/lib/selectors/numRange.js.map +1 -1
  172. package/dist/lib/selectors/startsWith.js +0 -2
  173. package/dist/lib/selectors/startsWith.js.map +1 -1
  174. package/dist/lib/sequences/fullSeq.js +5 -3
  175. package/dist/lib/sequences/fullSeq.js.map +1 -1
  176. package/dist/lib/slice.js +2 -5
  177. package/dist/lib/slice.js.map +1 -1
  178. package/dist/lib/summarize.js +6 -6
  179. package/dist/lib/summarize.js.map +1 -1
  180. package/dist/lib/summary/deviation.js +0 -2
  181. package/dist/lib/summary/deviation.js.map +1 -1
  182. package/dist/lib/summary/first.js +0 -2
  183. package/dist/lib/summary/first.js.map +1 -1
  184. package/dist/lib/summary/last.js +0 -2
  185. package/dist/lib/summary/last.js.map +1 -1
  186. package/dist/lib/summary/max.js +0 -2
  187. package/dist/lib/summary/max.js.map +1 -1
  188. package/dist/lib/summary/mean.js +0 -2
  189. package/dist/lib/summary/mean.js.map +1 -1
  190. package/dist/lib/summary/meanRate.js +0 -2
  191. package/dist/lib/summary/meanRate.js.map +1 -1
  192. package/dist/lib/summary/median.js +0 -2
  193. package/dist/lib/summary/median.js.map +1 -1
  194. package/dist/lib/summary/min.js +0 -2
  195. package/dist/lib/summary/min.js.map +1 -1
  196. package/dist/lib/summary/n.js +0 -2
  197. package/dist/lib/summary/n.js.map +1 -1
  198. package/dist/lib/summary/nDistinct.js +2 -4
  199. package/dist/lib/summary/nDistinct.js.map +1 -1
  200. package/dist/lib/summary/sum.js +0 -2
  201. package/dist/lib/summary/sum.js.map +1 -1
  202. package/dist/lib/summary/variance.js +0 -2
  203. package/dist/lib/summary/variance.js.map +1 -1
  204. package/dist/lib/tally.js +4 -4
  205. package/dist/lib/tally.js.map +1 -1
  206. package/dist/lib/tidy.js +0 -2
  207. package/dist/lib/tidy.js.map +1 -1
  208. package/dist/lib/total.js +0 -2
  209. package/dist/lib/total.js.map +1 -1
  210. package/dist/lib/transmute.js +0 -2
  211. package/dist/lib/transmute.js.map +1 -1
  212. package/dist/lib/vector/cumsum.js +0 -2
  213. package/dist/lib/vector/cumsum.js.map +1 -1
  214. package/dist/lib/vector/lag.js +1 -3
  215. package/dist/lib/vector/lag.js.map +1 -1
  216. package/dist/lib/vector/lead.js +1 -3
  217. package/dist/lib/vector/lead.js.map +1 -1
  218. package/dist/lib/vector/roll.js +1 -3
  219. package/dist/lib/vector/roll.js.map +1 -1
  220. package/dist/lib/vector/rowNumber.js +0 -2
  221. package/dist/lib/vector/rowNumber.js.map +1 -1
  222. package/dist/lib/when.js +1 -4
  223. package/dist/lib/when.js.map +1 -1
  224. package/dist/tidy.d.ts +217 -1775
  225. package/dist/umd/tidy.js +307 -184
  226. package/dist/umd/tidy.js.map +1 -1
  227. package/dist/umd/tidy.min.js +1 -1
  228. package/dist/umd/tidy.min.js.map +1 -1
  229. package/genai-docs/api-core.md +357 -0
  230. package/genai-docs/api-grouping.md +400 -0
  231. package/genai-docs/api-joins.md +118 -0
  232. package/genai-docs/api-other.md +238 -0
  233. package/genai-docs/api-pivot.md +112 -0
  234. package/genai-docs/api-selectors.md +159 -0
  235. package/genai-docs/api-sequences.md +127 -0
  236. package/genai-docs/api-slice.md +137 -0
  237. package/genai-docs/api-summarize.md +528 -0
  238. package/genai-docs/api-vector.md +239 -0
  239. package/genai-docs/gotchas.md +193 -0
  240. package/genai-docs/index.md +44 -0
  241. package/genai-docs/mental-model.md +270 -0
  242. package/genai-docs/patterns.md +384 -0
  243. package/genai-docs/quick-reference.md +125 -0
  244. package/package.json +16 -10
  245. package/LICENSE +0 -21
@@ -0,0 +1,238 @@
1
+ # Other Functions
2
+
3
+ Miscellaneous tidyjs functions for completing, filling, replacing, adding rows, and math utilities.
4
+
5
+ ```js
6
+ import { tidy, complete, expand, fill, replaceNully, addRows, rate, TMath } from '@tidyjs/tidy';
7
+ ```
8
+
9
+ ---
10
+
11
+ <!-- keywords: complete, fill missing combinations, add missing rows -->
12
+ ## complete
13
+
14
+ Fill in missing combinations of data. Adds rows for any combination of specified keys that does not already exist.
15
+
16
+ **Signature:** `complete<T>(expandKeys: string | string[] | KeyMap<T>, replaceNullySpec?: Partial<T>)`
17
+ **Goes inside:** `tidy(data, complete(...))`
18
+
19
+ ### Parameters
20
+ - **expandKeys** `string | string[] | KeyMap<T>` -- defines which columns to expand. As a `KeyMap`, each key maps to an array of values or a sequence function (e.g., `fullSeq`).
21
+ - **replaceNullySpec** `Partial<T>` (optional) -- replace null/undefined in newly created rows. E.g., `{ value: 0 }`.
22
+
23
+ ### Example
24
+ ```js
25
+ const data = [
26
+ { group: 'a', year: 2020, value: 10 },
27
+ { group: 'a', year: 2021, value: 20 },
28
+ { group: 'b', year: 2020, value: 30 },
29
+ ];
30
+
31
+ tidy(data, complete({ group: ['a', 'b'], year: [2020, 2021] }, { value: 0 }));
32
+ // output:
33
+ // [
34
+ // { group: 'a', year: 2020, value: 10 },
35
+ // { group: 'a', year: 2021, value: 20 },
36
+ // { group: 'b', year: 2020, value: 30 },
37
+ // { group: 'b', year: 2021, value: 0 }, // added, value filled with 0
38
+ // ]
39
+ ```
40
+
41
+ ---
42
+
43
+ <!-- keywords: expand, all combinations, cartesian product, cross join -->
44
+ ## expand
45
+
46
+ Generate all combinations of the specified keys. Unlike `complete`, returns only the expanded combination rows (does not merge with original data).
47
+
48
+ **Signature:** `expand<T>(expandKeys: string | string[] | KeyMap<T>)`
49
+ **Goes inside:** `tidy(data, expand(...))`
50
+
51
+ ### Parameters
52
+ - **expandKeys** `string | string[] | KeyMap<T>` -- columns to expand. As a string or array, uses distinct values from the data. As a `KeyMap`, values can be explicit arrays or sequence functions.
53
+
54
+ ### Example
55
+ ```js
56
+ const data = [
57
+ { group: 'a', year: 2020 },
58
+ { group: 'b', year: 2021 },
59
+ ];
60
+
61
+ tidy(data, expand(['group', 'year']));
62
+ // output: all combinations of distinct group and year values
63
+ // [
64
+ // { group: 'a', year: 2020 },
65
+ // { group: 'a', year: 2021 },
66
+ // { group: 'b', year: 2020 },
67
+ // { group: 'b', year: 2021 },
68
+ // ]
69
+ ```
70
+
71
+ ---
72
+
73
+ <!-- keywords: fill, fill down, forward fill, last observation carried forward -->
74
+ ## fill
75
+
76
+ Fill null/undefined values forward (downward) using the last non-null value.
77
+
78
+ **Signature:** `fill<T>(keys: string | string[])`
79
+ **Goes inside:** `tidy(data, fill(...))`
80
+
81
+ ### Parameters
82
+ - **keys** `string | string[]` -- column name(s) to fill.
83
+
84
+ ### Example
85
+ ```js
86
+ const data = [
87
+ { name: 'Alice', value: 10 },
88
+ { name: undefined, value: 20 },
89
+ { name: undefined, value: 30 },
90
+ { name: 'Bob', value: 40 },
91
+ ];
92
+
93
+ tidy(data, fill('name'));
94
+ // output:
95
+ // [
96
+ // { name: 'Alice', value: 10 },
97
+ // { name: 'Alice', value: 20 }, // filled from above
98
+ // { name: 'Alice', value: 30 }, // filled from above
99
+ // { name: 'Bob', value: 40 },
100
+ // ]
101
+ ```
102
+
103
+ ---
104
+
105
+ <!-- keywords: replace nully, replace null, replace undefined, default values, coalesce -->
106
+ ## replaceNully
107
+
108
+ Replace null or undefined values with specified defaults.
109
+
110
+ **Signature:** `replaceNully<T>(replaceSpec: Partial<T>)`
111
+ **Goes inside:** `tidy(data, replaceNully(...))`
112
+
113
+ ### Parameters
114
+ - **replaceSpec** `Partial<T>` -- object mapping column names to replacement values. Only null/undefined values are replaced.
115
+
116
+ ### Example
117
+ ```js
118
+ const data = [
119
+ { name: 'Alice', score: null, grade: undefined },
120
+ { name: 'Bob', score: 85, grade: 'B' },
121
+ ];
122
+
123
+ tidy(data, replaceNully({ score: 0, grade: 'N/A' }));
124
+ // output:
125
+ // [
126
+ // { name: 'Alice', score: 0, grade: 'N/A' },
127
+ // { name: 'Bob', score: 85, grade: 'B' },
128
+ // ]
129
+ ```
130
+
131
+ ---
132
+
133
+ <!-- keywords: add rows, add items, append, insert rows -->
134
+ ## addRows
135
+
136
+ Append rows to the data. Alias: `addItems`.
137
+
138
+ **Signature:** `addRows<T>(itemsToAdd: T | T[] | ((items: T[]) => T | T[]))`
139
+ **Goes inside:** `tidy(data, addRows(...))`
140
+
141
+ ### Parameters
142
+ - **itemsToAdd** `T | T[] | ((items: T[]) => T | T[])` -- rows to append. Can be a single item, an array, or a function that receives the current items and returns new rows.
143
+
144
+ ### Example
145
+ ```js
146
+ const data = [{ name: 'Alice', value: 10 }];
147
+
148
+ tidy(data, addRows([{ name: 'Bob', value: 20 }]));
149
+ // output: [{ name: 'Alice', value: 10 }, { name: 'Bob', value: 20 }]
150
+
151
+ // dynamic: add a total row
152
+ tidy(data, addRows((items) => ({
153
+ name: 'Total',
154
+ value: items.reduce((s, d) => s + d.value, 0),
155
+ })));
156
+ ```
157
+
158
+ ---
159
+
160
+ <!-- keywords: rate, ratio, divide, item accessor, mutate rate -->
161
+ ## rate (item accessor)
162
+
163
+ Create a per-item rate accessor for use inside `mutate()`. Computes `numerator / denominator` for each row.
164
+
165
+ **Signature:** `rate<T>(numerator: keyof T | Accessor, denominator: keyof T | Accessor, options?: { predicate?, allowDivideByZero? })`
166
+ **Goes inside:** `mutate({ col: rate('num', 'denom') })`
167
+
168
+ ### Parameters
169
+ - **numerator** `keyof T | ((d, i, arr) => number)` -- column name or accessor for the numerator.
170
+ - **denominator** `keyof T | ((d, i, arr) => number)` -- column name or accessor for the denominator.
171
+ - **options.predicate** `(d, i, arr) => boolean` -- if provided, returns `undefined` when predicate is false.
172
+ - **options.allowDivideByZero** `boolean` -- if `true`, allows division by zero (returns `Infinity`). Default: `false` (returns `undefined` when denominator is 0, except 0/0 which returns 0).
173
+
174
+ ### Example
175
+ ```js
176
+ const data = [
177
+ { hits: 30, attempts: 100 },
178
+ { hits: 0, attempts: 0 },
179
+ { hits: 5, attempts: 0 },
180
+ ];
181
+
182
+ tidy(data, mutate({ pct: rate('hits', 'attempts') }));
183
+ // output:
184
+ // [
185
+ // { hits: 30, attempts: 100, pct: 0.3 },
186
+ // { hits: 0, attempts: 0, pct: 0 }, // 0/0 = 0
187
+ // { hits: 5, attempts: 0, pct: undefined }, // div by zero = undefined
188
+ // ]
189
+ ```
190
+
191
+ **Do not confuse with `TMath.rate`** (see below), which is a plain math function, not an item accessor.
192
+
193
+ ---
194
+
195
+ <!-- keywords: TMath, math rate, math add, math subtract, null safe math -->
196
+ ## TMath
197
+
198
+ Plain math utility functions with null/undefined safety. These are standalone functions, not tidy pipeline operators.
199
+
200
+ ```js
201
+ import { TMath } from '@tidyjs/tidy';
202
+ ```
203
+
204
+ ### TMath.rate(numerator, denominator, allowDivideByZero?)
205
+
206
+ Compute `numerator / denominator` with null safety.
207
+
208
+ - Returns `undefined` if either argument is null/undefined.
209
+ - Returns `0` if both numerator and denominator are 0.
210
+ - Returns `undefined` if denominator is 0 (unless `allowDivideByZero` is `true`).
211
+
212
+ ```js
213
+ TMath.rate(30, 100); // 0.3
214
+ TMath.rate(0, 0); // 0
215
+ TMath.rate(5, 0); // undefined
216
+ TMath.rate(null, 100); // undefined
217
+ TMath.rate(5, 0, true); // Infinity
218
+ ```
219
+
220
+ ### TMath.add(a, b, nullyZero?)
221
+
222
+ Null-safe addition. Returns `undefined` if either value is null/undefined, unless `nullyZero` is `true` (treats null/undefined as 0).
223
+
224
+ ```js
225
+ TMath.add(1, 2); // 3
226
+ TMath.add(1, null); // undefined
227
+ TMath.add(1, null, true); // 1
228
+ ```
229
+
230
+ ### TMath.subtract(a, b, nullyZero?)
231
+
232
+ Null-safe subtraction. Returns `undefined` if either value is null/undefined, unless `nullyZero` is `true`.
233
+
234
+ ```js
235
+ TMath.subtract(5, 3); // 2
236
+ TMath.subtract(5, null); // undefined
237
+ TMath.subtract(5, null, true); // 5
238
+ ```
@@ -0,0 +1,112 @@
1
+ # Pivot (Reshape)
2
+
3
+ Reshape data between long and wide formats.
4
+
5
+ ```js
6
+ import { tidy, pivotWider, pivotLonger } from '@tidyjs/tidy';
7
+ ```
8
+
9
+ ---
10
+
11
+ <!-- keywords: pivot wider, spread, long to wide, reshape, widen -->
12
+ ## pivotWider
13
+
14
+ Reshape from long format to wide format by spreading values into new columns.
15
+
16
+ **Signature:** `pivotWider<T>(options: { namesFrom, valuesFrom, valuesFill?, valuesFillMap?, namesSep? })`
17
+ **Goes inside:** `tidy(data, pivotWider(...))`
18
+
19
+ ### Parameters
20
+ - **namesFrom** `keyof T | (keyof T)[]` -- column(s) whose values become new column names.
21
+ - **valuesFrom** `keyof T | (keyof T)[]` -- column(s) whose values fill the new columns.
22
+ - **valuesFill** `any` -- value to use when a combination has no data. Default: `undefined`.
23
+ - **valuesFillMap** `Record<string, any>` -- per-valuesFrom fill values (e.g., `{ count: 0, total: 0 }`).
24
+ - **namesSep** `string` -- separator when combining multiple namesFrom or valuesFrom keys. Default: `'_'`.
25
+
26
+ ### Example
27
+ ```js
28
+ const data = [
29
+ { name: 'Alice', subject: 'math', score: 90 },
30
+ { name: 'Alice', subject: 'reading', score: 85 },
31
+ { name: 'Bob', subject: 'math', score: 70 },
32
+ { name: 'Bob', subject: 'reading', score: 95 },
33
+ ];
34
+
35
+ tidy(data, pivotWider({
36
+ namesFrom: 'subject',
37
+ valuesFrom: 'score',
38
+ valuesFill: 0,
39
+ }));
40
+ // output:
41
+ // [
42
+ // { name: 'Alice', math: 90, reading: 85 },
43
+ // { name: 'Bob', math: 70, reading: 95 },
44
+ // ]
45
+ ```
46
+
47
+ ### Multiple valuesFrom
48
+ ```js
49
+ tidy(data, pivotWider({
50
+ namesFrom: 'subject',
51
+ valuesFrom: ['score', 'grade'],
52
+ namesSep: '_',
53
+ }));
54
+ // columns become: name, score_math, score_reading, grade_math, grade_reading
55
+ ```
56
+
57
+ ---
58
+
59
+ <!-- keywords: pivot longer, melt, gather, wide to long, unpivot, reshape -->
60
+ ## pivotLonger
61
+
62
+ Reshape from wide format to long format by collapsing columns into rows.
63
+
64
+ **Signature:** `pivotLonger<T>(options: { cols?, namesTo, valuesTo, namesSep? })`
65
+ **Goes inside:** `tidy(data, pivotLonger(...))`
66
+
67
+ ### Parameters
68
+ - **cols** `(keyof T)[] | SelectorFn` -- columns to pivot into longer format. Accepts an array of column names or selector functions like `startsWith()`, `contains()`, etc.
69
+ - **namesTo** `string | string[]` -- name for the new column(s) that will hold the former column names.
70
+ - **valuesTo** `string | string[]` -- name for the new column(s) that will hold the values.
71
+ - **namesSep** `string` -- separator to split column names when `namesTo` is an array. Default: `'_'`.
72
+
73
+ ### Example
74
+ ```js
75
+ const data = [
76
+ { name: 'Alice', math: 90, reading: 85 },
77
+ { name: 'Bob', math: 70, reading: 95 },
78
+ ];
79
+
80
+ tidy(data, pivotLonger({
81
+ cols: ['math', 'reading'],
82
+ namesTo: 'subject',
83
+ valuesTo: 'score',
84
+ }));
85
+ // output:
86
+ // [
87
+ // { name: 'Alice', subject: 'math', score: 90 },
88
+ // { name: 'Alice', subject: 'reading', score: 85 },
89
+ // { name: 'Bob', subject: 'math', score: 70 },
90
+ // { name: 'Bob', subject: 'reading', score: 95 },
91
+ // ]
92
+ ```
93
+
94
+ ### Using selectors for cols
95
+ ```js
96
+ import { startsWith } from '@tidyjs/tidy';
97
+
98
+ const data = [
99
+ { id: 1, rev_q1: 100, rev_q2: 200, cost_q1: 50 },
100
+ ];
101
+
102
+ tidy(data, pivotLonger({
103
+ cols: [startsWith('rev_')],
104
+ namesTo: 'quarter',
105
+ valuesTo: 'revenue',
106
+ }));
107
+ // output:
108
+ // [
109
+ // { id: 1, cost_q1: 50, quarter: 'rev_q1', revenue: 100 },
110
+ // { id: 1, cost_q1: 50, quarter: 'rev_q2', revenue: 200 },
111
+ // ]
112
+ ```
@@ -0,0 +1,159 @@
1
+ # Selectors
2
+
3
+ Functions that dynamically select column names based on patterns. Selectors return `(items: T[]) => string[]`.
4
+
5
+ Use selectors inside `select()`, `summarizeAt()`, `totalAt()`, and `pivotLonger({ cols: ... })`.
6
+
7
+ ```js
8
+ import { tidy, select,
9
+ everything, startsWith, endsWith, contains, matches, numRange, negate
10
+ } from '@tidyjs/tidy';
11
+ ```
12
+
13
+ ---
14
+
15
+ <!-- keywords: everything, all columns, select all -->
16
+ ## everything
17
+
18
+ Select all columns.
19
+
20
+ **Signature:** `everything<T>()`
21
+ **Returns:** `(items: T[]) => string[]`
22
+
23
+ ### Example
24
+ ```js
25
+ tidy(data, select([everything(), '-secret']));
26
+ // selects all columns except 'secret'
27
+ ```
28
+
29
+ ---
30
+
31
+ <!-- keywords: starts with, prefix, column prefix -->
32
+ ## startsWith
33
+
34
+ Select columns whose names start with a prefix.
35
+
36
+ **Signature:** `startsWith<T>(prefix: string, ignoreCase?: boolean)`
37
+ **Returns:** `(items: T[]) => string[]`
38
+
39
+ ### Parameters
40
+ - **prefix** `string` -- the prefix to match.
41
+ - **ignoreCase** `boolean` -- case-insensitive matching. Default: `true`.
42
+
43
+ ### Example
44
+ ```js
45
+ // data has columns: rev_q1, rev_q2, cost_q1
46
+ tidy(data, select([startsWith('rev_')]));
47
+ // keeps: rev_q1, rev_q2
48
+ ```
49
+
50
+ ---
51
+
52
+ <!-- keywords: ends with, suffix, column suffix -->
53
+ ## endsWith
54
+
55
+ Select columns whose names end with a suffix.
56
+
57
+ **Signature:** `endsWith<T>(suffix: string, ignoreCase?: boolean)`
58
+ **Returns:** `(items: T[]) => string[]`
59
+
60
+ ### Parameters
61
+ - **suffix** `string` -- the suffix to match.
62
+ - **ignoreCase** `boolean` -- case-insensitive matching. Default: `true`.
63
+
64
+ ### Example
65
+ ```js
66
+ // data has columns: name_en, name_fr, age
67
+ tidy(data, select([endsWith('_en')]));
68
+ // keeps: name_en
69
+ ```
70
+
71
+ ---
72
+
73
+ <!-- keywords: contains, substring, column search -->
74
+ ## contains
75
+
76
+ Select columns whose names contain a substring.
77
+
78
+ **Signature:** `contains<T>(substring: string, ignoreCase?: boolean)`
79
+ **Returns:** `(items: T[]) => string[]`
80
+
81
+ ### Parameters
82
+ - **substring** `string` -- the substring to search for.
83
+ - **ignoreCase** `boolean` -- case-insensitive matching. Default: `true`.
84
+
85
+ ### Example
86
+ ```js
87
+ // data has columns: total_revenue, net_revenue, cost
88
+ tidy(data, select([contains('revenue')]));
89
+ // keeps: total_revenue, net_revenue
90
+ ```
91
+
92
+ ---
93
+
94
+ <!-- keywords: matches, regex, pattern, column regex -->
95
+ ## matches
96
+
97
+ Select columns whose names match a regular expression.
98
+
99
+ **Signature:** `matches<T>(regex: RegExp)`
100
+ **Returns:** `(items: T[]) => string[]`
101
+
102
+ ### Parameters
103
+ - **regex** `RegExp` -- the regular expression to test against.
104
+
105
+ ### Example
106
+ ```js
107
+ // data has columns: q1_sales, q2_sales, q1_cost, notes
108
+ tidy(data, select([matches(/^q\d+_sales$/)]));
109
+ // keeps: q1_sales, q2_sales
110
+ ```
111
+
112
+ ---
113
+
114
+ <!-- keywords: num range, numbered columns, prefix with numbers -->
115
+ ## numRange
116
+
117
+ Select columns matching a prefix followed by numbers in a range.
118
+
119
+ **Signature:** `numRange<T>(prefix: string, range: [number, number], width?: number)`
120
+ **Returns:** `(items: T[]) => string[]`
121
+
122
+ ### Parameters
123
+ - **prefix** `string` -- the column name prefix.
124
+ - **range** `[number, number]` -- inclusive `[start, end]` range of numbers.
125
+ - **width** `number` (optional) -- zero-pad numbers to this width. E.g., `width=3` turns `1` into `001`.
126
+
127
+ ### Example
128
+ ```js
129
+ // data has columns: wk1, wk2, wk3, ..., wk52, name
130
+ tidy(data, select([numRange('wk', [1, 4])]));
131
+ // keeps: wk1, wk2, wk3, wk4
132
+
133
+ // with zero-padded columns: wk001, wk002, ...
134
+ tidy(data, select([numRange('wk', [1, 4], 3)]));
135
+ // keeps: wk001, wk002, wk003, wk004
136
+ ```
137
+
138
+ ---
139
+
140
+ <!-- keywords: negate, invert, exclude, drop columns -->
141
+ ## negate
142
+
143
+ Invert a selector to exclude the matched columns. Prefixes matched keys with `-`.
144
+
145
+ **Signature:** `negate<T>(selectors: Selector | Selector[])`
146
+ **Returns:** `(items: T[]) => string[]`
147
+
148
+ ### Parameters
149
+ - **selectors** -- one or more selectors (or key names) to invert.
150
+
151
+ ### Example
152
+ ```js
153
+ // data has columns: id, rev_q1, rev_q2, cost_q1
154
+ tidy(data, select([negate(startsWith('rev_'))]));
155
+ // drops rev_q1, rev_q2 -- keeps id, cost_q1
156
+
157
+ // equivalent to:
158
+ tidy(data, select(['-rev_q1', '-rev_q2']));
159
+ ```
@@ -0,0 +1,127 @@
1
+ # Sequences
2
+
3
+ Generate full sequences of values. Typically used inside `complete()` or `expand()` to define the full range of a variable.
4
+
5
+ ```js
6
+ import { tidy, complete, expand,
7
+ fullSeq, fullSeqDate, fullSeqDateISOString,
8
+ vectorSeq, vectorSeqDate
9
+ } from '@tidyjs/tidy';
10
+ ```
11
+
12
+ ---
13
+
14
+ <!-- keywords: full sequence, numeric sequence, fill range, step -->
15
+ ## fullSeq
16
+
17
+ Generate a full numeric sequence from min to max of a column's values.
18
+
19
+ **Signature:** `fullSeq<T>(key: keyof T | ((d: T) => number), period?: number)`
20
+ **Returns:** `(items: T[]) => number[]`
21
+
22
+ ### Parameters
23
+ - **key** `keyof T | ((d: T) => number)` -- column name or accessor to read numeric values from.
24
+ - **period** `number` -- step size between values. Default: `1`.
25
+
26
+ ### Example
27
+ ```js
28
+ const data = [
29
+ { year: 2020, value: 10 },
30
+ { year: 2023, value: 30 },
31
+ ];
32
+
33
+ tidy(data, complete({ year: fullSeq('year') }));
34
+ // fills in missing years: 2020, 2021, 2022, 2023
35
+ // rows for 2021 and 2022 are added with value: undefined
36
+ ```
37
+
38
+ ---
39
+
40
+ <!-- keywords: full date sequence, date range, granularity, day week month -->
41
+ ## fullSeqDate
42
+
43
+ Generate a full date sequence from min to max of a column's Date values.
44
+
45
+ **Signature:** `fullSeqDate<T>(key: keyof T | ((d: T) => Date), granularity?: Granularity, period?: number)`
46
+ **Returns:** `(items: T[]) => Date[]`
47
+
48
+ ### Parameters
49
+ - **key** `keyof T | ((d: T) => Date)` -- column name or accessor to read Date values from.
50
+ - **granularity** `Granularity` -- step unit. One of: `'second'` / `'s'`, `'minute'` / `'min'`, `'day'` / `'d'`, `'week'` / `'w'`, `'month'` / `'m'`, `'year'` / `'y'` (and plural forms). Default: `'day'`.
51
+ - **period** `number` -- number of granularity units per step. Default: `1`.
52
+
53
+ ### Example
54
+ ```js
55
+ const data = [
56
+ { date: new Date('2023-01-01'), value: 1 },
57
+ { date: new Date('2023-01-04'), value: 4 },
58
+ ];
59
+
60
+ tidy(data, complete({ date: fullSeqDate('date', 'day') }));
61
+ // fills in Jan 1, 2, 3, 4 -- adds rows for Jan 2 and Jan 3
62
+ ```
63
+
64
+ ---
65
+
66
+ <!-- keywords: full date sequence ISO, date string, ISO 8601 -->
67
+ ## fullSeqDateISOString
68
+
69
+ Same as `fullSeqDate` but returns ISO 8601 strings instead of Date objects.
70
+
71
+ **Signature:** `fullSeqDateISOString<T>(key: keyof T | ((d: T) => string), granularity?: Granularity, period?: number)`
72
+ **Returns:** `(items: T[]) => string[]`
73
+
74
+ ### Parameters
75
+ Same as `fullSeqDate`. The key accessor should return a string parseable by `new Date(...)`.
76
+
77
+ ### Example
78
+ ```js
79
+ const data = [
80
+ { date: '2023-01-01', value: 1 },
81
+ { date: '2023-01-03', value: 3 },
82
+ ];
83
+
84
+ tidy(data, complete({ date: fullSeqDateISOString('date', 'day') }));
85
+ // fills dates as ISO strings: '2023-01-01T00:00:00.000Z', '2023-01-02T00:00:00.000Z', ...
86
+ ```
87
+
88
+ ---
89
+
90
+ <!-- keywords: vector sequence, explicit values, numeric -->
91
+ ## vectorSeq
92
+
93
+ Generate a numeric sequence from an explicit array of values (min to max with a step).
94
+
95
+ **Signature:** `vectorSeq(values: number[], period?: number): number[]`
96
+ **Returns:** `number[]` (not a factory function -- returns the sequence directly)
97
+
98
+ ### Parameters
99
+ - **values** `number[]` -- array of numbers. The sequence spans from `min(values)` to `max(values)`.
100
+ - **period** `number` -- step size. Default: `1`.
101
+
102
+ ### Example
103
+ ```js
104
+ vectorSeq([2, 8], 2);
105
+ // output: [2, 4, 6, 8]
106
+ ```
107
+
108
+ ---
109
+
110
+ <!-- keywords: vector date sequence, explicit date values -->
111
+ ## vectorSeqDate
112
+
113
+ Generate a date sequence from an explicit array of Date values (min to max).
114
+
115
+ **Signature:** `vectorSeqDate(values: Date[], granularity?: Granularity, period?: number): Date[]`
116
+ **Returns:** `Date[]` (not a factory function -- returns the sequence directly)
117
+
118
+ ### Parameters
119
+ - **values** `Date[]` -- array of Dates. The sequence spans from earliest to latest.
120
+ - **granularity** `Granularity` -- step unit. Default: `'day'`.
121
+ - **period** `number` -- number of granularity units per step. Default: `1`.
122
+
123
+ ### Example
124
+ ```js
125
+ vectorSeqDate([new Date('2023-01-01'), new Date('2023-01-03')], 'day');
126
+ // output: [Date(Jan 1), Date(Jan 2), Date(Jan 3)]
127
+ ```