elixir-explorer / explorer

Series (one-dimensional) and dataframes (two-dimensional) for fast and elegant data exploration in Elixir
https://hexdocs.pm/explorer
MIT License
1.1k stars 120 forks source link

[Feature request] Add support for Decimal type #867

Open Munksgaard opened 7 months ago

Munksgaard commented 7 months ago

As per this comment I am opening this issue.

I am working with monetary data, for which floats are largely discouraged. As a result, I am using the fairly popular Decimal package and the associated Ecto support to store monetary values in my database and process them in my app.

I’m also a big fan of Livebook and Explorer to process my data. However, Explorer does not currently have support for Decimals, which means that I have to manually convert to floats, losing all the benefits of working with Decimal in the first place.

Therefore, I am wondering what it would take to add support for Decimals to Explorer and humbly requesting it for consideration.

billylanchantin commented 7 months ago

(Carrying over some of my comment as well)

Polars does support a decimal datatype:

If we want to support it as well, the tricky part will be representing things in Elixir. I see two options:

I haven't played with the Decimal datatype in Polars or Arrow, so I don't know if it maps nicely to the Decimal library's representation. But I have no objections to exploring either option (or some other thing I didn't think of).

josevalim commented 7 months ago

There is a reference here: https://arrow.apache.org/docs/r/reference/data-type.html

The implementation is straight-forward, it is stored as a large integer, which we can easily convert to Decimal using Decimal.new/3. If a list of Decimals is given as input, we will need to compute the scale, using Decimal.scale. And for precision, we can use the maximum one.

billylanchantin commented 7 months ago

👍 I think I'm comfortable adding Decimal as a dep.

@Munksgaard PRs welcome! If you're not able to, then I can take a crack when I have some time.

Munksgaard commented 7 months ago

One complication that I can see is that Decimal allows both NaN and Infinity as values, which we don't have representations for in Polars as far as I can tell.

josevalim commented 7 months ago

Yes, we should raise when encoding those. We will already have to do a prepass converting all decimals into int::128 or int::256, so we can raise on NaN and Infinity.

Munksgaard commented 7 months ago

@Munksgaard PRs welcome! If you're not able to, then I can take a crack when I have some time.

I would love to help out, but realistically I won't be able to contribute anything significant in the next couple of weeks :-(

cigrainger commented 7 months ago

I'm comfortable with Decimal as a dep as well. It doesn't carry its own deps, pretty lightweight.

billylanchantin commented 7 months ago

Rustler now supports 128 bit integers (thanks for initiating that, @Munksgaard!):

I think we can consider this issue blocked until rustler does another release. Otherwise we'd have to go off their master branch, which probably isn't worth the headache since they seem to release regularly.

LostKobrakai commented 7 months ago

Seems like this has already been released with rustler 0.32.1

philss commented 7 months ago

The update of Rustler to v0.32.1 has landed on main :)

alexpearce commented 4 months ago

I had a crack at adding Decimal support and managed to add reading without too much trouble: https://github.com/alexpearce/explorer/commit/709aa6768f4944a07126eb7ae595f449b5153346

I found adding write support more challenging. It seems that Decimal support in polars-core isn't quite as mature as for other dtypes so write support requires a bit more work.

billylanchantin commented 4 months ago

@alexpearce Feel free to open a PR. If you're still having trouble, we can discuss there why write support is more difficult.