dataframe-toolkit 0.11.1__tar.gz → 0.11.3__tar.gz
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.
- {dataframe_toolkit-0.11.1 → dataframe_toolkit-0.11.3}/PKG-INFO +126 -19
- {dataframe_toolkit-0.11.1 → dataframe_toolkit-0.11.3}/README.md +124 -18
- {dataframe_toolkit-0.11.1 → dataframe_toolkit-0.11.3}/pyproject.toml +2 -1
- {dataframe_toolkit-0.11.1 → dataframe_toolkit-0.11.3}/pyproject.toml.orig +2 -1
- dataframe_toolkit-0.11.3/src/dftk/commands/eval_cmd.py +409 -0
- {dataframe_toolkit-0.11.1 → dataframe_toolkit-0.11.3}/src/dftk/commands/query_cmd.py +22 -0
- dataframe_toolkit-0.11.3/src/dftk/common/evalfuncs.py +439 -0
- dataframe_toolkit-0.11.1/src/dftk/commands/eval_cmd.py +0 -831
- {dataframe_toolkit-0.11.1 → dataframe_toolkit-0.11.3}/src/dftk/__init__.py +0 -0
- {dataframe_toolkit-0.11.1 → dataframe_toolkit-0.11.3}/src/dftk/cli.py +0 -0
- {dataframe_toolkit-0.11.1 → dataframe_toolkit-0.11.3}/src/dftk/commands/__init__.py +0 -0
- {dataframe_toolkit-0.11.1 → dataframe_toolkit-0.11.3}/src/dftk/commands/annotate_cmd.py +0 -0
- {dataframe_toolkit-0.11.1 → dataframe_toolkit-0.11.3}/src/dftk/commands/base.py +0 -0
- {dataframe_toolkit-0.11.1 → dataframe_toolkit-0.11.3}/src/dftk/commands/binx_cmd.py +0 -0
- {dataframe_toolkit-0.11.1 → dataframe_toolkit-0.11.3}/src/dftk/commands/chi_cmd.py +0 -0
- {dataframe_toolkit-0.11.1 → dataframe_toolkit-0.11.3}/src/dftk/commands/clean_cmd.py +0 -0
- {dataframe_toolkit-0.11.1 → dataframe_toolkit-0.11.3}/src/dftk/commands/cleannames_cmd.py +0 -0
- {dataframe_toolkit-0.11.1 → dataframe_toolkit-0.11.3}/src/dftk/commands/concat_cmd.py +0 -0
- {dataframe_toolkit-0.11.1 → dataframe_toolkit-0.11.3}/src/dftk/commands/corr_cmd.py +0 -0
- {dataframe_toolkit-0.11.1 → dataframe_toolkit-0.11.3}/src/dftk/commands/dataset_cmd.py +0 -0
- {dataframe_toolkit-0.11.1 → dataframe_toolkit-0.11.3}/src/dftk/commands/describe_cmd.py +0 -0
- {dataframe_toolkit-0.11.1 → dataframe_toolkit-0.11.3}/src/dftk/commands/explode_cmd.py +0 -0
- {dataframe_toolkit-0.11.1 → dataframe_toolkit-0.11.3}/src/dftk/commands/fit_cmd.py +0 -0
- {dataframe_toolkit-0.11.1 → dataframe_toolkit-0.11.3}/src/dftk/commands/func_cmd.py +0 -0
- {dataframe_toolkit-0.11.1 → dataframe_toolkit-0.11.3}/src/dftk/commands/help.py +0 -0
- {dataframe_toolkit-0.11.1 → dataframe_toolkit-0.11.3}/src/dftk/commands/hist_cmd.py +0 -0
- {dataframe_toolkit-0.11.1 → dataframe_toolkit-0.11.3}/src/dftk/commands/implode_cmd.py +0 -0
- {dataframe_toolkit-0.11.1 → dataframe_toolkit-0.11.3}/src/dftk/commands/info_cmd.py +0 -0
- {dataframe_toolkit-0.11.1 → dataframe_toolkit-0.11.3}/src/dftk/commands/interp_cmd.py +0 -0
- {dataframe_toolkit-0.11.1 → dataframe_toolkit-0.11.3}/src/dftk/commands/line_cmd.py +0 -0
- {dataframe_toolkit-0.11.1 → dataframe_toolkit-0.11.3}/src/dftk/commands/melt_cmd.py +0 -0
- {dataframe_toolkit-0.11.1 → dataframe_toolkit-0.11.3}/src/dftk/commands/merge_cmd.py +0 -0
- {dataframe_toolkit-0.11.1 → dataframe_toolkit-0.11.3}/src/dftk/commands/pivot_cmd.py +0 -0
- {dataframe_toolkit-0.11.1 → dataframe_toolkit-0.11.3}/src/dftk/commands/print_cmd.py +0 -0
- {dataframe_toolkit-0.11.1 → dataframe_toolkit-0.11.3}/src/dftk/commands/randvar_cmd.py +0 -0
- {dataframe_toolkit-0.11.1 → dataframe_toolkit-0.11.3}/src/dftk/commands/sample_cmd.py +0 -0
- {dataframe_toolkit-0.11.1 → dataframe_toolkit-0.11.3}/src/dftk/commands/scale_cmd.py +0 -0
- {dataframe_toolkit-0.11.1 → dataframe_toolkit-0.11.3}/src/dftk/commands/scat_cmd.py +0 -0
- {dataframe_toolkit-0.11.1 → dataframe_toolkit-0.11.3}/src/dftk/commands/segid_cmd.py +0 -0
- {dataframe_toolkit-0.11.1 → dataframe_toolkit-0.11.3}/src/dftk/commands/split_cmd.py +0 -0
- {dataframe_toolkit-0.11.1 → dataframe_toolkit-0.11.3}/src/dftk/commands/stat_cmd.py +0 -0
- {dataframe_toolkit-0.11.1 → dataframe_toolkit-0.11.3}/src/dftk/commands/test_cmd.py +0 -0
- {dataframe_toolkit-0.11.1 → dataframe_toolkit-0.11.3}/src/dftk/commands/transpose_cmd.py +0 -0
- {dataframe_toolkit-0.11.1 → dataframe_toolkit-0.11.3}/src/dftk/commands/wstat_cmd.py +0 -0
- {dataframe_toolkit-0.11.1 → dataframe_toolkit-0.11.3}/src/dftk/common/__init__.py +0 -0
- {dataframe_toolkit-0.11.1 → dataframe_toolkit-0.11.3}/src/dftk/common/copula.py +0 -0
- {dataframe_toolkit-0.11.1 → dataframe_toolkit-0.11.3}/src/dftk/common/io.py +0 -0
- {dataframe_toolkit-0.11.1 → dataframe_toolkit-0.11.3}/src/dftk/common/plot.py +0 -0
- {dataframe_toolkit-0.11.1 → dataframe_toolkit-0.11.3}/src/dftk/common/seed.py +0 -0
- {dataframe_toolkit-0.11.1 → dataframe_toolkit-0.11.3}/src/dftk/common/seq.py +0 -0
- {dataframe_toolkit-0.11.1 → dataframe_toolkit-0.11.3}/src/dftk/common/stats.py +0 -0
- {dataframe_toolkit-0.11.1 → dataframe_toolkit-0.11.3}/src/dftk/io.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: dataframe-toolkit
|
|
3
|
-
Version: 0.11.
|
|
3
|
+
Version: 0.11.3
|
|
4
4
|
Summary: A command-line toolkit for DataFrame analysis and manipulation
|
|
5
5
|
Keywords: dataframe,statistics,data analysis,CLI,TSV,pandas
|
|
6
6
|
Author: Gunnar Pálsson
|
|
@@ -20,6 +20,7 @@ Requires-Dist: statsmodels>=0.14
|
|
|
20
20
|
Requires-Dist: patsy>=0.5.6
|
|
21
21
|
Requires-Dist: duckdb>=0.8
|
|
22
22
|
Requires-Dist: matplotlib>=3.7
|
|
23
|
+
Requires-Dist: pillow>=13.0
|
|
23
24
|
Requires-Dist: seaborn>=0.12
|
|
24
25
|
Requires-Dist: tqdm>=4.65
|
|
25
26
|
Requires-Python: >=3.12
|
|
@@ -226,35 +227,141 @@ printf "sample\tfluor\ns1\t60\ns2\t110\n" \
|
|
|
226
227
|
|
|
227
228
|
### Filling missing values
|
|
228
229
|
|
|
229
|
-
`eval -f` takes pandas column methods (`COL.method(...)`)
|
|
230
|
-
`ffill`, `bfill` and `interpolate` fill empty cells
|
|
231
|
-
|
|
230
|
+
`eval -f` takes pandas column methods (`COL.method(...)`); `fillna`,
|
|
231
|
+
`ffill`, `bfill` and `interpolate` fill empty cells and keep the others.
|
|
232
|
+
|
|
233
|
+
| Formula | Fills with |
|
|
234
|
+
|---|---|
|
|
235
|
+
| `x = x.fillna(y)` | the value in column `y` |
|
|
236
|
+
| `x = x.fillna(0)`, `sex = sex.fillna('unknown')` | a fixed value |
|
|
237
|
+
| `x = x.fillna(y).fillna(0)` | `y` first, then 0 |
|
|
238
|
+
| `x = x.fillna(x.groupby(g).transform('mean'))` | the mean of the row's group (or `'median'`, ...) |
|
|
239
|
+
| `x = x.ffill()` / `x = x.bfill()` | the value above / below (`ffill(limit=1)`: at most one row) |
|
|
240
|
+
| `x = x.groupby(g).ffill()` | the value above, within each group of `g` |
|
|
241
|
+
| `x = x.interpolate()` | a straight line between the values above and below, by row position |
|
|
242
|
+
|
|
243
|
+
Write to a new column (`x_filled = x.fillna(y)`) to keep the original, and
|
|
244
|
+
mark the gaps first (`missing = x.isna()`) to tell filled values apart.
|
|
245
|
+
Only empty cells are filled: a missing row (a year with no row at all) is
|
|
246
|
+
not added.
|
|
247
|
+
|
|
248
|
+
**Defaults from another table.** A column that is in both files gets the
|
|
249
|
+
suffix `_r` from `merge`; fill from it, then drop it. Here the defaults are
|
|
250
|
+
each species' median body mass:
|
|
232
251
|
|
|
233
252
|
```bash
|
|
234
|
-
dftk
|
|
235
|
-
|
|
253
|
+
dftk dataset penguins -o | dftk pivot ... -i species -v body_mass_g \
|
|
254
|
+
-f median --move median_body_mass_g:body_mass_g -o defaults.parquet
|
|
255
|
+
dftk dataset penguins -o \
|
|
256
|
+
| dftk merge ... -r defaults.parquet -k species -t left -o \
|
|
257
|
+
| dftk eval ... -f "body_mass_g = body_mass_g.fillna(body_mass_g_r)" \
|
|
258
|
+
--drop body_mass_g_r
|
|
236
259
|
```
|
|
237
260
|
|
|
238
|
-
|
|
239
|
-
each group:
|
|
261
|
+
**From neighbouring rows** (`co2` is a weekly series with gaps):
|
|
240
262
|
|
|
241
263
|
```bash
|
|
242
|
-
dftk dataset
|
|
243
|
-
-f "
|
|
244
|
-
|
|
245
|
-
|
|
264
|
+
dftk dataset co2 -o | dftk eval ... -f "ffill = co2.ffill()" \
|
|
265
|
+
-f "bfill = co2.bfill()" -f "linear = co2.interpolate()"
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
`ffill` leaves the first rows empty and `bfill` the last ones;
|
|
269
|
+
`x.ffill().fillna(x.bfill())` fills both. `interpolate()` counts one step
|
|
270
|
+
per row, so the rows must be evenly spaced; for an x-based lookup from a
|
|
271
|
+
reference curve, see `dftk interp`.
|
|
246
272
|
|
|
273
|
+
**Row order and groups.** These methods use the rows in the order they are
|
|
274
|
+
in. Sort first, in a step of its own: `--sortasc` applies to a command's
|
|
275
|
+
output, so in the same command it would come after the fill. When a table
|
|
276
|
+
holds several series (sites, countries, samples), fill within each group,
|
|
277
|
+
or values are taken from the neighbouring group. Rows of a group don't need
|
|
278
|
+
to be next to each other, but within each group they must be in order:
|
|
279
|
+
|
|
280
|
+
```bash
|
|
247
281
|
dftk dataset healthexp -o \
|
|
248
|
-
| dftk eval ... -f "le = Life_Expectancy.where(Year % 10 != 5)"
|
|
282
|
+
| dftk eval ... -f "le = Life_Expectancy.where(Year % 10 != 5)" \
|
|
283
|
+
--sortasc Country Year -o \
|
|
249
284
|
| dftk eval ... -f "le_filled = le.groupby(Country).ffill()"
|
|
250
285
|
```
|
|
251
286
|
|
|
252
|
-
`
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
287
|
+
`interpolate()` has no grouped form. Once each group's rows are together,
|
|
288
|
+
gaps inside a group are right, but a gap at a group's start or end is
|
|
289
|
+
filled from the neighbouring group. To leave those empty, keep only values
|
|
290
|
+
with something before and after them in the same group:
|
|
291
|
+
|
|
292
|
+
```bash
|
|
293
|
+
dftk dataset healthexp -o \
|
|
294
|
+
| dftk eval ... -f "le = Life_Expectancy.where(Year % 10 != 5)" \
|
|
295
|
+
--sortasc Country Year -o \
|
|
296
|
+
| dftk eval ... -f "before = le.groupby(Country).ffill().notna()" \
|
|
297
|
+
-f "after = le.groupby(Country).bfill().notna()" \
|
|
298
|
+
-f "le_linear = le.interpolate().where(before & after)" \
|
|
299
|
+
--drop before after
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
### Differences between rows
|
|
303
|
+
|
|
304
|
+
For the change in a column from one row to the next, `eval -f` takes
|
|
305
|
+
pandas `diff()` and `pct_change()`, also within groups. They use the rows
|
|
306
|
+
in their order, so sort first, in a step of its own:
|
|
307
|
+
|
|
308
|
+
```bash
|
|
309
|
+
dftk dataset healthexp -o | dftk eval ... --sortasc Country Year -o \
|
|
310
|
+
| dftk eval ... -f "change = Spending_USD.groupby(Country).diff().round(1)" \
|
|
311
|
+
-f "pct = (Spending_USD.groupby(Country).pct_change() * 100).round(1)" \
|
|
312
|
+
-f "years = Year.groupby(Country).diff()"
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
```text
|
|
316
|
+
Year Country Spending_USD Life_Expectancy change pct years
|
|
317
|
+
1971 Canada 313.391 72.8
|
|
318
|
+
1976 Canada 543.337 73.8 229.9 73.4 5.0
|
|
319
|
+
1979 Canada 692.269 75.1 148.9 27.4 3.0
|
|
320
|
+
1980 Canada 791.812 75.2 99.5 14.4 1.0
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
The first row of each country gets an empty cell. Without
|
|
324
|
+
`groupby(Country)`, it would be compared with the last row of the
|
|
325
|
+
previous country.
|
|
326
|
+
|
|
327
|
+
To compare a value with one in another column of the previous or next row, for example the
|
|
328
|
+
gap between segments given by `Chr`, `Begin`, `End`, use SQL's `LAG()` /
|
|
329
|
+
`LEAD()` in `query --sql`:
|
|
330
|
+
|
|
331
|
+
```bash
|
|
332
|
+
dftk query segments.tsv --sql \
|
|
333
|
+
'SELECT *, "Begin" - LAG("End") OVER (PARTITION BY Chr ORDER BY "Begin")
|
|
334
|
+
AS gap
|
|
335
|
+
FROM data ORDER BY Chr, "Begin"'
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
```text
|
|
339
|
+
Chr Begin End Id gap
|
|
340
|
+
chr1 100 200 a
|
|
341
|
+
chr1 250 400 b 50
|
|
342
|
+
chr1 390 500 c -10
|
|
343
|
+
chr2 50 80 d
|
|
344
|
+
chr2 100 300 e 20
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
A negative gap is an overlap, and the first segment on each chromosome
|
|
348
|
+
gets an empty cell. `lead("Begin") OVER (...) - "End"` gives the gap to
|
|
349
|
+
the next segment instead.
|
|
350
|
+
|
|
351
|
+
- `Begin` and `End` are SQL keywords: quote such column names with double
|
|
352
|
+
quotes and the whole statement with single quotes.
|
|
353
|
+
- No sorting is needed first; `ORDER BY` inside `OVER` sets the order.
|
|
354
|
+
- Integers stay integers.
|
|
355
|
+
|
|
356
|
+
`eval -f` can do the same with pandas `shift`, but it goes by row order, so
|
|
357
|
+
sort by `Chr` and `Begin` first (results are floats):
|
|
358
|
+
|
|
359
|
+
```bash
|
|
360
|
+
dftk eval segments.tsv -f 'gap = Begin - End.groupby(Chr).shift()'
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
Without `groupby(Chr)` the first segment of a chromosome is compared with
|
|
364
|
+
the last one of the previous chromosome.
|
|
258
365
|
|
|
259
366
|
### Bootstrap confidence intervals
|
|
260
367
|
|
|
@@ -197,35 +197,141 @@ printf "sample\tfluor\ns1\t60\ns2\t110\n" \
|
|
|
197
197
|
|
|
198
198
|
### Filling missing values
|
|
199
199
|
|
|
200
|
-
`eval -f` takes pandas column methods (`COL.method(...)`)
|
|
201
|
-
`ffill`, `bfill` and `interpolate` fill empty cells
|
|
202
|
-
|
|
200
|
+
`eval -f` takes pandas column methods (`COL.method(...)`); `fillna`,
|
|
201
|
+
`ffill`, `bfill` and `interpolate` fill empty cells and keep the others.
|
|
202
|
+
|
|
203
|
+
| Formula | Fills with |
|
|
204
|
+
|---|---|
|
|
205
|
+
| `x = x.fillna(y)` | the value in column `y` |
|
|
206
|
+
| `x = x.fillna(0)`, `sex = sex.fillna('unknown')` | a fixed value |
|
|
207
|
+
| `x = x.fillna(y).fillna(0)` | `y` first, then 0 |
|
|
208
|
+
| `x = x.fillna(x.groupby(g).transform('mean'))` | the mean of the row's group (or `'median'`, ...) |
|
|
209
|
+
| `x = x.ffill()` / `x = x.bfill()` | the value above / below (`ffill(limit=1)`: at most one row) |
|
|
210
|
+
| `x = x.groupby(g).ffill()` | the value above, within each group of `g` |
|
|
211
|
+
| `x = x.interpolate()` | a straight line between the values above and below, by row position |
|
|
212
|
+
|
|
213
|
+
Write to a new column (`x_filled = x.fillna(y)`) to keep the original, and
|
|
214
|
+
mark the gaps first (`missing = x.isna()`) to tell filled values apart.
|
|
215
|
+
Only empty cells are filled: a missing row (a year with no row at all) is
|
|
216
|
+
not added.
|
|
217
|
+
|
|
218
|
+
**Defaults from another table.** A column that is in both files gets the
|
|
219
|
+
suffix `_r` from `merge`; fill from it, then drop it. Here the defaults are
|
|
220
|
+
each species' median body mass:
|
|
203
221
|
|
|
204
222
|
```bash
|
|
205
|
-
dftk
|
|
206
|
-
|
|
223
|
+
dftk dataset penguins -o | dftk pivot ... -i species -v body_mass_g \
|
|
224
|
+
-f median --move median_body_mass_g:body_mass_g -o defaults.parquet
|
|
225
|
+
dftk dataset penguins -o \
|
|
226
|
+
| dftk merge ... -r defaults.parquet -k species -t left -o \
|
|
227
|
+
| dftk eval ... -f "body_mass_g = body_mass_g.fillna(body_mass_g_r)" \
|
|
228
|
+
--drop body_mass_g_r
|
|
207
229
|
```
|
|
208
230
|
|
|
209
|
-
|
|
210
|
-
each group:
|
|
231
|
+
**From neighbouring rows** (`co2` is a weekly series with gaps):
|
|
211
232
|
|
|
212
233
|
```bash
|
|
213
|
-
dftk dataset
|
|
214
|
-
-f "
|
|
215
|
-
|
|
216
|
-
|
|
234
|
+
dftk dataset co2 -o | dftk eval ... -f "ffill = co2.ffill()" \
|
|
235
|
+
-f "bfill = co2.bfill()" -f "linear = co2.interpolate()"
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
`ffill` leaves the first rows empty and `bfill` the last ones;
|
|
239
|
+
`x.ffill().fillna(x.bfill())` fills both. `interpolate()` counts one step
|
|
240
|
+
per row, so the rows must be evenly spaced; for an x-based lookup from a
|
|
241
|
+
reference curve, see `dftk interp`.
|
|
217
242
|
|
|
243
|
+
**Row order and groups.** These methods use the rows in the order they are
|
|
244
|
+
in. Sort first, in a step of its own: `--sortasc` applies to a command's
|
|
245
|
+
output, so in the same command it would come after the fill. When a table
|
|
246
|
+
holds several series (sites, countries, samples), fill within each group,
|
|
247
|
+
or values are taken from the neighbouring group. Rows of a group don't need
|
|
248
|
+
to be next to each other, but within each group they must be in order:
|
|
249
|
+
|
|
250
|
+
```bash
|
|
218
251
|
dftk dataset healthexp -o \
|
|
219
|
-
| dftk eval ... -f "le = Life_Expectancy.where(Year % 10 != 5)"
|
|
252
|
+
| dftk eval ... -f "le = Life_Expectancy.where(Year % 10 != 5)" \
|
|
253
|
+
--sortasc Country Year -o \
|
|
220
254
|
| dftk eval ... -f "le_filled = le.groupby(Country).ffill()"
|
|
221
255
|
```
|
|
222
256
|
|
|
223
|
-
`
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
257
|
+
`interpolate()` has no grouped form. Once each group's rows are together,
|
|
258
|
+
gaps inside a group are right, but a gap at a group's start or end is
|
|
259
|
+
filled from the neighbouring group. To leave those empty, keep only values
|
|
260
|
+
with something before and after them in the same group:
|
|
261
|
+
|
|
262
|
+
```bash
|
|
263
|
+
dftk dataset healthexp -o \
|
|
264
|
+
| dftk eval ... -f "le = Life_Expectancy.where(Year % 10 != 5)" \
|
|
265
|
+
--sortasc Country Year -o \
|
|
266
|
+
| dftk eval ... -f "before = le.groupby(Country).ffill().notna()" \
|
|
267
|
+
-f "after = le.groupby(Country).bfill().notna()" \
|
|
268
|
+
-f "le_linear = le.interpolate().where(before & after)" \
|
|
269
|
+
--drop before after
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### Differences between rows
|
|
273
|
+
|
|
274
|
+
For the change in a column from one row to the next, `eval -f` takes
|
|
275
|
+
pandas `diff()` and `pct_change()`, also within groups. They use the rows
|
|
276
|
+
in their order, so sort first, in a step of its own:
|
|
277
|
+
|
|
278
|
+
```bash
|
|
279
|
+
dftk dataset healthexp -o | dftk eval ... --sortasc Country Year -o \
|
|
280
|
+
| dftk eval ... -f "change = Spending_USD.groupby(Country).diff().round(1)" \
|
|
281
|
+
-f "pct = (Spending_USD.groupby(Country).pct_change() * 100).round(1)" \
|
|
282
|
+
-f "years = Year.groupby(Country).diff()"
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
```text
|
|
286
|
+
Year Country Spending_USD Life_Expectancy change pct years
|
|
287
|
+
1971 Canada 313.391 72.8
|
|
288
|
+
1976 Canada 543.337 73.8 229.9 73.4 5.0
|
|
289
|
+
1979 Canada 692.269 75.1 148.9 27.4 3.0
|
|
290
|
+
1980 Canada 791.812 75.2 99.5 14.4 1.0
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
The first row of each country gets an empty cell. Without
|
|
294
|
+
`groupby(Country)`, it would be compared with the last row of the
|
|
295
|
+
previous country.
|
|
296
|
+
|
|
297
|
+
To compare a value with one in another column of the previous or next row, for example the
|
|
298
|
+
gap between segments given by `Chr`, `Begin`, `End`, use SQL's `LAG()` /
|
|
299
|
+
`LEAD()` in `query --sql`:
|
|
300
|
+
|
|
301
|
+
```bash
|
|
302
|
+
dftk query segments.tsv --sql \
|
|
303
|
+
'SELECT *, "Begin" - LAG("End") OVER (PARTITION BY Chr ORDER BY "Begin")
|
|
304
|
+
AS gap
|
|
305
|
+
FROM data ORDER BY Chr, "Begin"'
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
```text
|
|
309
|
+
Chr Begin End Id gap
|
|
310
|
+
chr1 100 200 a
|
|
311
|
+
chr1 250 400 b 50
|
|
312
|
+
chr1 390 500 c -10
|
|
313
|
+
chr2 50 80 d
|
|
314
|
+
chr2 100 300 e 20
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
A negative gap is an overlap, and the first segment on each chromosome
|
|
318
|
+
gets an empty cell. `lead("Begin") OVER (...) - "End"` gives the gap to
|
|
319
|
+
the next segment instead.
|
|
320
|
+
|
|
321
|
+
- `Begin` and `End` are SQL keywords: quote such column names with double
|
|
322
|
+
quotes and the whole statement with single quotes.
|
|
323
|
+
- No sorting is needed first; `ORDER BY` inside `OVER` sets the order.
|
|
324
|
+
- Integers stay integers.
|
|
325
|
+
|
|
326
|
+
`eval -f` can do the same with pandas `shift`, but it goes by row order, so
|
|
327
|
+
sort by `Chr` and `Begin` first (results are floats):
|
|
328
|
+
|
|
329
|
+
```bash
|
|
330
|
+
dftk eval segments.tsv -f 'gap = Begin - End.groupby(Chr).shift()'
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
Without `groupby(Chr)` the first segment of a chromosome is compared with
|
|
334
|
+
the last one of the previous chromosome.
|
|
229
335
|
|
|
230
336
|
### Bootstrap confidence intervals
|
|
231
337
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "dataframe-toolkit"
|
|
3
|
-
version = "0.11.
|
|
3
|
+
version = "0.11.3"
|
|
4
4
|
description = "A command-line toolkit for DataFrame analysis and manipulation"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
keywords = [
|
|
@@ -29,6 +29,7 @@ dependencies = [
|
|
|
29
29
|
"patsy>=0.5.6",
|
|
30
30
|
"duckdb>=0.8",
|
|
31
31
|
"matplotlib>=3.7",
|
|
32
|
+
"pillow>=13.0",
|
|
32
33
|
"seaborn>=0.12",
|
|
33
34
|
"tqdm>=4.65",
|
|
34
35
|
]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "dataframe-toolkit"
|
|
3
|
-
version = "0.11.
|
|
3
|
+
version = "0.11.3"
|
|
4
4
|
description = "A command-line toolkit for DataFrame analysis and manipulation"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
authors = [
|
|
@@ -26,6 +26,7 @@ dependencies = [
|
|
|
26
26
|
"patsy>=0.5.6",
|
|
27
27
|
"duckdb>=0.8",
|
|
28
28
|
"matplotlib>=3.7",
|
|
29
|
+
"pillow>=13.0", # not used directly (matplotlib needs it); floor for security fixes
|
|
29
30
|
"seaborn>=0.12",
|
|
30
31
|
"tqdm>=4.65",
|
|
31
32
|
]
|