Преобразование временного ряда в год до даты - PullRequest
0 голосов
/ 12 июня 2018

Допустим, я смотрю на данные по срокам погашения казначейских обязательств США .Он измеряется ежедневно, но не реально, как процентная ставка.

Я могу получить среднее геометрическое значение ставки за квартал примерно так:

import pandas as pd
from scipy.stats.mstats import gmean
# ...
tbill_quarterly = raw_tbill.resample('Q').apply(lambda x: gmean(x).item())

Как бы я получил год-актуализировать квартальную статистику по этим данным?То есть цифра в каждом квартале (для 2018: 2018-03-31, 2018-06-30, 2018-09-30, 2018-12-31), содержащая доход от начала года до квартальной даты.

Документация по передискретизации (или, действительно, StackOverflow answer , которая служит заменой несуществующей документации) предоставляет только частоты.И я не могу найти какую-то функцию на год в scipy.stats.

Ответы [ 2 ]

0 голосов
/ 12 июня 2018

Использование справки из Pandas DataFrame для групповых перекрывающихся интервалов переменной длины

import pandas as pd
import numpy as np
from scipy.stats.mstats import gmean


# Get data & format
df = pd.read_csv("...\DGS1.csv")
def convert(x):
    try:
        return float(x)
    except ValueError:
        return np.nan

# Format data
df['DATE'] = pd.to_datetime(df.DATE)
df['DGS1'] = df.DGS1.map(convert)
df = df.set_index('DATE').dropna()

# Reindex date according to @ifly6 answer
df = df.reindex(pd.date_range(df.index.min(), df.index.max(), freq='D'),method='ffill')
df = df.reset_index().rename(columns={'index': 'date'})

# Determine if the date sits inside the date interval
def year_to_quarter_groups(x):
    return pd.Series([l for l in bins if l[0] <= x <= l[1]])

# Create all the date intervals
# bins = [
#     (pd.datetime(2013, 1, 1), pd.datetime(2013, 3, 31)),  
#     (pd.datetime(2013, 1, 1), pd.datetime(2013, 6, 30)),
#     ...
# ]
dates_from_ = [[i]*4 for i in  pd.date_range('1/1/2013', end='1/1/2019', freq='AS')]
dates_from = [item for sublist in dates_from_ for item in sublist]  # flatten list
dates_to = pd.date_range('1/1/2013', end='1/1/2019', freq='Q')
bins = list(zip(dates_from, dates_to))

# Create a set of intervals that each date belongs to
# A date can belong to up to four intervals/quarters [0, 1, 2, 3]
intervals = df['date'].apply(year_to_quarter_groups).stack().reset_index(1, drop=True)

# Combine the dataframes
new = pd.concat([df, intervals], axis=1).rename(columns={0: 'year_to_quarter'}).drop('date', axis=1)

# Calculate the geometric mean
new.groupby(['year_to_quarter']).DGS1.apply(lambda x: gmean(x))

Out[]:
year_to_quarter
(2013-01-01 00:00:00, 2013-06-30 00:00:00)    0.140469
(2013-01-01 00:00:00, 2013-09-30 00:00:00)    0.125079
(2013-01-01 00:00:00, 2013-12-31 00:00:00)    0.124699
(2014-01-01 00:00:00, 2014-03-31 00:00:00)    0.119801
(2014-01-01 00:00:00, 2014-06-30 00:00:00)    0.110655
(2014-01-01 00:00:00, 2014-09-30 00:00:00)    0.109624
(2014-01-01 00:00:00, 2014-12-31 00:00:00)    0.117386
(2015-01-01 00:00:00, 2015-03-31 00:00:00)    0.222842
(2015-01-01 00:00:00, 2015-06-30 00:00:00)    0.235393
(2015-01-01 00:00:00, 2015-09-30 00:00:00)    0.267067
(2015-01-01 00:00:00, 2015-12-31 00:00:00)    0.301378
(2016-01-01 00:00:00, 2016-03-31 00:00:00)    0.574620
(2016-01-01 00:00:00, 2016-06-30 00:00:00)    0.569675
(2016-01-01 00:00:00, 2016-09-30 00:00:00)    0.564723
(2016-01-01 00:00:00, 2016-12-31 00:00:00)    0.605566
(2017-01-01 00:00:00, 2017-03-31 00:00:00)    0.882396
(2017-01-01 00:00:00, 2017-06-30 00:00:00)    0.994391
(2017-01-01 00:00:00, 2017-09-30 00:00:00)    1.071789
(2017-01-01 00:00:00, 2017-12-31 00:00:00)    1.175368
(2018-01-01 00:00:00, 2018-03-31 00:00:00)    1.935798
(2018-01-01 00:00:00, 2018-06-30 00:00:00)    2.054127
(2018-01-01 00:00:00, 2018-09-30 00:00:00)    2.054127
(2018-01-01 00:00:00, 2018-12-31 00:00:00)    2.054127
0 голосов
/ 12 июня 2018

