eshangj/stackoverflow_q_and_a_sample huggingface dataset:
Question: I cannot use the pl.exclude() selector as index in pl.DataFrame.unpivot despite the documentation of this method type hinting the index parameter as follows. index: 'ColumnNameOrSelector | Sequence[ColumnNameOrSelector] | None' = None  The follow code can be used to reproduce the error. import polars as pl df = pl.DataFrame({ 'foo' : ['one', 'two', 'three'], 'bar' : ['four', 'five', 'six'], 'baz' : [10, 20, 30], 'qux' : [50, 60, 70] }) column_list = ['baz', 'qux'] df.unpivot(column_list, index=pl.exclude(column_list))  TypeError: argument 'index': 'Expr' object cannot be converted to 'PyString'  Moreover, using the columns explicitly works fine. df.unpivot(column_list, index=['foo', 'bar'])  So, how can column selectors be used in pl.DataFrame.unpivot?

Answer: pl.exclude is a "regular" polars expression (of type pl.Expr). Selectors are special objects (also expressions, but of a specific subtype cs._selector_proxy_) that can be found in pl.selectors. import polars.selectors as cs column_list = ['baz', 'qux'] df.unpivot(column_list, index=cs.exclude(column_list))  shape: (6, 4) ┌───────┬──────┬──────────┬───────┐ │ foo ┆ bar ┆ variable ┆ value │ │ --- ┆ --- ┆ --- ┆ --- │ │ str ┆ str ┆ str ┆ i64 │ ╞═══════╪══════╪══════════╪═══════╡ │ one ┆ four ┆ baz ┆ 10 │ │ two ┆ five ┆ baz ┆ 20 │ │ three ┆ six ┆ baz ┆ 30 │ │ one ┆ four ┆ qux ┆ 50 │ │ two ┆ five ┆ qux ┆ 60 │ │ three ┆ six ┆ qux ┆ 70 │ └───────┴──────┴──────────┴───────┘
Question:  if user is not None: login(request, user) return redirect('home') else: error_message = "Invalid username or password." return render(request, 'login.html', {'error_message': error_message})  Using the above code, if user enters wrong credentials, login.html shows up successfully with error message. But now the URL is http://localhost:8000/authentication_view/. Now if the user re-enters credentials, the URL will be http://localhost:8000/authentication_view/authentication_view/, and it creates Page Not Found error. If I use return redirect('login_view'), then the error message will not show.  Could someone help me how to show login page with error message without adding Authentication View to the URL? I was expecting: if user provides wrong credentials, he gets error message and goes back to login page. Now he can re-enter credentials. But now login page is not usable because authentication view name is already added to the URL. New login attempt will add authentication view name twice the URL.

Answer: The issue with the action mentioned in the html page in form tag. you must have something like <form method="post" action="authentication_view/"> To solve the issue, best way is to remove the action from form tag. by default html form submit to same page. do something like this. <form method="post">  If you are loading page from different url and submitting form to other mention the complete url. in your case it should be. <form method="post" action="/authentication_view">
Question: I tried to start pytest but the settings file cannot be found by pytest I'm in virtualenv with Python 3.11.9 and pytest 8.3.2 ImportError: No module named 'drf.settings' pytest-django could not find a Django project (no manage.py file could be found). You must explicitly add your Django project to the Python path to have it picked up.  here the structure of my project ├── README.md ├── drf │ ├── drf │ │ ├── __init__.py │ │ ├── production_settings.py │ │ ├── settings.py │ │ ├── urls.py │ │ └── wsgi.py │ ├── manage.py │ └── tests │ ├── __pycache__ │ │ └── test_auth.cpython-311-pytest-8.3.2.pyc │ ├── factory_boy │ │ ├── __pycache__ │ │ │ └── factory_models.cpython-311.pyc │ │ └── factory_models.py │ └── test_auth.py ├── drf-uwsgi.ini ├── pytest.ini ├── requirements.in ├── requirements.txt  and here the content of pytest.ini [pytest] DJANGO_SETTINGS_MODULE = drf.settings python_files = test_*.py django_debug_mode = true pythonpath = .venv/bin/python  What I have tried so far:  I tried to add init.py to tests directory (seems not be recommended and didn't worked) deactivate and reactivate the virtualenv change drf.settings.py for drf.drf.settings but nothing run pytest as module with python -m pytest tests  edit: at this moment I can run pytest with any problem, but I use a conftest for that and search a solution with pytest.ini If you have any suggestions ;)

