Given a dataframe containing strings, how can I use the second dataframe to grab slices from the first as new columns?
df_strs = pl.DataFrame({
"Col_A": ["AAABBCCCC", "DDDEEFFFF"],
"Col_B": ["AAB", "DDE"]
})
print(df_strs)
df_offsets = pl.DataFrame({
"Reference_Col": ["Col_A", "Col_A", "Col_A", "Col_B", "Col_B"],
"Offset": [0, 3, 5, 0, 2],
"Length": [3, 2, 4, 2, 1],
"Alias": ["Col_A_1", "Col_A_2", "Col_A_3", "Col_B_1", "Col_B_2"]
})
print(df_offsets)
Output:
df_strs
shape: (2, 2)
┌───────────┬───────┐
│ Col_A ┆ Col_B │
│ --- ┆ --- │
│ str ┆ str │
╞═══════════╪═══════╡
│ AAABBCCCC ┆ AAB │
├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┤
│ DDDEEFFFF ┆ DDE │
└───────────┴───────┘
df_offsets
shape: (5, 4)
┌───────────────┬────────┬────────┬─────────┐
│ Reference_Col ┆ Offset ┆ Length ┆ Alias │
│ --- ┆ --- ┆ --- ┆ --- │
│ str ┆ i64 ┆ i64 ┆ str │
╞═══════════════╪════════╪════════╪═════════╡
│ Col_A ┆ 0 ┆ 3 ┆ Col_A_1 │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
│ Col_A ┆ 3 ┆ 2 ┆ Col_A_2 │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
│ Col_A ┆ 5 ┆ 4 ┆ Col_A_3 │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
│ Col_B ┆ 0 ┆ 2 ┆ Col_B_1 │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
│ Col_B ┆ 2 ┆ 1 ┆ Col_B_2 │
└───────────────┴────────┴────────┴─────────┘
So that the resulting dataframe has five columns, where each column is reference[offset:offset+length] with name defined by alias?
in the above example, the result would be:
shape: (5, 4)
┌─────────┬─────────┬─────────┬─────────┬─────────┐
│ Col_A_1 ┆ Col_A_2 ┆ Col_A_3 ┆ Col_B_1 ┆ Col_B_2 │
│ --- ┆ --- ┆ --- ┆ --- ┆ --- │
│ str ┆ str ┆ str ┆ str ┆ str │
╞═════════╪═════════╪═════════╪═════════╪═════════╡
│ AAA ┆ BB ┆ CCCC ┆ AA ┆ B │
├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
│ DDD ┆ EE ┆ FFFF ┆ DD ┆ E │
└─────────┴─────────┴─────────┴─────────┴─────────┘
I can do this using loops, but I feel there must be a more idiomatic way to use polars. My current solution is:
df_offsets = df_offsets.transpose() # this converts our ints to strs
for s in df_offsets:
df_strs = df_strs.with_column(
pl.col(s[0]).str.slice(int(s[1]), int(s[2])).alias(s[3])
)
Output:
>>>print(df_strs)
shape: (2, 7)
┌───────────┬───────┬─────────┬─────────┬─────────┬─────────┬─────────┐
│ Col_A ┆ Col_B ┆ Col_A_0 ┆ Col_A_1 ┆ Col_A_2 ┆ Col_B_0 ┆ Col_B_1 │
│ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │
│ str ┆ str ┆ str ┆ str ┆ str ┆ str ┆ str │
╞═══════════╪═══════╪═════════╪═════════╪═════════╪═════════╪═════════╡
│ AAABBCCCC ┆ AAB ┆ AAA ┆ BB ┆ CCCC ┆ AA ┆ B │
├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
│ DDDEEFFFF ┆ DDE ┆ DDD ┆ EE ┆ FFFF ┆ DD ┆ E │
└───────────┴───────┴─────────┴─────────┴─────────┴─────────┴─────────┘
Is there a more optimized way of doing this?