Я ненавижу публиковать ответ на свой вопрос, но, решив проблему, я чувствую, что должен, если кто-то еще столкнется с такой проблемой.Я не гарантирую, что это самое элегантное решение.Вероятно, это не так.

Я загрузил данные из FRED (ссылка в ответе) в файл treasury-1year-rates_1980-present.csv, содержащий данные с 1979-12-31 до настоящего момента (в настоящее время 2018-06-12),Вам нужно получить данные за 1979-12-31, потому что 1980-01-01 - это NA, так как это федеральный праздник, то есть Новый год.

raw_tbill = pd.read_csv(path.join(base_dir, 'treasury-1year-rates_1980-present.csv'),
                        parse_dates=['DATE'], na_values=['.'])
raw_tbill.columns = [s.lower() for s in raw_tbill.columns.values.tolist()]
print(f'Loaded t-bill 1-year rates data, from 1980 to present, with {len(raw_tbill)} entries')

В данных FRED используется .для представления отсутствующих данных.Таким образом, включение na_values['.'], и мы также хотим, чтобы столбец даты был проанализирован, таким образом, включение параметра parse_dates.

Мне нравится все в нижнем регистре.Он хранится здесь только потому, что я не хочу менять имена всех следующих столбцов.Это настоящая боль.

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

Арифметика означает неправильно. Арифметика означает, что неправильно иметь дело с процентамиданные.Вы должны использовать геометрические средства.См. это для получения дополнительной информации.Это создает данные квартал за кварталом.

Данные на самом деле не ежедневные. В любом случае, эти данные на самом деле не ежедневные.Для решения этой проблемы и того факта, что казначейские векселя по-прежнему оплачиваются в праздничные и выходные дни, все эти выходные должны быть заполнены распространяемыми вперед данными.В противном случае геометрические средние значения будут неправильными, поскольку одно из геометрических средних предположений состоит в том, что данные равномерно распределены во времени (если только вы не взвесите их, что фактически является тем же, что я делаю здесь, но я сделал это, потому что вычисление весоввремя подумать. Это не так).

# fill in days and put in the previous applicable figure
# need to deal with gaps in data
raw_tbill.set_index('date', inplace=True)
raw_tbill.dropna(inplace=True)
tbill_data = raw_tbill.reindex(pd.date_range(raw_tbill.index.min(), raw_tbill.index.max(), freq='D'),
                               method='ffill')

Годы не завершены. После этого у меня есть годы, которые на самом деле не заполнены (например, по-видимому,1979-12-31 пусто).Их нужно удалить за бесполезность.

# drop incomplete years
count = tbill_data.set_index([tbill_data.index.year, tbill_data.index.day]).count(level=0)
years = count[count['dgs1'] >= 365].index
tbill_data['tmp_remove'] = tbill_data.apply(lambda r : 0 if r.name.year in years else 1, axis=1)
tbill_data = tbill_data[tbill_data['tmp_remove'] == 0].drop('tmp_remove', axis=1)

Отсюда, если вы следуете коду, индекс теперь равен DatetimeIndex.Таким образом, столбец даты отсутствует.

Получите квартальные индексы и рассчитайте. Теперь, технически, вам не нужно делать этот шаг.Это в моем коде, потому что я должен произвести это.Однако на этом пути обработки вы должны сделать это, просто чтобы получить индексы для каждого квартала.В противном случае ни четверти, ни сигары.

Кроме того, данные DSG1 представлены в процентах, мы не хотим их получать, если вы что-то с ними делаете, вы, вероятно, хотите их в пропорции, т.е. 100pc = 1.

# turn the daily tbill data into quarterly data
# use geometric means
tbill_data['dgs1'] = tbill_data['dgs1'] / 100
tbill_qtrly = tbill_data.resample('Q').apply(lambda x: gmean(x).item())

В любом случае я затем определяю функцию для вычисления года до даты, которая также использует геометрические средние значения для этого.Это тогда поднабор соответствующих данных на дату.Я полагаю, что год от года включает отчетную дату, оправдывающую <=.Если это на самом деле не так, прокомментируйте.

def calculate_ytd(row):
    year = row.name.year
    year_data = tbill_data[tbill_data.index.year == year]
    applicable_data = year_data[year_data.index <= row.name]
    return gmean(applicable_data['dgs1'])

tbill_qtrly['dgs1_ytd'] = tbill_qtrly.apply(lambda r : calculate_ytd(r), axis=1)

Применение этой функции производит данные.

Пост-сценарий. Можно также использовать ежеквартальногеометрическое среднее в качестве основы для расчета, если все входные переменные положительные, начиная с

equation

, где все переменные a - e положительны.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...