Answer: You need to add pythonpath within the pytest.ini as follows: [pytest] pythonpath = drf DJANGO_SETTINGS_MODULE = drf.settings python_files = test_*.py  Or you can change the layout of the tests and move the pytest.ini from the project's root to the tests folder like this SO post.  Note: use drf.settings instead of drf.settings.py
Question: My DataFrame is: import pandas as pd df = pd.DataFrame( { 'a': [-3, -1, -2, -5, 10, -3, -13, -3, -2, 1, 2, -100], } )  Expected output:  a 0 -3 1 -1 2 -2 3 -5  Logic: I want to return the largest streak of negative numbers. And if there are more than one streak that are the largest, I want to return the first streak. In df there are two negative streaks with size of 4, so the first one is returned. This is my attempt but whenever I use idxmax() in my code, I want to double check because it gets tricky sometimes in some scenarios. import numpy as np df['sign'] = np.sign(df.a) df['sign_streak'] = df.sign.ne(df.sign.shift(1)).cumsum() m = df.sign.eq(-1) group_sizes = df.groupby('sign_streak').size() largest_group = group_sizes.idxmax() largest_group_df = df[df['sign_streak'] == largest_group] 

Answer: Your code is fine, you could simplify it a bit, avoiding the intermediate columns: # get sign s = np.sign(df['a']) # form groups of successive identical sign g = s.ne(s.shift()).cumsum() # keep only negative, get size per group and first group with max size out = df[g.eq(df[s.eq(-1)].groupby(g).size().idxmax())]  Or, since you don't really care about the 0/+ difference: # negative numbers m = df['a'].lt(0) # form groups g = m.ne(m.shift()).cumsum() out = df[g.eq(df[m].groupby(g).size().idxmax())]  Note: idxmax is always fine if you want the first match. Output:  a 0 -3 1 -1 2 -2 3 -5
Question: Assume I have this dataframe import polars as pl df = pl.DataFrame({ 'item': ['CASH', 'CHECK', 'DEBT', 'CHECK', 'CREDIT', 'CASH'], 'quantity': [100, -20, 0, 10, 0, 0], 'value': [99, 47, None, 90, None, 120], 'value_other': [97, 57, None, 91, None, 110], 'value_other2': [94, 37, None, 93, None, 115], })  ┌────────┬──────────┬───────┬─────────────┬──────────────┐ │ item ┆ quantity ┆ value ┆ value_other ┆ value_other2 │ │ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ str ┆ i64 ┆ i64 ┆ i64 ┆ i64 │ ╞════════╪══════════╪═══════╪═════════════╪══════════════╡ │ CASH ┆ 100 ┆ 99 ┆ 97 ┆ 94 │ │ CHECK ┆ -20 ┆ 47 ┆ 57 ┆ 37 │ │ DEBT ┆ 0 ┆ null ┆ null ┆ null │ │ CHECK ┆ 10 ┆ 90 ┆ 91 ┆ 93 │ │ CREDIT ┆ 0 ┆ null ┆ null ┆ null │ │ CASH ┆ 0 ┆ 120 ┆ 110 ┆ 115 │ └────────┴──────────┴───────┴─────────────┴──────────────┘  Now I want to set all value columns to 0 for all rows where value is null and quantity == 0. Right now I have this solution cols = ['value', 'value_other', 'value_other2'] df = df.with_columns([ pl.when(pl.col('value').is_null() & (pl.col('quantity') == 0)) .then(0) .otherwise(pl.col(col)) .alias(col) for col in cols ])  which correctly gives ┌────────┬──────────┬───────┬─────────────┬──────────────┐ │ item ┆ quantity ┆ value ┆ value_other ┆ value_other2 │ │ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ str ┆ i64 ┆ i64 ┆ i64 ┆ i64 │ ╞════════╪══════════╪═══════╪═════════════╪══════════════╡ │ CASH ┆ 100 ┆ 99 ┆ 97 ┆ 94 │ │ CHECK ┆ -20 ┆ 47 ┆ 57 ┆ 37 │ │ DEBT ┆ 0 ┆ 0 ┆ 0 ┆ 0 │ │ CHECK ┆ 10 ┆ 90 ┆ 91 ┆ 93 │ │ CREDIT ┆ 0 ┆ 0 ┆ 0 ┆ 0 │ │ CASH ┆ 0 ┆ 120 ┆ 110 ┆ 115 │ └────────┴──────────┴───────┴─────────────┴──────────────┘  However, I feel this is very inefficient as my when condition is executed for every value column. Is there a way to achieve this using only polar internal functions & without the native for-loop?

