Skip to content

COMPAT: frame round error msg for py310 #41301

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
May 6, 2021

Conversation

fangchenli
Copy link
Member

@fangchenli fangchenli commented May 4, 2021

Not sure if this is the desired way to address this.

________________________ TestDataFrameRound.test_round _________________________

self = <pandas.tests.frame.methods.test_round.TestDataFrameRound object at 0x7fcdd089eb90>

    def test_round(self):
        # GH#2665
    
        # Test that rounding an empty DataFrame does nothing
        df = DataFrame()
        tm.assert_frame_equal(df, df.round())
    
        # Here's the test frame we'll be working with
        df = DataFrame({"col1": [1.123, 2.123, 3.123], "col2": [1.234, 2.234, 3.234]})
    
        # Default round to integer (i.e. decimals=0)
        expected_rounded = DataFrame({"col1": [1.0, 2.0, 3.0], "col2": [1.0, 2.0, 3.0]})
        tm.assert_frame_equal(df.round(), expected_rounded)
    
        # Round with an integer
        decimals = 2
        expected_rounded = DataFrame(
            {"col1": [1.12, 2.12, 3.12], "col2": [1.23, 2.23, 3.23]}
        )
        tm.assert_frame_equal(df.round(decimals), expected_rounded)
    
        # This should also work with np.round (since np.round dispatches to
        # df.round)
        tm.assert_frame_equal(np.round(df, decimals), expected_rounded)
    
        # Round with a list
        round_list = [1, 2]
        msg = "decimals must be an integer, a dict-like or a Series"
        with pytest.raises(TypeError, match=msg):
            df.round(round_list)
    
        # Round with a dictionary
        expected_rounded = DataFrame(
            {"col1": [1.1, 2.1, 3.1], "col2": [1.23, 2.23, 3.23]}
        )
        round_dict = {"col1": 1, "col2": 2}
        tm.assert_frame_equal(df.round(round_dict), expected_rounded)
    
        # Incomplete dict
        expected_partially_rounded = DataFrame(
            {"col1": [1.123, 2.123, 3.123], "col2": [1.2, 2.2, 3.2]}
        )
        partial_round_dict = {"col2": 1}
        tm.assert_frame_equal(df.round(partial_round_dict), expected_partially_rounded)
    
        # Dict with unknown elements
        wrong_round_dict = {"col3": 2, "col2": 1}
        tm.assert_frame_equal(df.round(wrong_round_dict), expected_partially_rounded)
    
        # float input to `decimals`
        non_int_round_dict = {"col1": 1, "col2": 0.5}
        msg = "integer argument expected, got float"
        with pytest.raises(TypeError, match=msg):
>           df.round(non_int_round_dict)

pandas/tests/frame/methods/test_round.py:67: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self =     col1   col2
0  1.123  1.234
1  2.123  2.234
2  3.123  3.234
decimals = {'col1': 1, 'col2': 0.5}, args = (), kwargs = {}
concat = <function concat at 0x7fce2c668e50>
_dict_round = <function DataFrame.round.<locals>._dict_round at 0x7fcdd13728c0>

    def round(
        self, decimals: int | dict[IndexLabel, int] | Series = 0, *args, **kwargs
    ) -> DataFrame:
        """
        Round a DataFrame to a variable number of decimal places.
    
        Parameters
        ----------
        decimals : int, dict, Series
            Number of decimal places to round each column to. If an int is
            given, round each column to the same number of places.
            Otherwise dict and Series round to variable numbers of places.
            Column names should be in the keys if `decimals` is a
            dict-like, or in the index if `decimals` is a Series. Any
            columns not included in `decimals` will be left as is. Elements
            of `decimals` which are not columns of the input will be
            ignored.
        *args
            Additional keywords have no effect but might be accepted for
            compatibility with numpy.
        **kwargs
            Additional keywords have no effect but might be accepted for
            compatibility with numpy.
    
        Returns
        -------
        DataFrame
            A DataFrame with the affected columns rounded to the specified
            number of decimal places.
    
        See Also
        --------
        numpy.around : Round a numpy array to the given number of decimals.
        Series.round : Round a Series to the given number of decimals.
    
        Examples
        --------
        >>> df = pd.DataFrame([(.21, .32), (.01, .67), (.66, .03), (.21, .18)],
        ...                   columns=['dogs', 'cats'])
        >>> df
            dogs  cats
        0  0.21  0.32
        1  0.01  0.67
        2  0.66  0.03
        3  0.21  0.18
    
        By providing an integer each column is rounded to the same number
        of decimal places
    
        >>> df.round(1)
            dogs  cats
        0   0.2   0.3
        1   0.0   0.7
        2   0.7   0.0
        3   0.2   0.2
    
        With a dict, the number of places for specific columns can be
        specified with the column names as key and the number of decimal
        places as value
    
        >>> df.round({'dogs': 1, 'cats': 0})
            dogs  cats
        0   0.2   0.0
        1   0.0   1.0
        2   0.7   0.0
        3   0.2   0.0
    
        Using a Series, the number of places for specific columns can be
        specified with the column names as index and the number of
        decimal places as value
    
        >>> decimals = pd.Series([0, 1], index=['cats', 'dogs'])
        >>> df.round(decimals)
            dogs  cats
        0   0.2   0.0
        1   0.0   1.0
        2   0.7   0.0
        3   0.2   0.0
        """
        from pandas.core.reshape.concat import concat
    
        def _dict_round(df, decimals):
            for col, vals in df.items():
                try:
                    yield _series_round(vals, decimals[col])
                except KeyError:
                    yield vals
    
        def _series_round(s, decimals):
            if is_integer_dtype(s) or is_float_dtype(s):
                return s.round(decimals)
            return s
    
        nv.validate_round(args, kwargs)
    
        if isinstance(decimals, (dict, Series)):
            if isinstance(decimals, Series):
                if not decimals.index.is_unique:
                    raise ValueError("Index of decimals must be unique")
