Question: I have a Polars DataFrame containing a column with strings representing 'sparse' sector exposures, like this: df = pl.DataFrame( pl.Series("sector_exposure", [ "Technology=0.207;Financials=0.090;Health Care=0.084;Consumer Discretionary=0.069", "Financials=0.250;Health Care=0.200;Consumer Staples=0.150;Industrials=0.400" ]) )     sector_exposure     Technology=0.207;Financials=0.090;Health Care=0.084;Consumer Discretionary=0.069   Financials=0.250;Health Care=0.200;Consumer Staples=0.150;Industrials=0.400    I want to "unpack" this string into new columns for each sector (e.g., Technology, Financials, Health Care) with associated values or a polars struct with sector names as fields and exposure values. I'm looking for a more efficient solution using polars expressions only, without resorting to Python loops (or python mapped functions). Can anyone provide guidance on how to accomplish this? This is what I have come up with so far - which works in producing the desired struct but is a little slow. ( df["sector_exposure"] .str .split(";") .map_elements(lambda x: {entry.split('=')[0]: float(entry.split('=')[1]) for entry in x}, skip_nulls=True, ) )  Output: shape: (2,) Series: 'sector_exposure' [struct[6]] [ {0.207,0.09,0.084,0.069,null,null} {null,0.25,0.2,null,0.15,0.4} ]  Thanks!

Answer: There are potentially two ways to do it that I can think of. Regex extract df.with_columns(pl.col('sector_exposure').str.extract(x+r"=(\d+\.\d+)").cast(pl.Float64).alias(x) for x in ["Technology", "Financials", "Health Care", "Consumer Discretionary", "Consumer Staples","Industrials"]) shape: (2, 7) ┌────────────────┬────────────┬────────────┬─────────────┬────────────────┬──────────┬─────────────┐ │ sector_exposur ┆ Technology ┆ Financials ┆ Health Care ┆ Consumer ┆ Consumer ┆ Industrials │ │ e ┆ --- ┆ --- ┆ --- ┆ Discretionary ┆ Staples ┆ --- │ │ --- ┆ f64 ┆ f64 ┆ f64 ┆ --- ┆ --- ┆ f64 │ │ str ┆ ┆ ┆ ┆ f64 ┆ f64 ┆ │ ╞════════════════╪════════════╪════════════╪═════════════╪════════════════╪══════════╪═════════════╡ │ Technology=0.2 ┆ 0.207 ┆ 0.09 ┆ 0.084 ┆ 0.069 ┆ null ┆ null │ │ 07;Financials= ┆ ┆ ┆ ┆ ┆ ┆ │ │ 0.090;Health ┆ ┆ ┆ ┆ ┆ ┆ │ │ Care=0.084;Con ┆ ┆ ┆ ┆ ┆ ┆ │ │ sumer Discreti ┆ ┆ ┆ ┆ ┆ ┆ │ │ onary=0.069 ┆ ┆ ┆ ┆ ┆ ┆ │ │ Financials=0.2 ┆ null ┆ 0.25 ┆ 0.2 ┆ null ┆ 0.15 ┆ 0.4 │ │ 50;Health Care ┆ ┆ ┆ ┆ ┆ ┆ │ │ =0.200;Consume ┆ ┆ ┆ ┆ ┆ ┆ │ │ r Staples=0.15 ┆ ┆ ┆ ┆ ┆ ┆ │ │ 0;Industrials= ┆ ┆ ┆ ┆ ┆ ┆ │ │ 0.400 ┆ ┆ ┆ ┆ ┆ ┆ │ └────────────────┴────────────┴────────────┴─────────────┴────────────────┴──────────┴─────────────┘  In this one we're counting on all the numbers being decimal (you could tweak the regex to get around this a bit) and all the sectors being prespecified in the generator within with_columns Split and pivot ( df .with_columns(str_split=pl.col('sector_exposure').str.split(';')) .explode('str_split') .with_columns( pl.col('str_split') .str.split('=') .list.to_struct(fields=['sector','value']) ) .unnest('str_split') .pivot(values='value',index='sector_exposure',columns='sector',aggregate_function='first') .with_columns(pl.exclude('sector_exposure').cast(pl.Float64)) ) shape: (2, 7) ┌────────────────┬────────────┬────────────┬─────────────┬────────────────┬──────────┬─────────────┐ │ sector_exposur ┆ Technology ┆ Financials ┆ Health Care ┆ Consumer ┆ Consumer ┆ Industrials │ │ e ┆ --- ┆ --- ┆ --- ┆ Discretionary ┆ Staples ┆ --- │ │ --- ┆ f64 ┆ f64 ┆ f64 ┆ --- ┆ --- ┆ f64 │ │ str ┆ ┆ ┆ ┆ f64 ┆ f64 ┆ │ ╞════════════════╪════════════╪════════════╪═════════════╪════════════════╪══════════╪═════════════╡ │ Technology=0.2 ┆ 0.207 ┆ 0.09 ┆ 0.084 ┆ 0.069 ┆ null ┆ null │ │ 07;Financials= ┆ ┆ ┆ ┆ ┆ ┆ │ │ 0.090;Health ┆ ┆ ┆ ┆ ┆ ┆ │ │ Care=0.084;Con ┆ ┆ ┆ ┆ ┆ ┆ │ │ sumer Discreti ┆ ┆ ┆ ┆ ┆ ┆ │ │ onary=0.069 ┆ ┆ ┆ ┆ ┆ ┆ │ │ Financials=0.2 ┆ null ┆ 0.25 ┆ 0.2 ┆ null ┆ 0.15 ┆ 0.4 │ │ 50;Health Care ┆ ┆ ┆ ┆ ┆ ┆ │ │ =0.200;Consume ┆ ┆ ┆ ┆ ┆ ┆ │ │ r Staples=0.15 ┆ ┆ ┆ ┆ ┆ ┆ │ │ 0;Industrials= ┆ ┆ ┆ ┆ ┆ ┆ │ │ 0.400 ┆ ┆ ┆ ┆ ┆ ┆ │ └────────────────┴────────────┴────────────┴─────────────┴────────────────┴──────────┴─────────────┘  In this one you do a "round" of splitting at the semi colon and then explode. Then you split again on the equal but you turn that into a struct which you then unnest. From there you pivot the sectors up to columns. If the sectors existed in the same order then you could use str.extract_groups but with varying orders I don't think it works.