Answer: You can pass list of column names into pl.col() and when\then\otherwise accepts Expr which can contain multiple columns. cols = ['value', 'value_other', 'value_other2'] df.with_columns( pl .when((pl.col.quantity != 0) | pl.col.value.is_not_null()) .then(pl.col(cols)) .otherwise(0) ) # or df.with_columns( pl .when(pl.col.quantity != 0).then(pl.col(cols)) .when(pl.col.value.is_not_null()).then(pl.col(cols)) .otherwise(0) )  shape: (6, 5) ┌────────┬──────────┬───────┬─────────────┬──────────────┐ │ item ┆ quantity ┆ value ┆ value_other ┆ value_other2 │ │ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ str ┆ i64 ┆ i64 ┆ i64 ┆ i64 │ ╞════════╪══════════╪═══════╪═════════════╪══════════════╡ │ CASH ┆ 100 ┆ 99 ┆ 97 ┆ 94 │ │ CHECK ┆ -20 ┆ 47 ┆ 57 ┆ 37 │ │ DEBT ┆ 0 ┆ 0 ┆ 0 ┆ 0 │ │ CHECK ┆ 10 ┆ 90 ┆ 91 ┆ 93 │ │ CREDIT ┆ 0 ┆ 0 ┆ 0 ┆ 0 │ │ CASH ┆ 0 ┆ 120 ┆ 110 ┆ 115 │ └────────┴──────────┴───────┴─────────────┴──────────────┘
Question: $ python3 -t -c 'print("hello world")' hello world  What does -t do? It's not mentioned in python3 --help. Usually unknown options cause a non-zero exit code, like $ python3 -r Unknown option: -r usage: python3 [option] ... [-c cmd | -m mod | file | -] [arg] ... Try `python -h' for more information. 

Answer: The -t option in python3 was a feature from Python 2.x that warned about inconsistent use of tabs and spaces in the source code. However, this option was removed in Python 3.x. Therefore, when you run python3 -t -c 'print("hello world")', Python 3 just ignores the -t option and executes the code as usual.
Question: This is my DataFrame: import pandas as pd df = pd.DataFrame( { 'a': [3, 1, 2, 5, 10, 3, 13, 3, 2], } )  Expected output is creating a a_max and a_min:  a a_max a_min 0 3 NaN NaN 1 1 3 1 2 2 3 1 3 5 3 1 4 10 3 1 5 3 10 3 6 13 10 3 7 3 13 3 8 2 13 2  Logic: I explain the logic row by row. There is a dynamic window for this df that for the first instance of the window only the first row is considered. For the second instance of the window the first two rows are considered. Same as below:  These are the first four windows. It expands accordingly. For each window I need to find the maximum value and after that I need to find the minimum value BELOW that maximum value. I start explaining it from the yellow window. For this window the max value is 3 and the min value BELOW it is 1. So that is why a_max and a_min for this window is 3 and 1. Now for the orange window the maximum value is 5 but since there are no values in this window BELOW this value that is less than 5, the previous a_max and a_min are repeated. And the logic continues for the rest of rows. This is my attempt: df['a_max'] = df.a.cummax() df['a_min'] = df.a.cummin() 

