Процентное изменение панд на основе значения предыдущего столбца, определенного datetime - PullRequest
0 голосов
/ 09 июня 2019

Я хотел бы рассчитать годовой (2) и 3-летний годовой рост дивидендов (среднее геометрическое значение) в каждой группе «тикеров» в нижеприведенном фрейме данных, где рост всегда относительно последнего временипериод в каждой группе.

У меня есть:

   ticker        date  dividends
0       A   3/31/2019       0.63
1       A   3/31/2018       0.56
2       A   3/31/2017       0.49
3       A   3/31/2016       0.43
4       A   3/31/2015      16.13
5       A   3/31/2014       0.50
6     AAU  12/31/2018          0
7     AAU  12/31/2017          0
8     AAU  12/31/2016          0
9     AAU  12/31/2015          0
10    AAU  12/31/2014          0
11     AB   3/31/2019       2.68
12     AB   3/31/2018       2.30
13     AB   3/31/2017       1.92
14     AB   3/31/2016       1.86
15     AB   3/31/2015       1.86
16     AB   3/31/2014       1.79
17   ADIL   3/31/2019          0
18   ADIL   3/31/2018          0

Используя руководство, данное @ anky_91 в комментарии ниже:

df2 = df1.assign(div_1yr_cagr=df1.sort_values(['ticker', 'date']).dividends.pct_change(periods=1,
                 div_2yr_cagr=pow(df1.sort_values(['ticker', 'date']).dividends.pct_change(periods=2) + 1, 0.5) - 1,
                 div_3yr_cagr=pow(df1.sort_values(['ticker', 'date']).dividends.pct_change(periods=3) + 1, 0.3333) - 1)

С этим я 'мы получили ниже.Проблема в группах тикеров, где данные менее чем за 3 года, вышеприведенный код заполняет ячейки -1,0, и я хотел бы вместо этого оценить их как NaN (например, когда дивиденды равны нулю).Кроме того, я забочусь только о росте по отношению к самой последней дате в каждой группе, так есть ли способ Pythonic, где статистика роста не рассчитывается в каждой группе для дат, предшествующих самой последней?

Я получил:

   ticker        date  dividends  div_1yr_cagr  div_2yr_cagr  div_3yr_cagr
0       A   3/31/2019      0.626      0.113879      0.267206      0.455814
1       A   3/31/2018      0.562      0.137652      0.306977     -0.965158
2       A   3/31/2017      0.494      0.148837     -0.969374     -0.019841
3       A   3/31/2016      0.430     -0.973342     -0.146825           NaN
4       A   3/31/2015     16.130     31.003968           NaN           NaN
5       A   3/31/2014      0.504           NaN           NaN           NaN
6     AAU  12/31/2018      0.000           NaN           NaN           NaN
7     AAU  12/31/2017      0.000           NaN           NaN           NaN
8     AAU  12/31/2016      0.000           NaN           NaN     -1.000000
9     AAU  12/31/2015      0.000           NaN     -1.000000     -1.000000
10    AAU  12/31/2014      0.000     -1.000000     -1.000000     -1.000000
11     AB   3/31/2019      2.680      0.165217      0.395833      0.440860
12     AB   3/31/2018      2.300      0.197917      0.236559      0.236559
13     AB   3/31/2017      1.920      0.032258      0.032258      0.072626
14     AB   3/31/2016      1.860      0.000000      0.039106           inf
15     AB   3/31/2015      1.860      0.039106           inf           inf
16     AB   3/31/2014      1.790           inf           inf           inf
17   ADIL   3/31/2019      0.000           NaN     -1.000000     -1.000000
18   ADIL   3/31/2018      0.000     -1.000000     -1.000000     -1.000000

Но хотел бы:

   ticker        date  dividends  div_1yr_cagr  div_2yr_cagr  div_3yr_cagr
0       A   3/31/2019      0.626      0.113879      0.267206      0.455814
1       A   3/31/2018      0.562           NaN           NaN           NaN
2       A   3/31/2017      0.494           NaN           NaN           NaN
3       A   3/31/2016      0.430           NaN           NaN           NaN
4       A   3/31/2015     16.130           NaN           NaN           NaN
5       A   3/31/2014      0.504           NaN           NaN           NaN
6     AAU  12/31/2018      0.000           NaN           NaN           NaN
7     AAU  12/31/2017      0.000           NaN           NaN           NaN
8     AAU  12/31/2016      0.000           NaN           NaN           NaN
9     AAU  12/31/2015      0.000           NaN           NaN           NaN
10    AAU  12/31/2014      0.000           NaN           NaN           NaN
11     AB   3/31/2019      2.680      0.165217      0.395833      0.440860
12     AB   3/31/2018      2.300           NaN           NaN           NaN
13     AB   3/31/2017      1.920           NaN           NaN           NaN
14     AB   3/31/2016      1.860           NaN           NaN           NaN
15     AB   3/31/2015      1.860           NaN           NaN           NaN
16     AB   3/31/2014      1.790           NaN           NaN           NaN
17   ADIL   3/31/2019      0.000           NaN           NaN           NaN
18   ADIL   3/31/2018      0.000           NaN           NaN           NaN

Спасибо!

1 Ответ

1 голос
/ 10 июня 2019

Это решение, которое рассчитывает только то, что вас волнует. Он основан на предположении, что для каждого тикера существует ровно одна строка для каждого года.

df.sort_values(by=["ticker", "date"], ascending=[True, False], inplace=True)

# Find date, dividends, and index of the most recent record for each ticker
# and populate result to the entire dataframe
df["index"] = df.index
df[["rec_date", "rec_div", "rec_idx"]] = df.groupby("ticker").transform("first")
df["offset"] = df["rec_date"].dt.year - df["date"].dt.year   # Compute time offset by year

# Copy relevant rows and columns into a new dataframe for further computation
mdf = df.loc[df["offset"].between(1, 3), ["dividends", "rec_div", "offset", "rec_idx"]].copy()

# Compute annualized growth and organize result into desired format
mdf["cagr"] = (mdf["rec_div"] / mdf["dividends"]).pow(1 / mdf["offset"]) - 1
cagr_df = mdf.pivot(index="rec_idx", columns="offset", values="cagr")
cagr_df.columns = ["div_{}yr_cagr".format(i) for i in cagr_df.columns]

# Merge the calculated numbers with original df to get desired output
result_df = df[["ticker", "date", "dividends"]].join(cagr_df)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...