Pandas version checks

  • [X] I have checked that this issue has not already been reported.

  • [X] I have confirmed this bug exists on the latest version of pandas.

  • [ ] I have confirmed this bug exists on the main branch of pandas.

Reproducible Example

>>> data = pd.DataFrame(
        [
            ['a', 1, decimal.Decimal('1')],
            ['a', 2, decimal.Decimal('2')],
            ['b', 3, decimal.Decimal('3')],
            ['b', 4, decimal.Decimal('4')]
        ], columns=['dim', 'float', 'decimal']
    )
>>> data
  dim  float decimal
0   a      1       1
1   a      2       2
2   b      3       3
3   b      4       4
>>> # for pd.Series
>>> type(data['float'].mean())
numpy.float64
>>> type(data['decimal'].mean())
numpy.float64
>>> type(data['decimal'].sum() / len(data['decimal']))
decimal.Decimal
>>> # for DataFrame
>>> type(data.sum()['decimal'])
decimal.Decimal
>>> type(data.mean()['decimal'])
numpy.float64

Issue Description

When the mean function calculates decimal types, it produces a floating-point result, whereas the expected result should be of decimal type.

Expected Behavior

type(data['decimal'].mean()) decimal.Decimal type(data.mean()['decimal']) decimal.Decimal

Installed Versions

INSTALLED VERSIONS ------------------ commit : 2e218d10984e9919f0296931d92ea851c6a6faf5 python : 3.9.13.final.0 python-bits : 64 OS : Darwin OS-release : 22.3.0 Version : Darwin Kernel Version 22.3.0: Mon Jan 30 20:42:11 PST 2023; root:xnu-8792.81.3~2/RELEASE_X86_64 machine : x86_64 processor : i386 byteorder : little LC_ALL : None LANG : zh_CN.UTF-8 LOCALE : zh_CN.UTF-8 pandas : 1.5.3 numpy : 1.24.1 pytz : 2022.2.1 dateutil : 2.8.2 setuptools : 65.6.3 pip : 23.0.1 Cython : None pytest : None hypothesis : None sphinx : None blosc : None feather : None xlsxwriter : None lxml.etree : 4.9.1 html5lib : None pymysql : 1.0.2 psycopg2 : None jinja2 : 3.1.2 IPython : 8.9.0 pandas_datareader: None bs4 : 4.11.1 bottleneck : None brotli : None fastparquet : None fsspec : None gcsfs : None matplotlib : 3.5.2 numba : None numexpr : None odfpy : None openpyxl : 3.0.10 pandas_gbq : None pyarrow : 9.0.0 pyreadstat : None pyxlsb : None s3fs : None scipy : 1.9.1 snappy : None sqlalchemy : 2.0.0 tables : None tabulate : None xarray : None xlrd : None xlwt : None zstandard : None tzdata : None

Comment From: evgepab

take

Comment From: eirinikafourou

take

Comment From: haiyashah

take

Comment From: haiyashah

This is a corrected version of that code. We can create a custom function that converts the output of numpy.mean() to decimal.

Code:

import numpy as np
import decimal

def mean_decimal(arr):
    return decimal.Decimal(str(np.mean(arr)))

#Example usage
data = pd.DataFrame(
    [
        ['a', 1, decimal.Decimal('1')],
        ['a', 2, decimal.Decimal('2')],
        ['b', 3, decimal.Decimal('3')],
        ['b', 4, decimal.Decimal('4')]
    ], columns=['dim', 'float', 'decimal']
)

#For pd.Series
print(type(data['float'].mean()))  # numpy.float64
print(type(mean_decimal(data['decimal'])))  # decimal.Decimal

#For DataFrame
print(type(data.mean()['decimal']))  # numpy.float64
print(type(data.sum()['decimal']))  # decimal.Decimal

Explanation:

This function mean_decimal() takes an array as input and returns the mean value as a decimal.Decimal type. We convert the mean value to a string using str() and then pass it to the decimal.Decimal() constructor to ensure it's of the correct type.

We can then use this function to calculate the mean of the 'decimal' column in our DataFrame and ensure it's of type decimal.Decimal as follows:

Function:

print(type(mean_decimal(data['decimal']))) #decimal.Decimal

Comment From: rhshadrach

We currently do the computation (via NumPy object dtype) as Decimal and then convert the result to float. So if we choose to return Decimal here, I think we can do so without a performance regression.

Comment From: jbrockmendel

I'd suggest using dtype = pd.ArrowDtype(pa.decimal128(32)) here (32 is an arbitrary choice here)