Answer: This is a tricky one, I would use a cummax+shift, then mask+ffill to compute a_max. Then a_min is the groupby.cummin per group of identical a_max: # compute the shifted cummax cm = df['a'].cummax().shift() # a_max is the cummax except if the current row is larger df['a_max'] = cm.mask(df['a'].gt(cm)).ffill() # a_min is the cummin of the current group of a_max df['a_min'] = df.groupby('a_max')['a'].cummin()  Output:  a a_max a_min 0 3 NaN NaN 1 1 3.0 1.0 2 2 3.0 1.0 3 5 3.0 1.0 4 10 3.0 1.0 5 3 10.0 3.0 6 13 10.0 3.0 7 3 13.0 3.0 8 2 13.0 2.0  Intermediates:  a a_max cummax shift mask ffill a_min 0 3 NaN 3 NaN NaN NaN NaN 1 1 3.0 3 3.0 3.0 3.0 1.0 2 2 3.0 3 3.0 3.0 3.0 1.0 3 5 3.0 5 3.0 NaN 3.0 1.0 4 10 3.0 10 5.0 NaN 3.0 1.0 5 3 10.0 10 10.0 10.0 10.0 3.0 6 13 10.0 13 10.0 NaN 10.0 3.0 7 3 13.0 13 13.0 13.0 13.0 3.0 8 2 13.0 13 13.0 13.0 13.0 2.0
Question: Using scikit-learn, I've set up a regression model to predict customers' maximum spend per transaction. The dataset I'm using looks a bit like this; the target column is maximum spend per transaction during the previous year: customer_number | metric_1 | metric_2 | target ----------------|----------|----------|------- 111 | A | X | 15 222 | A | Y | 20 333 | B | Y | 30  I split the dataset into training & testing sets, one-hot encode the features, train the model, and make some test predictions: target = pd.DataFrame(dataset, columns = ["target"]) features = dataset.drop("target", axis = 1) train_features, test_features, train_target, test_target = train_test_split(features, target, test_size = 0.25) train_features = pd.get_dummies(train_features) test_features = pd.get_dummies(test_features) model = RandomForestRegressor() model.fit(X = train_features, y = train_target) test_prediction = model.predict(X = test_features)  I can output various measures of the model's accuracy (mean average error, mean squared error etc) using the relevant functions in scikit-learn. However, I'd like to be able to tell which customers' predictions are the most inaccurate. So I want to be able to create a dataframe which looks like this: customer_number | target | prediction | error ----------------|--------|----------- |------ 111 | 15 | 17 | 2 222 | 20 | 19 | 1 333 | 30 | 50 | 20  I can use this to investigate if there is any correlation between the features and the model making inaccurate predictions. In this example, I can see that customer 333 has the biggest error by far, so I could potentially infer that customers with metric_1 = B end up with less accurate predictions. I think I can calculate errors like this (please correct me if I'm wrong on this), but I don't know how to tie them back to customer number. error = abs(test_target - test_prediction)  How can I get the desired result?

Answer: The error you are computing is the absolute error. When averaged it gives the Mean Absolute Error which is commonly used to evaluate regression models. You can read about the choice of an error metric here. This error vector is the length of your test dataset and its elements are in the same order as your records. Many people assign them back into the dataframe. Then, if you leave customer number in there, everything should line up. Starting with the DataFrame df and using idiomatic names for things: df_train, df_test = train_test_split(df) y_train, y_test = df_train["target"], df_test["target"] X_train = df_train.drop(["customer_number", "target"], axis=1) X_test = df_test.drop(["customer_number", "target"], axis=1) X_train = pd.get_dummies(X_train) X_test = pd.get_dummies(X_test) model = RandomForestRegressor() model.fit(X_train, y_train) df_test["prediction"] = model.predict(X_test) df_test["error"] = abs(df_test["target"] - df_test["prediction"])
Question: I have a pandas DataFrame: >>> f = pd.DataFrame.from_dict({"r0":{"c0":1,"c1":2},("r",1):{"c0":3,"c1":4}},orient="index") c0 c1 r0 1 2 (r, 1) 3 4  I can get the 1st row: >>> list(f.loc["r0"].items()) [('c0', 1), ('c1', 2)]  but not the second row because f.loc[("r",1)] raises KeyError. I suppose I can do >>> list(f.loc[[("r",1)]].iloc[0].items()) [('c0', 3), ('c1', 4)]  but this is unspeakably ugly. What is the right way? PS. No, I do not want to use MultiIndex here.

Answer: Try using cross-section to get values from multiple indices. list(f.xs(("r", 1)).items())
Question: Using PyQt6, I am investigating using QFileDialog directly without the use of one of the static functions (i.e. don't use QFileDialog.getOpenFileName). The issue that I am running into is creating a filter list that uses a combination of MIME types and named types. For example, say you want to set a filter for *.css and *.qss files. At there core, they are essentially the same file type, however MIME doesn't recognize *.qss. I really like the idea of using MIME types because it ensures that the many extension options of a file type are included (i.e. [*.jpg, *.jpeg, *.jpe] or [*.md, *.mkd, *.markdown]), but I also need to work with the files that are not included in MIME. The code snippet that I am working with is as follows: file_dialog = QFileDialog() file_dialog.setFileMode(QFileDialog.FileMode.ExistingFiles) file_dialog.setMimeTypeFilters(["text/css", "application/octet-stream"]) file_dialog.setNameFilter("Qt Style Sheet (*.qss)") if file_dialog.exec(): print(file_dialog.selectedFiles())  When this code executes, the .setNameFilter function completely overwrites the filters set with the .setMimeTypeFilters function. If I reverse the order of the filter setting, the same thing happens just in reverse. I have also tried adding the name filter to the MIME type list, but the name filter is just ignored. file_dialog.setMimeTypeFilters(["text/css", "Qt Style Sheet (*.qss)", "application/octet-stream"])  Anyone know of a way to have both filters without having to explicitly set all options and nix using .setMimeTypeFilters?

Answer: Combining mime-filters and name-filters is quite easy to achieve using QMimeDatabase. Doing things this way will allow you to merge glob patterns (e.g. *.qss with the css defaults), as well as getting full control over the final ordering of the filters. This won't normally be possible when using the QFileDialog methods. Below is a simple function that demonstrates the idea. The function takes a dict with mime-type/filter-name keys and glob-list values. If the function detects a mime-type, the glob-list will be merged with the built-in defaults. The return value is a list that can be passed to setNameFilters. The code logic is essentially the same as what QFileDialog itself uses, but tweaked slightly to allow greater flexibility: def combine_filters(filters): result = [] md = QMimeDatabase() for name, patterns in filters.items(): if (mt := md.mimeTypeForName(name)).isValid(): if mt.isDefault(): result.append('All Files (*)') continue name = mt.comment() patterns = sorted(mt.globPatterns() + list(patterns or ())) result.append(f'{name} ({" ".join(patterns)})') return result  Example with merge: filters = combine_filters({ 'text/css': ['*.qss'], 'application/octet-stream': None, }) print('\n'.join(filters)) # CSS stylesheet (*.css *.qss) # All Files (*)  Example without merge: filters = combine_filters({ 'text/css': None, 'Qt Style Sheet': ['*.qss'], 'application/octet-stream': None, }) print('\n'.join(filters)) # CSS stylesheet (*.css) # Qt Style Sheet (*.qss) # All Files (*)
Question: I have the following classes: class Info: data: str class Data: info: Info  When I call model_dump in Data class, pydantic will serialize the classe recursively as described here  This is the primary way of converting a model to a dictionary. Sub-models will be recursively converted to dictionaries.  Is there any way to stop the recursive part or specify how deep we want the serialisation go? My desired output would be something like the following: { "info": Info }  instead of { "info": { "data":"some data" } }  I tried to search in documentation how to change this behaviour but didn't find anything.

Answer: Converting to a dictionary solves this: >>> data = Data(info=Info(data='test')) >>> dict(data) {'info': Info(data='test')}
Question: Writing a df with a list column like so df = pl.DataFrame({'a': [1,2,3], 'b':[['A','B'], ['C', 'D'], ['E', 'F']]}) df.write_database( "test", "sqlite:///test.db", if_table_exists = "replace", )  works fine, but then running pl.read_database_uri(query="SELECT * FROM test", uri="sqlite://test.db")  gives the error RuntimeError: Invalid column type Blob at index: 1, name: b  I cannot seem to get around this by using engine_options in write_database to specify that I want a list field (not a blob), nor by using schema_overrides in the read_database_uri. What is the correct way to write/read this sort of data frame with list column(s)?

Answer: I believe that that in your case you'll need to save list of strings as BLOB in MySQL lite and later somehow decode bytes back to list. However there is two problems:  polars standard protocol connectorx can't read BLOB columns, thus you need to swith to adbc Even after switching to adbc it is not clear how to convert BLOB back to bytes.  Thus I would propose to merge list of string with any separator and store strings as VARCHAR and later convert back: import polars as pl SEP = "\t" df = pl.DataFrame({'a': [1,2,3], 'b':[['A','B'], ['C', 'D'], ['E', 'F']]}) # mapping: List[str] -> str df = df.with_columns(b = pl.col('b').list.join(SEP)) df.write_database( "test", "sqlite:///test.db", if_table_exists = "replace", ) ff = pl.read_database_uri(query="SELECT a,b FROM test", uri="sqlite://test.db", ) # mapping: str -> List[str] ff = ff.with_columns(pl.col('b').str.split(SEP))  Alternatively: Or serialize the column to json and again save it in dabase as VARCHAR - later deserialise back import json import polars as pl df = pl.DataFrame({'a': [1,2,3], 'b':[['A','B'], ['C', 'D'], ['E', 'F']]}) # dump to json f = lambda x: json.dumps(list(x)) df = df.with_columns(b = pl.col('b').apply(f)) df.write_database( "test", "sqlite:///test.db", if_table_exists = "replace", ) ff = pl.read_database_uri(query="SELECT a,b FROM test", uri="sqlite://test.db", ) ff = ff.with_columns(pl.col('b').str.json_decode())  Alternative 2: Prepare the column by converting it to binary object before saving it in sql database. Column will be saved as BLOB. import pickle import polars as pl df = pl.DataFrame({'a': [1,2,3], 'b':[['A','B'], ['C', 'D'], ['E', 'F']]}) # dump column to binary object df = df.with_columns(b = pl.col('b').apply(pickle.dumps)) df.write_database( "test", "sqlite:///test.db", if_table_exists = "replace", ) ff = pl.read_database_uri(query="SELECT a,b FROM test", uri="sqlite://test.db", engine='adbc', # need to use adbc engine instead of standard ) ff = ff.with_columns(pl.col('b').apply(pickle.loads))
Question: I have the following code. import polars as pl class Summary: def __init__(self, value: float, origin: str): self.value = value self.origin = origin def __repr__(self) -> str: return f'Summary({self.value},{self.origin})' def __mul__(self, x: float | int) -> 'Summary': return Summary(self.value * x, self.origin) def __rmul__(self, x: float | int) -> 'Summary': return self * x mapping = { 'CASH': Summary( 1, 'E'), 'ITEM': Summary(-9, 'A'), 'CHECK': Summary(46, 'A'), } df = pl.DataFrame({'quantity': [7, 4, 10], 'type': mapping.keys(), 'summary': mapping.values()})  The dataframe df looks as follows. shape: (3, 3) ┌──────────┬───────┬───────────────┐ │ quantity ┆ type ┆ summary │ │ --- ┆ --- ┆ --- │ │ i64 ┆ str ┆ object │ ╞══════════╪═══════╪═══════════════╡ │ 7 ┆ CASH ┆ Summary(1,E) │ │ 4 ┆ ITEM ┆ Summary(-9,A) │ │ 10 ┆ CHECK ┆ Summary(46,A) │ └──────────┴───────┴───────────────┘  Especially, the summary column contains a Summary class object, which supports multiplication. Now, I'd like to multiply this column with the quantity column. However, the naive approach raises an error. df.with_columns(pl.col('quantity').mul(pl.col('summary')).alias('qty_summary'))  SchemaError: failed to determine supertype of i64 and object  Is there a way to multiply these columns?

Answer: Remember that Polars is designed so that computations run in Rust, not Python, where it's like 1000x faster. If you have Python operations you want to run, you lose a lot of the benefit of using Polars in the first place. But, thankfully, Polars does have a very nice feature that is relevant here, which is “native” processing of dataclasses. import polars as pl from dataclasses import dataclass @dataclass class Summary: value: float origin: str def __mul__(self, x: float | int) -> "Summary": return Summary(self.value * x, self.origin) def __rmul__(self, x: float | int) -> "Summary": return self * x mapping = { "CASH": Summary(1, "E"), "ITEM": Summary(-9, "A"), "CHECK": Summary(46, "A"), } df = pl.DataFrame( { "quantity": [7, 4, 10], "type": mapping.keys(), "summary": mapping.values(), } ) df  Because Summary is a dataclass, you 1. don't need __init__ and __repr__ (they come for free), and 2. don't need to do anything special for Polars to struct-ify them. shape: (3, 3) ┌──────────┬───────┬────────────┐ │ quantity ┆ type ┆ summary │ │ --- ┆ --- ┆ --- │ │ i64 ┆ str ┆ struct[2] │ ╞══════════╪═══════╪════════════╡ │ 7 ┆ CASH ┆ {1.0,"E"} │ │ 4 ┆ ITEM ┆ {-9.0,"A"} │ │ 10 ┆ CHECK ┆ {46.0,"A"} │ └──────────┴───────┴────────────┘  Now you can just do regular Polars struct ops: df.with_columns( qty_summary=pl.struct( pl.col("summary").struct.field("value") * pl.col("quantity"), pl.col("summary").struct.field("origin"), ) )