Assume the following polars df
:
┌────────────┬─────────┬────────────┬─────────┬──────────┬─────────────┐
│ gDate ┆ pl ┆ redemption ┆ pc ┆ ppc ┆ tval │
│ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │
│ date ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 │
╞════════════╪═════════╪════════════╪═════════╪══════════╪═════════════╡
│ 2024-01-30 ┆ 10069.0 ┆ 10068.0 ┆ 10068.0 ┆ 0.07 ┆ 1492.033 │
│ 2024-01-31 ┆ 10082.0 ┆ 10075.0 ┆ 10082.0 ┆ 0.14 ┆ 1236.318 │
│ 2024-02-03 ┆ 10095.0 ┆ 10095.0 ┆ 10095.0 ┆ 0.13 ┆ 2266.253 │
│ 2024-02-04 ┆ 10102.0 ┆ 10102.0 ┆ 10103.0 ┆ 0.08 ┆ 1418.583 │
│ 2024-02-05 ┆ 10110.0 ┆ 10109.0 ┆ 10109.0 ┆ 0.06 ┆ 1940.722 │
│ … ┆ … ┆ … ┆ … ┆ … ┆ … │
│ 2024-03-26 ┆ 10113.0 ┆ 10112.0 ┆ 10112.0 ┆ 0.07 ┆ 1268.171 │
│ 2024-03-27 ┆ 10126.0 ┆ 10119.0 ┆ 10126.0 ┆ 0.14 ┆ 1240.438 │
│ 2024-03-30 ┆ 10149.0 ┆ 10141.0 ┆ 10148.0 ┆ 0.22 ┆ 1317.312 │
│ 2024-04-02 ┆ 10163.0 ┆ 10162.0 ┆ 10162.0 ┆ 0.14 ┆ 1675.402 │
│ 2024-04-03 ┆ 10177.0 ┆ 10169.0 ┆ 10176.0 ┆ 0.137768 ┆ 1546.426394 │
└────────────┴─────────┴────────────┴─────────┴──────────┴─────────────┘
I want to add a value to redemption column for a specific date
. The date could be one of the existing dates, or a new one. If it is an existing date, I will just update the existing value. Otherwise, I should create a new row with the new value set and other columns set to null
.
In pandas I used to do this using df.loc[date, 'redemption'] = new_value
. In polars assigning to a non-existing row raises polars.exceptions.OutOfBoundsError: indices are out of bounds
. What is the most idiomatic way to achieve the same in polars?
My current approach:
from polars import *
from datetime import date
df = from_repr("""\
┌────────────┬─────────┬────────────┬─────────┬──────────┬─────────────┐
│ gDate ┆ pl ┆ redemption ┆ pc ┆ ppc ┆ tval │
│ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │
│ date ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 │
╞════════════╪═════════╪════════════╪═════════╪══════════╪═════════════╡
│ 2024-01-30 ┆ 10069.0 ┆ 10068.0 ┆ 10068.0 ┆ 0.07 ┆ 1492.033 │
│ 2024-01-31 ┆ 10082.0 ┆ 10075.0 ┆ 10082.0 ┆ 0.14 ┆ 1236.318 │
│ 2024-02-03 ┆ 10095.0 ┆ 10095.0 ┆ 10095.0 ┆ 0.13 ┆ 2266.253 │
│ 2024-02-04 ┆ 10102.0 ┆ 10102.0 ┆ 10103.0 ┆ 0.08 ┆ 1418.583 │
│ 2024-02-05 ┆ 10110.0 ┆ 10109.0 ┆ 10109.0 ┆ 0.06 ┆ 1940.722 │
│ … ┆ … ┆ … ┆ … ┆ … ┆ … │
│ 2024-03-26 ┆ 10113.0 ┆ 10112.0 ┆ 10112.0 ┆ 0.07 ┆ 1268.171 │
│ 2024-03-27 ┆ 10126.0 ┆ 10119.0 ┆ 10126.0 ┆ 0.14 ┆ 1240.438 │
│ 2024-03-30 ┆ 10149.0 ┆ 10141.0 ┆ 10148.0 ┆ 0.22 ┆ 1317.312 │
│ 2024-04-02 ┆ 10163.0 ┆ 10162.0 ┆ 10162.0 ┆ 0.14 ┆ 1675.402 │
│ 2024-04-03 ┆ 10177.0 ┆ 10169.0 ┆ 10176.0 ┆ 0.137768 ┆ 1546.426394 │
└────────────┴─────────┴────────────┴─────────┴──────────┴─────────────┘""")
date = date(2024, 4, 3)
new_value = 7777
df = df.join(
DataFrame([[date], [new_value]]),
left_on='gDate',
right_on='column_0',
how='outer_coalesce',
).with_columns(
when(col('column_1').is_null())
.then(col('redemption'))
.otherwise(col('column_1'))
).drop('column_1')
print(df)
.update()
is perhaps a little simpler.
df.update(
pl.select(gDate = pl.date(2024, 4, 3), redemption = 7777),
on = "gDate",
how = "outer"
)
shape: (10, 6)
┌────────────┬─────────┬────────────┬─────────┬──────────┬─────────────┐
│ gDate ┆ pl ┆ redemption ┆ pc ┆ ppc ┆ tval │
│ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │
│ date ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 │
╞════════════╪═════════╪════════════╪═════════╪══════════╪═════════════╡
│ 2024-01-30 ┆ 10069.0 ┆ 10068.0 ┆ 10068.0 ┆ 0.07 ┆ 1492.033 │
│ 2024-01-31 ┆ 10082.0 ┆ 10075.0 ┆ 10082.0 ┆ 0.14 ┆ 1236.318 │
│ 2024-02-03 ┆ 10095.0 ┆ 10095.0 ┆ 10095.0 ┆ 0.13 ┆ 2266.253 │
│ 2024-02-04 ┆ 10102.0 ┆ 10102.0 ┆ 10103.0 ┆ 0.08 ┆ 1418.583 │
│ 2024-02-05 ┆ 10110.0 ┆ 10109.0 ┆ 10109.0 ┆ 0.06 ┆ 1940.722 │
│ 2024-03-26 ┆ 10113.0 ┆ 10112.0 ┆ 10112.0 ┆ 0.07 ┆ 1268.171 │
│ 2024-03-27 ┆ 10126.0 ┆ 10119.0 ┆ 10126.0 ┆ 0.14 ┆ 1240.438 │
│ 2024-03-30 ┆ 10149.0 ┆ 10141.0 ┆ 10148.0 ┆ 0.22 ┆ 1317.312 │
│ 2024-04-02 ┆ 10163.0 ┆ 10162.0 ┆ 10162.0 ┆ 0.14 ┆ 1675.402 │
│ 2024-04-03 ┆ 10177.0 ┆ 7777.0 ┆ 10176.0 ┆ 0.137768 ┆ 1546.426394 │
└────────────┴─────────┴────────────┴─────────┴──────────┴─────────────┘
how='outer' will update existing rows where the key matches while also adding any new rows contained in the given frame
df.update(
pl.select(gDate = pl.date(2028, 4, 3), redemption = 7777),
on = "gDate",
how = "outer"
)
shape: (11, 6)
┌────────────┬─────────┬────────────┬─────────┬──────────┬─────────────┐
│ gDate ┆ pl ┆ redemption ┆ pc ┆ ppc ┆ tval │
│ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │
│ date ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 │
╞════════════╪═════════╪════════════╪═════════╪══════════╪═════════════╡
│ 2024-01-30 ┆ 10069.0 ┆ 10068.0 ┆ 10068.0 ┆ 0.07 ┆ 1492.033 │
│ 2024-01-31 ┆ 10082.0 ┆ 10075.0 ┆ 10082.0 ┆ 0.14 ┆ 1236.318 │
│ 2024-02-03 ┆ 10095.0 ┆ 10095.0 ┆ 10095.0 ┆ 0.13 ┆ 2266.253 │
│ 2024-02-04 ┆ 10102.0 ┆ 10102.0 ┆ 10103.0 ┆ 0.08 ┆ 1418.583 │
│ 2024-02-05 ┆ 10110.0 ┆ 10109.0 ┆ 10109.0 ┆ 0.06 ┆ 1940.722 │
│ … ┆ … ┆ … ┆ … ┆ … ┆ … │
│ 2024-03-27 ┆ 10126.0 ┆ 10119.0 ┆ 10126.0 ┆ 0.14 ┆ 1240.438 │
│ 2024-03-30 ┆ 10149.0 ┆ 10141.0 ┆ 10148.0 ┆ 0.22 ┆ 1317.312 │
│ 2024-04-02 ┆ 10163.0 ┆ 10162.0 ┆ 10162.0 ┆ 0.14 ┆ 1675.402 │
│ 2024-04-03 ┆ 10177.0 ┆ 10169.0 ┆ 10176.0 ┆ 0.137768 ┆ 1546.426394 │
│ 2028-04-03 ┆ null ┆ 7777.0 ┆ null ┆ null ┆ null │
└────────────┴─────────┴────────────┴─────────┴──────────┴─────────────┘