121 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			121 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
import numpy as np
 | 
						|
import pytest
 | 
						|
 | 
						|
from pandas import (
 | 
						|
    DataFrame,
 | 
						|
    Series,
 | 
						|
)
 | 
						|
import pandas._testing as tm
 | 
						|
 | 
						|
 | 
						|
class TestDataFramePctChange:
 | 
						|
    @pytest.mark.parametrize(
 | 
						|
        "periods,fill_method,limit,exp",
 | 
						|
        [
 | 
						|
            (1, "ffill", None, [np.nan, np.nan, np.nan, 1, 1, 1.5, 0, 0]),
 | 
						|
            (1, "ffill", 1, [np.nan, np.nan, np.nan, 1, 1, 1.5, 0, np.nan]),
 | 
						|
            (1, "bfill", None, [np.nan, 0, 0, 1, 1, 1.5, np.nan, np.nan]),
 | 
						|
            (1, "bfill", 1, [np.nan, np.nan, 0, 1, 1, 1.5, np.nan, np.nan]),
 | 
						|
            (-1, "ffill", None, [np.nan, np.nan, -0.5, -0.5, -0.6, 0, 0, np.nan]),
 | 
						|
            (-1, "ffill", 1, [np.nan, np.nan, -0.5, -0.5, -0.6, 0, np.nan, np.nan]),
 | 
						|
            (-1, "bfill", None, [0, 0, -0.5, -0.5, -0.6, np.nan, np.nan, np.nan]),
 | 
						|
            (-1, "bfill", 1, [np.nan, 0, -0.5, -0.5, -0.6, np.nan, np.nan, np.nan]),
 | 
						|
        ],
 | 
						|
    )
 | 
						|
    @pytest.mark.parametrize("klass", [DataFrame, Series])
 | 
						|
    def test_pct_change_with_nas(self, periods, fill_method, limit, exp, klass):
 | 
						|
        vals = [np.nan, np.nan, 1, 2, 4, 10, np.nan, np.nan]
 | 
						|
        obj = klass(vals)
 | 
						|
 | 
						|
        res = obj.pct_change(periods=periods, fill_method=fill_method, limit=limit)
 | 
						|
        tm.assert_equal(res, klass(exp))
 | 
						|
 | 
						|
    def test_pct_change_numeric(self):
 | 
						|
        # GH#11150
 | 
						|
        pnl = DataFrame(
 | 
						|
            [np.arange(0, 40, 10), np.arange(0, 40, 10), np.arange(0, 40, 10)]
 | 
						|
        ).astype(np.float64)
 | 
						|
        pnl.iat[1, 0] = np.nan
 | 
						|
        pnl.iat[1, 1] = np.nan
 | 
						|
        pnl.iat[2, 3] = 60
 | 
						|
 | 
						|
        for axis in range(2):
 | 
						|
            expected = pnl.ffill(axis=axis) / pnl.ffill(axis=axis).shift(axis=axis) - 1
 | 
						|
            result = pnl.pct_change(axis=axis, fill_method="pad")
 | 
						|
 | 
						|
            tm.assert_frame_equal(result, expected)
 | 
						|
 | 
						|
    def test_pct_change(self, datetime_frame):
 | 
						|
        rs = datetime_frame.pct_change(fill_method=None)
 | 
						|
        tm.assert_frame_equal(rs, datetime_frame / datetime_frame.shift(1) - 1)
 | 
						|
 | 
						|
        rs = datetime_frame.pct_change(2)
 | 
						|
        filled = datetime_frame.fillna(method="pad")
 | 
						|
        tm.assert_frame_equal(rs, filled / filled.shift(2) - 1)
 | 
						|
 | 
						|
        rs = datetime_frame.pct_change(fill_method="bfill", limit=1)
 | 
						|
        filled = datetime_frame.fillna(method="bfill", limit=1)
 | 
						|
        tm.assert_frame_equal(rs, filled / filled.shift(1) - 1)
 | 
						|
 | 
						|
        rs = datetime_frame.pct_change(freq="5D")
 | 
						|
        filled = datetime_frame.fillna(method="pad")
 | 
						|
        tm.assert_frame_equal(
 | 
						|
            rs, (filled / filled.shift(freq="5D") - 1).reindex_like(filled)
 | 
						|
        )
 | 
						|
 | 
						|
    def test_pct_change_shift_over_nas(self):
 | 
						|
        s = Series([1.0, 1.5, np.nan, 2.5, 3.0])
 | 
						|
 | 
						|
        df = DataFrame({"a": s, "b": s})
 | 
						|
 | 
						|
        chg = df.pct_change()
 | 
						|
        expected = Series([np.nan, 0.5, 0.0, 2.5 / 1.5 - 1, 0.2])
 | 
						|
        edf = DataFrame({"a": expected, "b": expected})
 | 
						|
        tm.assert_frame_equal(chg, edf)
 | 
						|
 | 
						|
    @pytest.mark.parametrize(
 | 
						|
        "freq, periods, fill_method, limit",
 | 
						|
        [
 | 
						|
            ("5B", 5, None, None),
 | 
						|
            ("3B", 3, None, None),
 | 
						|
            ("3B", 3, "bfill", None),
 | 
						|
            ("7B", 7, "pad", 1),
 | 
						|
            ("7B", 7, "bfill", 3),
 | 
						|
            ("14B", 14, None, None),
 | 
						|
        ],
 | 
						|
    )
 | 
						|
    def test_pct_change_periods_freq(
 | 
						|
        self, datetime_frame, freq, periods, fill_method, limit
 | 
						|
    ):
 | 
						|
        # GH#7292
 | 
						|
        rs_freq = datetime_frame.pct_change(
 | 
						|
            freq=freq, fill_method=fill_method, limit=limit
 | 
						|
        )
 | 
						|
        rs_periods = datetime_frame.pct_change(
 | 
						|
            periods, fill_method=fill_method, limit=limit
 | 
						|
        )
 | 
						|
        tm.assert_frame_equal(rs_freq, rs_periods)
 | 
						|
 | 
						|
        empty_ts = DataFrame(index=datetime_frame.index, columns=datetime_frame.columns)
 | 
						|
        rs_freq = empty_ts.pct_change(freq=freq, fill_method=fill_method, limit=limit)
 | 
						|
        rs_periods = empty_ts.pct_change(periods, fill_method=fill_method, limit=limit)
 | 
						|
        tm.assert_frame_equal(rs_freq, rs_periods)
 | 
						|
 | 
						|
 | 
						|
@pytest.mark.parametrize("fill_method", ["pad", "ffill", None])
 | 
						|
def test_pct_change_with_duplicated_indices(fill_method):
 | 
						|
    # GH30463
 | 
						|
    data = DataFrame(
 | 
						|
        {0: [np.nan, 1, 2, 3, 9, 18], 1: [0, 1, np.nan, 3, 9, 18]}, index=["a", "b"] * 3
 | 
						|
    )
 | 
						|
    result = data.pct_change(fill_method=fill_method)
 | 
						|
    if fill_method is None:
 | 
						|
        second_column = [np.nan, np.inf, np.nan, np.nan, 2.0, 1.0]
 | 
						|
    else:
 | 
						|
        second_column = [np.nan, np.inf, 0.0, 2.0, 2.0, 1.0]
 | 
						|
    expected = DataFrame(
 | 
						|
        {0: [np.nan, np.nan, 1.0, 0.5, 2.0, 1.0], 1: second_column},
 | 
						|
        index=["a", "b"] * 3,
 | 
						|
    )
 | 
						|
    tm.assert_frame_equal(result, expected)
 |