让我们说我正在看US Treasury bill maturity data。它每天测量,但不是每天测量的百分比。
我可以得到四分之一速率的几何平均值:
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)的数字持有从年初到季度的回报。 / p>
重采样文档(或实际上,StackOverflow answer用作替换不存在的文档)仅提供频率。而我似乎无法在scipy.stats
中找到某种年初至今的功能。
答案 0 :(得分:0)
我讨厌回答我自己的问题,但是解决了这个问题后,我觉得我应该,如果其他人遇到这样的问题。我不保证这是最优雅的解决方案。它可能不是。
我将数据从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
参数。
我碰巧想把一切都放在小写字母中。它只保留在这里,因为我不想更改以下所有列名称。这真的很痛苦。
首先要避开两种误解,或者先解决问题。
算术意味着错误。算术方法对于处理百分比数据是错误的。你应该使用几何手段。有关详细说明,请参阅this。这会创建逐季度数据。
数据实际上并非每天。无论如何,这些数据实际上并非每天都有。为了解决这个问题,以及国库券仍然在节假日和周末支付的事实,所有这些周末都需要填充前向传播的数据。否则,几何平均值将是错误的,因为几何平均假设之一是数据在时间上均匀间隔(除非你加权它们,这实际上与我在这里做的相同,但我这样做是因为计算权重需要时间思考。这不是。
# 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数据是百分之百,我们不想要那些,如果你正在做任何事情,你可能想要它的比例,即100 pc = 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)
该功能的应用产生数据。
后脚本。如果所有输入变量都是正数,那么也可以使用季度几何平均值作为计算基础,因为
所有变量 a 到 e 都是正面的。
答案 1 :(得分:0)
使用Pandas DataFrame groupby overlapping intervals of variable length
的帮助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