PySpark-Column-Selectors 0.1.3__py3-none-any.whl

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.
@@ -0,0 +1,674 @@
1
+ Metadata-Version: 2.5
2
+ Name: PySpark_Column_Selectors
3
+ Version: 0.1.3
4
+ Summary: Adds column selector functionality to pyspark
5
+ Project-URL: bugs, https://github.com/tmichel3796/PySparkSelectors/issues
6
+ Project-URL: changelog, https://github.com/tmichel3796/PySparkSelectors/releases
7
+ Project-URL: documentation, https://tmichel3796.github.io/PySparkSelectors/
8
+ Project-URL: homepage, https://github.com/tmichel3796/PySparkSelectors
9
+ Author-email: "Trevor A. Michel" <Info@TrevorMichel.com>
10
+ Maintainer-email: "Trevor A. Michel" <Info@TrevorMichel.com>
11
+ License: MIT
12
+ License-File: LICENSE
13
+ Classifier: Typing :: Typed
14
+ Requires-Python: >=3.10
15
+ Requires-Dist: pyspark
16
+ Requires-Dist: rich
17
+ Requires-Dist: typer
18
+ Requires-Dist: typing-extensions
19
+ Description-Content-Type: text/markdown
20
+
21
+ # PySpark Column Selectors
22
+
23
+ A small object-oriented framework for selecting DataFrame columns by **dtype**, **position**, or **name pattern** instead of typing out column names by hand. A selector can be passed almost anywhere a column or list of columns is normally accepted, and selectors can be combined with set operations and chained with ordinary column transforms.
24
+
25
+ ![PyPI version](https://img.shields.io/pypi/v/PySpark_Column_Selectors.svg)
26
+
27
+ Adds column selector functionality to pyspark
28
+
29
+ - GitHub: <https://github.com/tmichel3796/PySpark_Column_Selectors/>
30
+ - PyPI package: <https://pypi.org/project/PySpark_Column_Selectors/>
31
+ - Created by: [**Trevor A. Michel**](trevormichel.com) \| GitHub <https://github.com/tmichel3796> \| PyPI <https://pypi.org/user/tmichel3796/>
32
+ - Free software: MIT License
33
+
34
+ ## Features
35
+
36
+ ## Dependencies
37
+
38
+ - Python 3.8+
39
+ - PySpark 3.4 or newer (for full functionality)
40
+ - PySpark 3.3 still works, except `T.TimestampNTZType` won't exist
41
+ - `temporal()`/`datetime_()` fall back to matching only `T.TimestampType` on those older versions instead of raising.
42
+ - `withColumns` with multiple selector-driven mutations in a single call (see [Using selectors with other DataFrame operations](#using-selectors-with-other-dataframe-operations)) requires PySpark 3.3+, since `DataFrame.withColumns` itself didn't exist before then.
43
+ - No third-party packages beyond PySpark itself -- everything else used (`functools`, `operator`, `re`, `typing`) is part of the Python standard library.
44
+ - Spark Connect (`pyspark.sql.connect`) is supported automatically when present, but is not required -- this framework works the same either way.
45
+
46
+ ## Importing
47
+
48
+ ``` python
49
+ import PySparkSelectors as scs
50
+ ```
51
+
52
+ Every example below assumes this import, and calls each selector as `scs.<function_name>(...)`.
53
+
54
+ ------------------------------------------------------------------------
55
+
56
+ ## Example data
57
+
58
+ Every example in this document runs against the same small DataFrame:
59
+
60
+ ``` python
61
+ df = spark.createDataFrame(
62
+ [
63
+ (1, "north", "east", 120.5, 88, True, "2024-01-15", 910, "2024-06-01 08:30:00"),
64
+ (2, "south", "west", 340.0, 95, False, "2024-03-22", 875, "2024-06-02 14:45:00"),
65
+ ],
66
+ ["id", "name", "region", "elevation", "totalscore", "isactive", "signupdate", "score2024", "lastseen"],
67
+ )
68
+ ```
69
+
70
+ | id | name | region | elevation | totalscore | isactive | signupdate | score2024 | lastseen |
71
+ |--------|--------|--------|--------|--------|--------|--------|--------|--------|
72
+ | 1 | north | east | 120.5 | 88 | true | 2024-01-15 | 910 | 2024-06-01 08:30:00 |
73
+ | 2 | south | west | 340.0 | 95 | false | 2024-03-22 | 875 | 2024-06-02 14:45:00 |
74
+
75
+ Dtypes: `id` (int), `name`/`region` (string), `elevation` (double), `totalscore`/`score2024` (int), `isactive` (boolean), `signupdate` (date), `lastseen` (timestamp).
76
+
77
+ ------------------------------------------------------------------------
78
+
79
+ ## Dtype-based selectors
80
+
81
+ Dtype selectors match against the real `pyspark.sql.types` classes, not dtype strings. Import the types module alongside the selectors:
82
+
83
+ ``` python
84
+ import pyspark.sql.types as T
85
+ ```
86
+
87
+ ### `by_dtype([...])`
88
+
89
+ Matches any `pyspark.sql.types.DataType` class (or classes) you pass in. A category base class (e.g. `T.NumericType`) matches every concrete subclass of it too -- `by_dtype([T.NumericType])` matches integer, floating-point, *and* decimal columns in one call.
90
+
91
+ ``` python
92
+ df.select(scs.by_dtype([T.StringType]))
93
+ ```
94
+
95
+ | name | region |
96
+ |-------|--------|
97
+ | north | east |
98
+ | south | west |
99
+
100
+ ### `string()`
101
+
102
+ ``` python
103
+ df.select(scs.string())
104
+ ```
105
+
106
+ | name | region |
107
+ |-------|--------|
108
+ | north | east |
109
+ | south | west |
110
+
111
+ ### `boolean()`
112
+
113
+ ``` python
114
+ df.select(scs.boolean())
115
+ ```
116
+
117
+ | isactive |
118
+ |----------|
119
+ | true |
120
+ | false |
121
+
122
+ ### `binary()`
123
+
124
+ There are no binary columns in this DataFrame, so this raises an error by default rather than returning nothing -- see [Handling zero matches](#handling-zero-matches) below.
125
+
126
+ ### `integer()`
127
+
128
+ Fixed-width integer columns (tinyint/smallint/int/bigint).
129
+
130
+ ``` python
131
+ df.select(scs.integer())
132
+ ```
133
+
134
+ | id | totalscore | score2024 |
135
+ |-----|------------|-----------|
136
+ | 1 | 88 | 910 |
137
+ | 2 | 95 | 875 |
138
+
139
+ ### `floats()`
140
+
141
+ Floating-point columns (float/double).
142
+
143
+ ``` python
144
+ df.select(scs.floats())
145
+ ```
146
+
147
+ | elevation |
148
+ |-----------|
149
+ | 120.5 |
150
+ | 340.0 |
151
+
152
+ ### `numeric()`
153
+
154
+ Every fixed-width numeric column (integer or floating-point).
155
+
156
+ ``` python
157
+ df.select(scs.numeric())
158
+ ```
159
+
160
+ | id | elevation | totalscore | score2024 |
161
+ |-----|-----------|------------|-----------|
162
+ | 1 | 120.5 | 88 | 910 |
163
+ | 2 | 340.0 | 95 | 875 |
164
+
165
+ ### `date()`
166
+
167
+ ``` python
168
+ df.select(scs.date())
169
+ ```
170
+
171
+ | signupdate |
172
+ |------------|
173
+ | 2024-01-15 |
174
+ | 2024-03-22 |
175
+
176
+ ### `datetime_()`
177
+
178
+ ``` python
179
+ df.select(scs.datetime_())
180
+ ```
181
+
182
+ | lastseen |
183
+ |---------------------|
184
+ | 2024-06-01 08:30:00 |
185
+ | 2024-06-02 14:45:00 |
186
+
187
+ ### `temporal()`
188
+
189
+ Date or timestamp columns.
190
+
191
+ ``` python
192
+ df.select(scs.temporal())
193
+ ```
194
+
195
+ | signupdate | lastseen |
196
+ |------------|---------------------|
197
+ | 2024-01-15 | 2024-06-01 08:30:00 |
198
+ | 2024-03-22 | 2024-06-02 14:45:00 |
199
+
200
+ ------------------------------------------------------------------------
201
+
202
+ ## Position-based selectors
203
+
204
+ ### `by_index(*indexes)`
205
+
206
+ Selects one or more columns by position. Negative positions work the same way Python indexing does (`-1` is the last column), and a `range(...)` can be mixed in with plain integers to grab a span in one call.
207
+
208
+ ``` python
209
+ df.select(scs.by_index(range(0, 1), 3))
210
+ ```
211
+
212
+ | id | name | elevation |
213
+ |-----|-------|-----------|
214
+ | 1 | north | 120.5 |
215
+ | 2 | south | 340.0 |
216
+
217
+ ### `first()`
218
+
219
+ ``` python
220
+ df.select(scs.first())
221
+ ```
222
+
223
+ | id |
224
+ |-----|
225
+ | 1 |
226
+ | 2 |
227
+
228
+ ### `last()`
229
+
230
+ ``` python
231
+ df.select(scs.last())
232
+ ```
233
+
234
+ | lastseen |
235
+ |---------------------|
236
+ | 2024-06-01 08:30:00 |
237
+ | 2024-06-02 14:45:00 |
238
+
239
+ ### Handle column not in range error {#handle-column-not-in-range-error}
240
+
241
+ By default, `by_index` raises if any requested position is out of range for the DataFrame (this DataFrame has 9 columns, at positions 0-8):
242
+
243
+ ``` python
244
+ df.select(scs.by_index(9))
245
+ # raises pyspark.errors.PySparkValueError -- position 9 is out of range
246
+ ```
247
+
248
+ Passing `strict_index_bounds=False` skips any out-of-range position instead of raising, so only the in-range positions are matched:
249
+
250
+ ``` python
251
+ df.select(scs.by_index(0, 9, strict_index_bounds=False))
252
+ ```
253
+
254
+ | id |
255
+ |-----|
256
+ | 1 |
257
+ | 2 |
258
+
259
+ > Note: if every requested position ends up out of range, `strict_index_bounds=False` alone still isn't enough to avoid an error -- the selector would then match zero columns, which raises on its own (see [Handling zero matches](#handling-zero-matches)). To allow that case too, also pass `require_col_match=False`.
260
+
261
+ ------------------------------------------------------------------------
262
+
263
+ ## Name-based selectors
264
+
265
+ All name-based matching below is case-insensitive -- `scs.by_name("REGION")` matches a column named `region` just as well as `scs.by_name("region")` does, and column names may contain a literal dot (e.g. `meta.source`) without being mistaken for a nested field.
266
+
267
+ ### `matches(pattern)`
268
+
269
+ Selects columns whose name matches a regular expression.
270
+
271
+ ``` python
272
+ df.select(scs.matches("score"))
273
+ ```
274
+
275
+ | totalscore | score2024 |
276
+ |------------|-----------|
277
+ | 88 | 910 |
278
+ | 95 | 875 |
279
+
280
+ `matches` takes any pattern the `re` module can compile, not just a plain substring -- anchors, character classes, and alternation all work:
281
+
282
+ ``` python
283
+ df.select(scs.matches(r"^s.*[aeiou]$|\d"))
284
+ ```
285
+
286
+ | signupdate | score2024 |
287
+ |------------|-----------|
288
+ | 2024-01-15 | 910 |
289
+ | 2024-03-22 | 875 |
290
+
291
+ This pattern matches a column name if it either starts with `s` and ends in a vowel (`signupdate`), or contains a digit anywhere in the name (`score2024`).
292
+
293
+ ### `starts_with(*prefixes)`
294
+
295
+ ``` python
296
+ df.select(scs.starts_with("e"))
297
+ ```
298
+
299
+ | elevation |
300
+ |-----------|
301
+ | 120.5 |
302
+ | 340.0 |
303
+
304
+ ### `ends_with(*suffixes)`
305
+
306
+ ``` python
307
+ df.select(scs.ends_with("date"))
308
+ ```
309
+
310
+ | signupdate |
311
+ |------------|
312
+ | 2024-01-15 |
313
+ | 2024-03-22 |
314
+
315
+ ### `contains(*substrings)`
316
+
317
+ ``` python
318
+ df.select(scs.contains("2024"))
319
+ ```
320
+
321
+ | score2024 |
322
+ |-----------|
323
+ | 910 |
324
+ | 875 |
325
+
326
+ ### `by_name(*names)`
327
+
328
+ Selects an exact list of column names.
329
+
330
+ ``` python
331
+ df.select(scs.by_name("id", "region"))
332
+ ```
333
+
334
+ | id | region |
335
+ |-----|--------|
336
+ | 1 | east |
337
+ | 2 | west |
338
+
339
+ ### `exclude(*names)`
340
+
341
+ Selects every column except the given names.
342
+
343
+ ``` python
344
+ df.select(scs.exclude("region"))
345
+ ```
346
+
347
+ | id | name | elevation | totalscore | isactive | signupdate | score2024 | lastseen |
348
+ |---------|---------|---------|---------|---------|---------|---------|---------|
349
+ | 1 | north | 120.5 | 88 | true | 2024-01-15 | 910 | 2024-06-01 08:30:00 |
350
+ | 2 | south | 340.0 | 95 | false | 2024-03-22 | 875 | 2024-06-02 14:45:00 |
351
+
352
+ ### `alpha()`
353
+
354
+ Column names made up only of letters. `score2024` is the only column name containing a digit, so it's the only one excluded here.
355
+
356
+ ``` python
357
+ df.select(scs.alpha())
358
+ ```
359
+
360
+ | id | name | region | elevation | totalscore | isactive | signupdate | lastseen |
361
+ |---------|---------|---------|---------|---------|---------|---------|---------|
362
+ | 1 | north | east | 120.5 | 88 | true | 2024-01-15 | 2024-06-01 08:30:00 |
363
+ | 2 | south | west | 340.0 | 95 | false | 2024-03-22 | 2024-06-02 14:45:00 |
364
+
365
+ ### `alphanumeric()`
366
+
367
+ Column names made up only of letters and/or digits -- every column name in this DataFrame qualifies, including `score2024`.
368
+
369
+ ``` python
370
+ df.select(scs.alphanumeric())
371
+ ```
372
+
373
+ Returns every column, identical to the example data table above.
374
+
375
+ ### `all()`
376
+
377
+ ``` python
378
+ df.select(scs.all())
379
+ ```
380
+
381
+ Returns every column, identical to the example data table above.
382
+
383
+ ------------------------------------------------------------------------
384
+
385
+ ## Combining selectors
386
+
387
+ Selectors support set-style operators so more specific selections can be built without listing columns by hand. Combined selectors always resolve columns in the same order they appear in the underlying DataFrame.
388
+
389
+ ### Union (`|`)
390
+
391
+ ``` python
392
+ df.select(scs.string() | scs.starts_with("e"))
393
+ ```
394
+
395
+ | name | region | elevation |
396
+ |-------|--------|-----------|
397
+ | north | east | 120.5 |
398
+ | south | west | 340.0 |
399
+
400
+ ### Intersection (`&`)
401
+
402
+ ``` python
403
+ df.select(scs.numeric() & scs.matches("score"))
404
+ ```
405
+
406
+ | totalscore | score2024 |
407
+ |------------|-----------|
408
+ | 88 | 910 |
409
+ | 95 | 875 |
410
+
411
+ ### Difference (`-`)
412
+
413
+ ``` python
414
+ df.select(scs.all() - scs.numeric())
415
+ ```
416
+
417
+ | name | region | isactive | signupdate | lastseen |
418
+ |-------|--------|----------|------------|---------------------|
419
+ | north | east | true | 2024-01-15 | 2024-06-01 08:30:00 |
420
+ | south | west | false | 2024-03-22 | 2024-06-02 14:45:00 |
421
+
422
+ ### Symmetric difference (`^`)
423
+
424
+ Columns matched by exactly one side, not both.
425
+
426
+ ``` python
427
+ df.select(scs.contains("score") ^ scs.numeric())
428
+ ```
429
+
430
+ | id | elevation |
431
+ |-----|-----------|
432
+ | 1 | 120.5 |
433
+ | 2 | 340.0 |
434
+
435
+ ### Complement (`~`)
436
+
437
+ ``` python
438
+ df.select(~scs.temporal())
439
+ ```
440
+
441
+ | id | name | region | elevation | totalscore | isactive | score2024 |
442
+ |-----|-------|--------|-----------|------------|----------|-----------|
443
+ | 1 | north | east | 120.5 | 88 | true | 910 |
444
+ | 2 | south | west | 340.0 | 95 | false | 875 |
445
+
446
+ ------------------------------------------------------------------------
447
+
448
+ ## Chaining transforms onto a selector
449
+
450
+ A transform can be chained onto a selector before it's resolved. The transform is applied to every column the selector matches, and the original column name is preserved in the result.
451
+
452
+ ### `.upper()`
453
+
454
+ ``` python
455
+ df.select(scs.string().upper())
456
+ ```
457
+
458
+ | name | region |
459
+ |-------|--------|
460
+ | NORTH | EAST |
461
+ | SOUTH | WEST |
462
+
463
+ ### `.cast(...)`
464
+
465
+ ``` python
466
+ df.select(scs.floats().cast("string"))
467
+ ```
468
+
469
+ | elevation |
470
+ |-----------|
471
+ | 120.5 |
472
+ | 340.0 |
473
+
474
+ The values look the same, but `elevation` is now a `string` column instead of a `double` column.
475
+
476
+ ### Arithmetic
477
+
478
+ ``` python
479
+ df.select(scs.integer() + 1)
480
+ ```
481
+
482
+ | id | totalscore | score2024 |
483
+ |-----|------------|-----------|
484
+ | 2 | 89 | 911 |
485
+ | 3 | 96 | 876 |
486
+
487
+ Because every column function available in PySpark is also available as a chained method on a selector, this works with things like `.substr(...)`, `.isNull()`, `.between(...)`, and comparison operators too, not just a fixed list of built-ins.
488
+
489
+ ### Renaming columns:
490
+
491
+ `.prefix(...)`, `.suffix(...)`, and `.map_alias(...)` Three functions used to modify a columns name.
492
+
493
+ #### `.prefix(prefix)`
494
+
495
+ Prepends `prefix` to every matched column's name.
496
+
497
+ ``` python
498
+ df.select(scs.by_name("id", "region").prefix("src_"))
499
+ ```
500
+
501
+ | src_id | src_region |
502
+ |--------|------------|
503
+ | 1 | east |
504
+ | 2 | west |
505
+
506
+ #### `.suffix(suffix)`
507
+
508
+ Appends `suffix` to every matched column's name.
509
+
510
+ ``` python
511
+ df.select(scs.numeric().suffix("_raw"))
512
+ ```
513
+
514
+ | id_raw | elevation_raw | totalscore_raw | score2024_raw |
515
+ |--------|---------------|----------------|---------------|
516
+ | 1 | 120.5 | 88 | 910 |
517
+ | 2 | 340.0 | 95 | 875 |
518
+
519
+ #### `.map_alias(func)`
520
+
521
+ Renames every matched column by passing its current name to `func`, a one-argument function returning the new name. `.prefix(...)` and `.suffix(...)` are both just `.map_alias(...)` with a prepend/append built in -- `.map_alias(...)` is for anything more custom.
522
+
523
+ ``` python
524
+ df.select(scs.by_name("name", "region").map_alias(lambda n: n.upper()))
525
+ ```
526
+
527
+ | NAME | REGION |
528
+ |-------|--------|
529
+ | north | east |
530
+ | south | west |
531
+
532
+ Note this renames the *columns*, not the *values* -- compare to `.upper()` above, which uppercases the values but keeps the column names unchanged.
533
+
534
+ ------------------------------------------------------------------------
535
+
536
+ ## Using selectors with row filtering
537
+
538
+ A selector used inside a comparison becomes a row condition instead of a column pick, and conditions built this way can be combined with `&`, `|`, and `~` the same way plain columns can. `filter`/`where` still return every original column for the matching rows -- only the relevant column(s) are shown below for readability.
539
+
540
+ ### A single condition
541
+
542
+ ``` python
543
+ df.filter(scs.by_name("totalscore") > 90)
544
+ ```
545
+
546
+ | id | totalscore |
547
+ |-----|------------|
548
+ | 2 | 95 |
549
+
550
+ *(the row for `id=1` is dropped, since `totalscore` there is 88)*
551
+
552
+ ### Combining conditions with `&`
553
+
554
+ ``` python
555
+ df.filter((scs.by_name("totalscore") > 90) & (scs.by_name("elevation") > 200))
556
+ ```
557
+
558
+ | id | totalscore | elevation |
559
+ |-----|------------|-----------|
560
+ | 2 | 95 | 340.0 |
561
+
562
+ ------------------------------------------------------------------------
563
+
564
+ ## Using selectors with other DataFrame operations {#using-selectors-with-other-dataframe-operations}
565
+
566
+ ### `select` with multiple selectors
567
+
568
+ ``` python
569
+ df.select(scs.string(), scs.integer())
570
+ ```
571
+
572
+ | name | region | id | totalscore | score2024 |
573
+ |-------|--------|-----|------------|-----------|
574
+ | north | east | 1 | 88 | 910 |
575
+ | south | west | 2 | 95 | 875 |
576
+
577
+ ### `groupBy` / `agg`
578
+
579
+ ``` python
580
+ df.groupBy(scs.by_name("region")).agg(scs.integer().sum())
581
+ ```
582
+
583
+ | region | sum(id) | sum(totalscore) | sum(score2024) |
584
+ |--------|---------|-----------------|----------------|
585
+ | east | 1 | 88 | 910 |
586
+ | west | 2 | 95 | 875 |
587
+
588
+ ### `drop`
589
+
590
+ ``` python
591
+ df.drop(scs.by_name("lastseen", "signupdate"))
592
+ ```
593
+
594
+ Removes `lastseen` and `signupdate`, leaving `id`, `name`, `region`, `elevation`, `totalscore`, `isactive`, `score2024`.
595
+
596
+ ### `sort` / `orderBy`
597
+
598
+ ``` python
599
+ df.sort(scs.by_name("elevation").desc())
600
+ ```
601
+
602
+ | id | elevation |
603
+ |-----|-----------|
604
+ | 2 | 340.0 |
605
+ | 1 | 120.5 |
606
+
607
+ *(every other original column is still present in the result; only `elevation` is shown here for readability)*
608
+
609
+ ### `withColumns` with multiple selector-driven mutations
610
+
611
+ ``` python
612
+ df.withColumns(
613
+ scs.floats().cast("string"),
614
+ scs.string().upper(),
615
+ )
616
+ ```
617
+
618
+ | id | name | region | elevation |
619
+ |-----|-------|--------|-----------|
620
+ | 1 | NORTH | EAST | 120.5 |
621
+ | 2 | SOUTH | WEST | 340.0 |
622
+
623
+ Both mutations happen in the same call: every double column is cast to string, and every string column is uppercased.
624
+
625
+ ------------------------------------------------------------------------
626
+
627
+ ## Checking whether something is a selector
628
+
629
+ ``` python
630
+ scs.is_selector(scs.numeric()) # True
631
+ scs.is_selector("totalscore") # False
632
+ ```
633
+
634
+ ------------------------------------------------------------------------
635
+
636
+ ## Handling zero matches {#handling-zero-matches}
637
+
638
+ By default, if a selector resolves to zero columns against a given DataFrame, it raises an error rather than silently returning nothing. This also applies to combined selectors -- for example, subtracting a selector that covers every matching column from itself will raise, since the result has nothing left in it.
639
+
640
+ ``` python
641
+ df.select(scs.binary())
642
+ # raises pyspark.errors.PySparkValueError -- zero columns matched
643
+ ```
644
+
645
+ Every selector function accepts a `require_col_match` keyword argument, which defaults to `True`. Passing `require_col_match=False` opts out of this check for that particular selector, allowing a zero-column match to pass through silently instead of raising:
646
+
647
+ ``` python
648
+ df.select(scs.binary(require_col_match=False))
649
+ # returns a result with zero columns instead of raising
650
+ ```
651
+
652
+ This also applies to `by_dtype`, `by_index`, and `matches` directly:
653
+
654
+ ``` python
655
+ df.select(scs.all() - scs.by_index(range(0, 8)))
656
+ # There are 9 total columns in the df.
657
+ # As such the above column selector expression returns all columns - all columns.
658
+ # as such no columns of data are returned.
659
+ # Result: raises pyspark.errors.PySparkValueError -- zero columns matched
660
+ ```
661
+
662
+ To bypass the no columns returned error, see the below examples. All column selector functions have access to require_col_match by_index is the only one that offers access to strict_index_bounds as shown in [Handle column not in range error](#handle-column-not-in-range-error)
663
+
664
+ ``` python
665
+ df.select(scs.by_dtype([T.BinaryType], require_col_match=False))
666
+ df.select(scs.by_index(9, strict_index_bounds=False, require_col_match=False))
667
+ df.select(scs.matches("no_such_pattern", require_col_match=False))
668
+ ```
669
+
670
+ ## Author
671
+
672
+ PySparkSelectors was created in 2026 by Trevor A. Michel.
673
+
674
+ Built with [Cookiecutter](https://github.com/cookiecutter/cookiecutter) and the [audreyfeldroy/cookiecutter-pypackage](https://github.com/audreyfeldroy/cookiecutter-pypackage) project template.
@@ -0,0 +1,13 @@
1
+ PySparkSelectors/__init__.py,sha256=E22iHgXsvwBoswHdxVhsBqPHjmiHfgOHn9aGHZjZofk,7196
2
+ PySparkSelectors/__main__.py,sha256=Qd-f8z2Q2vpiEP2x6PBFsJrpACWDVxFKQk820MhFmHo,59
3
+ PySparkSelectors/cli.py,sha256=HbigdTpEa4nVpBOmv3Yo5TvzEufBb0RU8jNCxike3OA,424
4
+ PySparkSelectors/models.py,sha256=wlotfpDGXK2yuMiBn8_JhGkhYoYyHNEYS_T5f_psBs0,60688
5
+ PySparkSelectors/py.typed,sha256=8PjyZ1aVoQpRVvt71muvuq5qE-jTFZkK-GLHkhdebmc,26
6
+ PySparkSelectors/spark_overrides.py,sha256=SzlKR4ZneHzI-41MqxdiGe4y8w4tdBhy4KKLmXBD3lM,27100
7
+ PySparkSelectors/user_functions.py,sha256=d5EjOmXUQ6bkpgJNCWnU3lvjw9OALyt3b_0k5k3ppPA,24535
8
+ PySparkSelectors/utils.py,sha256=1SAf2SUXuLxIYMxF7qnm2AHt3ALK-SDvsUNn8sVh0n8,11133
9
+ pyspark_column_selectors-0.1.3.dist-info/METADATA,sha256=15WBT99qqy08od1DMuSBFR-nwfDv0swvMb6Rf4tYV-U,19572
10
+ pyspark_column_selectors-0.1.3.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
11
+ pyspark_column_selectors-0.1.3.dist-info/entry_points.txt,sha256=lDrzJJqOS4wQeRcg4ImS80KEIgogVbR_xtLMHpL0n7U,62
12
+ pyspark_column_selectors-0.1.3.dist-info/licenses/LICENSE,sha256=Oy-B_iHRgcSZxZolbI4ZaEVdZonSaaqFNzv7avQdo78,13936
13
+ pyspark_column_selectors-0.1.3.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.32.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ PySparkSelectors = PySparkSelectors.cli:app