Polars DataFrame — десятичная точность удваивается при использовании целого числа

У меня есть фрейм данных Polars (v1.5.0) с 4 столбцами, как показано в примере ниже. Когда я умножаю десятичные столбцы на целочисленные, масштаб полученного десятичного столбца удваивается.

from decimal import Decimal
import polars as pl

df = pl.DataFrame({
    "a": [1, 2],
    "b": [Decimal('3.45'), Decimal('4.73')],
    "c": [Decimal('2.113'), Decimal('4.213')],
    "d": [Decimal('1.10'), Decimal('3.01')]
})
shape: (2, 4)
┌─────┬──────────────┬──────────────┬──────────────┐
│ a   ┆ b            ┆ c            ┆ d            │
│ --- ┆ ---          ┆ ---          ┆ ---          │
│ i64 ┆ decimal[*,2] ┆ decimal[*,3] ┆ decimal[*,2] │
╞═════╪══════════════╪══════════════╪══════════════╡
│ 1   ┆ 3.45         ┆ 2.113        ┆ 1.10         │
│ 2   ┆ 4.73         ┆ 4.213        ┆ 3.01         │
└─────┴──────────────┴──────────────┴──────────────┘
df.with_columns(pl.col("c", "d").mul(pl.col("a")))
shape: (2, 4)
┌─────┬──────────────┬──────────────┬──────────────┐
│ a   ┆ b            ┆ c            ┆ d            │
│ --- ┆ ---          ┆ ---          ┆ ---          │
│ i64 ┆ decimal[*,2] ┆ decimal[*,6] ┆ decimal[*,4] │
╞═════╪══════════════╪══════════════╪══════════════╡
│ 1   ┆ 3.45         ┆ 2.113000     ┆ 1.1000       │
│ 2   ┆ 4.73         ┆ 8.426000     ┆ 6.0200       │
└─────┴──────────────┴──────────────┴──────────────┘

Я не знаю, почему масштаб удваивается, когда я просто умножаю десятичную дробь на целое число. Что делать, чтобы масштаб не менялся?

Можете ли вы предоставить минимально воспроизводимый пример ?

mozway 23.08.2024 09:43

Я обновил вопрос с помощью рабочего примера.

fishfin 23.08.2024 10:01

Это обычные правила десятичного умножения — см., например, mathsteacher.com.au/year7/ch06_decimals/09_mult_dec/dec.htm. если вы умножите 0,01 * 0,01, вы получите 0,0001, и вам придется увеличить точность.

Roman Pekar 23.08.2024 10:01

Но я умножаю целое число на десятичное, а не десятичное на десятичное.

fishfin 23.08.2024 10:03

ах, я пропустил это

Roman Pekar 23.08.2024 10:05
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
4
5
50
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Пока это не учтено в определении pl.Expr.mul десятичных дробей, вы можете вернуться к желаемому масштабу следующим образом. Тем не менее, само умножение выполняется с более высокой точностью.

df.with_columns(
    pl.col(col).mul(pl.col("a")).cast(df.schema[col])
    for col in ["c", "d"]
)
shape: (2, 4)
┌─────┬──────────────┬──────────────┬──────────────┐
│ a   ┆ b            ┆ c            ┆ d            │
│ --- ┆ ---          ┆ ---          ┆ ---          │
│ i64 ┆ decimal[*,2] ┆ decimal[*,3] ┆ decimal[*,2] │
╞═════╪══════════════╪══════════════╪══════════════╡
│ 1   ┆ 3.45         ┆ 2.113        ┆ 1.10         │
│ 2   ┆ 4.73         ┆ 8.426        ┆ 6.02         │
└─────┴──────────────┴──────────────┴──────────────┘
Ответ принят как подходящий

Кажется, что масштаб действительно увеличился вдвое. Вы можете привести обратно к исходному типу dtype:

cols = ['c', 'd', 'e']
df.with_columns(pl.col(c).mul(pl.col('a')).cast(df[c].dtype) for c in cols)

Обратите внимание, что в настоящее время, похоже, не существует способа доступа к dtype в Expr, но это обсуждаемая функция.

Пример:

┌─────┬─────┬──────────────┬──────────────┬──────────────┐
│ a   ┆ b   ┆ c            ┆ d            ┆ e            │
│ --- ┆ --- ┆ ---          ┆ ---          ┆ ---          │
│ i64 ┆ i64 ┆ decimal[*,2] ┆ decimal[*,3] ┆ decimal[*,4] │
╞═════╪═════╪══════════════╪══════════════╪══════════════╡
│ 1   ┆ 3   ┆ 2.11         ┆ 1.100        ┆ 1.1001       │
│ 2   ┆ 4   ┆ 8.42         ┆ 6.022        ┆ 6.0004       │
└─────┴─────┴──────────────┴──────────────┴──────────────┘

Используемый вход:

from decimal import Decimal
df = pl.DataFrame({
    "a": [1, 2],
    "b": [3, 4],
    "c": [Decimal('2.11'), Decimal('4.21')],
    "d": [Decimal('1.10'), Decimal('3.011')],
    "e": [Decimal('1.1001'), Decimal('3.0002')],
})

Другие вопросы по теме