>           new_cols = list(_dict_round(self, decimals))

pandas/core/frame.py:9205: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

df =     col1   col2
0  1.123  1.234
1  2.123  2.234
2  3.123  3.234
decimals = {'col1': 1, 'col2': 0.5}

    def _dict_round(df, decimals):
        for col, vals in df.items():
            try:
>               yield _series_round(vals, decimals[col])

pandas/core/frame.py:9190: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

s = 0    1.234
1    2.234
2    3.234
Name: col2, dtype: float64, decimals = 0.5

    def _series_round(s, decimals):
        if is_integer_dtype(s) or is_float_dtype(s):
>           return s.round(decimals)

pandas/core/frame.py:9196: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = 0    1.234
1    2.234
2    3.234
Name: col2, dtype: float64
decimals = 0.5, args = (), kwargs = {}

    def round(self, decimals=0, *args, **kwargs) -> Series:
        """
        Round each value in a Series to the given number of decimals.
    
        Parameters
        ----------
        decimals : int, default 0
            Number of decimal places to round to. If decimals is negative,
            it specifies the number of positions to the left of the decimal point.
        *args, **kwargs
            Additional arguments and keywords have no effect but might be
            accepted for compatibility with NumPy.
    
        Returns
        -------
        Series
            Rounded values of the Series.
    
        See Also
        --------
        numpy.around : Round values of an np.array.
        DataFrame.round : Round values of a DataFrame.
    
        Examples
        --------
        >>> s = pd.Series([0.1, 1.3, 2.7])
        >>> s.round()
        0    0.0
        1    1.0
        2    3.0
        dtype: float64
        """
        nv.validate_round(args, kwargs)
>       result = self._values.round(decimals)
E       TypeError: 'float' object cannot be interpreted as an integer

pandas/core/series.py:2361: TypeError

During handling of the above exception, another exception occurred:

self = <pandas.tests.frame.methods.test_round.TestDataFrameRound object at 0x7fcdd089eb90>

>   ???
E   AssertionError: Regex pattern 'integer argument expected, got float' does not match "'float' object cannot be interpreted as an integer".

pandas/tests/frame/methods/test_round.py:-1: AssertionError

raise ValueError("Index of decimals must be unique")
if isinstance(decimals, Series) and not decimals.index.is_unique:
raise ValueError("Index of decimals must be unique")
if (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you check with is_dict_like and use .items() here?

@jreback jreback added this to the 1.3 milestone May 5, 2021
@jreback jreback merged commit 7b45be9 into pandas-dev:master May 6, 2021
@jreback
Copy link
Contributor

jreback commented May 6, 2021

thanks @fangchenli

JulianWgs pushed a commit to JulianWgs/pandas that referenced this pull request Jul 3, 2021
@fangchenli fangchenli deleted the round-error-msg branch November 18, 2022 02:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants