-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Following a selector with .exclude() is not considered a selector #16448
Comments
This is actually the expected behaviour as the expression-method To instead perform set operations with selectors (intersection, union, difference, complement) you can use the In your example what you actually need is the following: cs.expand_selector(df, cs.starts_with("a") - cs.by_name("ab"))
# ('a',) This keeps things consistent - you don't really want expression methods to change their return type based on what they were called on, but if you want to do set operations on selectors, you can absolutely do that 👍 |
Can you say a bit more about this? To my understanding, this is fairly common (e.g. made easy to hint through the Self type). from typing import Self
class Expr:
def exclude(self, ...) -> Self:
return self.__class__(...) edit: a good example is the suggested selection, where the return type of
The bigger picture for Great TablesI think the challenge right now in Great Tables is that we want to do these things:
I think we are running into three issues:
We just need to know they are not transforming data, and the column names they'd select. So if Thanks for coming on this funky selection adventureI realize a lot of this is a funkier use of the polars API. Thanks for being so quick to help with this stuff :) |
In this case it's about API consistency more than anything technical - it's cleanest if expression methods on selectors consistently broadcast as expressions (a selector is an expression of course, but it's also a little special so... arguable). I'm very amenable to finding ways to make this work for your use-case though;
So... there are definitely no renaming operations happening at this point?
😎👍 |
Simple selector rules of thumb
Are the rules of thumb for selectors something like this?
The rule of thumb (1) explains why (I'm not too worried about the model, so much as humans being able to guess what will work and what won't; hedging against the risk that they don't know how to rewrite the things they're used to in Simple selection vs renaming
Yeah, exactly:
ExampleSimple selection is really helpful for cases like the coffee data table . import polars as pl
import polars.selectors as cs
from great_tables import GT, loc, style
coffee_sales = pl.read_json("data/coffee-sales.json")
sel_rev = cs.starts_with("revenue")
sel_prof = cs.starts_with("profit")
coffee_table = (
GT(coffee_sales)
.tab_header("Sales of Coffee Equipment")
# Case 1: simple selection ----
# create spanner columns "Revenue" and "Profit" (super common activity)
.tab_spanner(label="Revenue", columns=sel_rev)
.tab_spanner(label="Profit", columns=sel_prof)
# Case 2: renaming ----
# renaming basically only happens here
.cols_label(
revenue_dollars="Amount",
profit_dollars="Amount",
revenue_pct="Percent",
profit_pct="Percent",
icon="",
product="Product",
)
) |
You have nailed the rules of thumb - enough so that I am genuinely tempted to crib that breakdown for a small section in the selectors documentation to make it more widely available 🤣 Anyway, with the information above in mind, I think I have a solution, and have made a PR. Take a look and see if you think it'll cover everything? |
Available in the new release: |
Thanks! This is super helpful, and the addition of |
Checks
Reproducible example
Following a selector with
.exclude()
breakscs.expand_selector()
:However, this succeeds:
Log output
Issue description
.exclude()
currently returns a selector only if it's called off ofcs.exclude()
, but not if it follows a selector. I wonder if this is related to their also being apolars.exclude()
method?Expected behavior
It seems like
.exclude()
should return a selector, whether called fromcs.exclude()
(which currently returns a selector) or after a selector.Installed versions
The text was updated successfully, but these errors were encountered: