
目录
一、概念解释
1.1 同比
同比增长计算公式:
同
比
增
长
率
=
(
本
期
数
-
同
期
数
)
÷
同
期
数
×
100
同比增长率=(本期数-同期数)÷同期数×100%
同比增长率=(本期数-同期数)÷同期数×100
例子:
比如说去年3月的产值100万,本年3月的产值300万,同比增长是怎么算的?是同比增长200%?还是同比增长300%?
本题中,同比增长率=(300-100)÷100=200%
同比增长率,一般是指和同期相比较的增长率。
某个指标的同比增长=(某个指标的值-同期这个指标的值)/同期这个指标的值
当同期数为负值的情况,公式应当完善如下:
同
比
增
长
率
=
(
本
期
数
-
同
期
数
)
÷
∣
同
期
数
∣
×
100
同比增长率=(本期数-同期数)÷ |同期数|×100%
同比增长率=(本期数-同期数)÷∣同期数∣×100
同比增长率=(50W-(-100W))/|-100W||×100%=150%
1.2 环比
环比计算公式:
环
比
增
长
率
=
(
本
期
数
−
上
期
数
)
/
上
期
数
×
100
环比增长率=(本期数-上期数)/上期数×100%
环比增长率=(本期数−上期数)/上期数×100
环比,表示连续2个统计周期(比如连续两月)内的量的变化比。
反映本期比上期增长了多少。”补充:
环比有 环比增长速度 和 环比发展速度 两种方法。
环比即与上期的数量作比较。
- 环比增长速度=(本期数-上期数)÷上期数×100%
反映本期比上期增长了多少。- 环比发展速度=本期数÷上期数×100%
环比发展速度是报告期水平与前一期水平之比,反映现象在前后两期的发展变化情况例如:
如:本期销售额为500万,上期销售额为350万。
环比增长速度=(500-350)÷350×100%=42.86%
环比发展速度=500÷350×100%=142.86%
环比增长速度= 环比发展速度-1。
1.3 占比
占比计算公式:
占
比
=
所
求
占
比
例
数
值
÷
总
数
值
×
100
占比 = 所求占比例数值 ÷ 总数值×100%
占比=所求占比例数值÷总数值×100
例如:
一部门总人数为250个,缺勤人数为8个,缺勤率是8/250=0.032。
占比是一个总体中各个部分的数量占总体数量的比重,用于反映总体的构成或者结构。
1.4 贡献率
贡献率计算公式:
贡
献
率
=
某
因
素
增
加
量
(
增
量
或
增
长
程
度
)
/
总
增
加
量
(
总
增
量
或
增
长
程
度
)
×
100
贡献率=某因素增加量(增量或增长程度)/总增加量(总增量或增长程度)×100%
贡献率=某因素增加量(增量或增长程度)/总增加量(总增量或增长程度)×100
上式实际上是指某因素的增长量(程度)占总增长量(程度)的比重。
贡献率常用于分析经济增长中各因素作用大小的程度。
例如:
2009年广东省生产总值39081.59亿元,比上年增长9.5%。其中,第一产业产值2006.02亿元,增长4.9%;第二产业产值19270.48亿元,增长8.7%;第三产业产值17805.09亿元,增长11.0%。那么三大产业对广东省GDP的贡献率是多少?
广东省GDP增长总额=39081.59-39081.59/(1+9.5%)=3390.05(亿元)
第一产业增长总额=2006.02-2006.02/(1+4.9%)=93.70(亿元),贡献率=93.70/3390.05=2.76%
第二产业增长总额=19270-19270/(1+8.7%)=1542.31(亿元),贡献率=1542.31/3390.05=45.50%
第三产业增长总额=17805.09-17805/(1+11.0%)=1764.46(亿元),贡献率=1764.46/3390.05=52.05%
1.5 拉动率
拉动率计算公式:
拉
动
增
长
率
=
(
某
值
今
年
量
−
某
值
去
年
量
)
/
总
值
的
去
年
量
∗
100
拉动增长率=(某值今年量-某值去年量) / 总值的去年量*100%
拉动增长率=(某值今年量−某值去年量)/总值的去年量∗100
拉动率 指现期某部分的增加值/总体的基期值,即部分量的增长对总量增长的一个贡献。
例如:
全省重工业今年产值=4935
全省重工业去年产值=3993
全省重工业较去年的增长=4935-3993=942
全省今年总产值=7334 亿元
全省去年总产值=6021 亿元
全省较去年去年总产值增长 = 7334 - 6021
重工业:
- 拉动率 =全省重工业较去年的增长 / 全省去年总产值 *100%
- 贡献率 = 全省重工业较去年的增长 / 全省较去年去年总产值增长 * 100%
二、python实现
2.1 同比实现
因为 同比 和 环比 的计算,都是对一个指标数据本身的计算,因此可以用同一个函数来实现。
备注:
类似的,同比 也存在这种环比补充说明的情况,本文均以 增长速度 进行 计算实现。
# 同比计算函数
def yearOnYear(temp_data,zhibiao_freq):
'''
temp_data,要计算的原始数据序列
zhibiao_freq,指标更新频率
'''
result = [] # 存放计算结果(嵌套列表)
# 判断指标的加工周期
if zhibiao_freq == '年':
rel_delta = relativedelta(years=1)
if zhibiao_freq == '季':
rel_delta = relativedelta(months=3)
if zhibiao_freq == '月':
rel_delta = relativedelta(months=1)
# 起止日期时间
min_riqi = min(temp_data.index)
max_riqi = max(temp_data.index)
# 对范围内日期数据进行同比加工计算,单位(%)
flag_riqi = min_riqi
tongbi_delta = relativedelta(years=1)
# 同比计算
while flag_riqi <= max_riqi-tongbi_delta:
temp_riqi = flag_riqi+tongbi_delta
# 当期值
try:
dangqi = float(temp_data.loc[temp_riqi])
except:
dangqi = None
# 上期值
try:
shangqi =float( temp_data.loc[flag_riqi])
except:
shangqi = None
if dangqi and shangqi:
value = format((dangqi - shangqi)/ abs(shangqi) *100,'.2f')
else:
value = None
result.append([temp_riqi,value]) # 指标结果
flag_riqi = flag_riqi+rel_delta # 更新日期
result = pd.DataFrame(result,columns=['日期','指标值'])
result = result.set_index('日期')
return result
2.2 环比实现
# 环比计算函数
def monthOnMonth(temp_data,zhibiao_freq):
'''
temp_data,要计算的原始数据序列
zhibiao_freq,指标更新频率
'''
result = [] # 存放计算结果(嵌套列表)
# 判断指标的加工周期
if zhibiao_freq == '年':
rel_delta = relativedelta(years=1)
if zhibiao_freq == '季':
rel_delta = relativedelta(months=3)
if zhibiao_freq == '月':
rel_delta = relativedelta(months=1)
# 起止日期时间
min_riqi = min(temp_data.index)
max_riqi = max(temp_data.index)
# 对范围内日期数据进行同比加工计算,单位(%)
flag_riqi = min_riqi
# 环比计算
while flag_riqi < max_riqi:
temp_riqi = flag_riqi+rel_delta
# 当期值
try:
dangqi = temp_data.loc[temp_riqi]
except:
dangqi = None
# 上期值
try:
shangqi = temp_data.loc[flag_riqi]
except:
shangqi = None
if dangqi and shangqi:
value = format(str((dangqi - shangqi)/ abs(shangqi)) *100,'.2f')
else:
value = None
result.append([temp_riqi,value]) # 指标结果
flag_riqi = flag_riqi+rel_delta # 更新日期
result = pd.DataFrame(result,columns=['日期','指标值'])
result = result.set_index('日期')
return result
2.3 累计值 获得 当期值
# 当期值函数
def currentPeriod(temp_data,zhibiao_freq):
'''
temp_data,要计算的原始数据序列
zhibiao_freq,指标更新频率
'''
result = [] # 存放计算结果(嵌套列表)
# 判断指标的加工周期
if zhibiao_freq == '年':
rel_delta = relativedelta(years=1)
if zhibiao_freq == '季':
rel_delta = relativedelta(months=3)
if zhibiao_freq == '月':
rel_delta = relativedelta(months=1)
# 起止日期时间
min_riqi = min(temp_data.index)
max_riqi = max(temp_data.index)
# 对范围内日期数据进行同比加工计算,单位(%)
flag_riqi = min_riqi
while flag_riqi < max_riqi:
temp_riqi = flag_riqi+rel_delta
# 当期值
try:
# dangqi = temp_data['index_val'][temp_riqi]
dangqi = float(temp_data.loc[temp_riqi])
except:
dangqi = None
# 上期值
try:
# shangqi = temp_data['index_val'][flag_riqi]
shangqi = float(temp_data.loc[flag_riqi])
except:
shangqi = None
if (temp_riqi.month)==1 and dangqi:
value = format(dangqi,'.2f')
elif dangqi and shangqi:
value = format((dangqi - shangqi),'.2f')
else:
value = None
#result.append([temp_riqi,zhibiao_code,yuanxing_name,value,zhibiao_freq]) # 指标结果
result.append([temp_riqi,value]) # 指标结果
flag_riqi = temp_riqi # 更新日期
result = pd.DataFrame(result,columns=['日期','指标值'])
result = result.set_index('日期')
return result
2.4 当期值 计算 累计值
# 当月值计算月度累计值,季度值计算季度累计值(季度累计值暂时未编码)
def monthToMonthAddUp(temp_data,zhibiao_freq):
'''
temp_data,要计算的原始数据序列
zhibiao_freq,指标更新频率
'''
result = temp_data.copy()
# 判断指标的加工周期
if zhibiao_freq == '年':
rel_delta = relativedelta(years=1)
if zhibiao_freq == '季':
rel_delta = relativedelta(months=3)
if zhibiao_freq == '月':
rel_delta = relativedelta(months=1)
min_riqi = min(temp_data.index)
max_riqi = max(temp_data.index)
# num = 0 # 数据加工对应的位置
for year in range(min_riqi.year,max_riqi.year+1):
temp = temp_data.loc[str(year)]
count = 0 # 判断月份数据是否匹配和完整标志
if zhibiao_freq == "月":
for y in temp.index:
if y.month != count+1 or any(temp.loc[y].isnull()) :
print('缺失的时间数据:',y)
temp.iloc[count:max(temp.index).month] = None
break
else:
temp.iloc[count] = round(sum(temp.iloc[:y.month]),2)
count += 1
result.loc[str(year)] = temp
if zhibiao_freq == "季":
print("请进行程序设计!")
result = pd.DataFrame(result)
result.columns = ['指标值']
result.index.name = '日期'
return result
···
### 2.5 移动均值
```python
# 移动均值 函数
def moveAverage(temp_data,zhibiao_freq,move_num):
'''
temp_data,序列
zhibiao_freq,指标加工频率
move_num,移动均值计算的期数
'''
move_num = move_num -1
result =[] # 存放计算结果(嵌套列表)
# 判断指标的加工周期
if zhibiao_freq == '年':
rel_delta_move = relativedelta(years=move_num)
rel_delta = relativedelta(years=1)
if zhibiao_freq == '季':
rel_delta_move = relativedelta(months=3*move_num)
rel_delta = relativedelta(months=3)
if zhibiao_freq == '月':
rel_delta_move = relativedelta(months=move_num)
rel_delta = relativedelta(months=1)
# 起止日期时间
min_riqi = min(temp_data.index)
max_riqi = max(temp_data.index)
# 对范围内日期数据进行移动均值计算
flag_riqi = min_riqi
flag_que = False # 是否确实数据,默认False
while flag_riqi <= max_riqi-rel_delta_move:
temp_riqi = flag_riqi + rel_delta_move
temp = temp_data.loc[flag_riqi:temp_riqi]
if any(temp.isnull()) or len(temp) != move_num+1:
flag_que = True # 存在确实数据
#print("日期段存在缺失数据",flag_riqi,temp_riqi)
result.append([temp_riqi,None])
else:
fenzi_list = [float(i) for i in temp]
result.append([temp_riqi,round(sum(fenzi_list)/move_num,2)])
flag_riqi += rel_delta
if flag_que:
print("指标存在缺失数据")
result = pd.DataFrame(result,columns = ["日期","指标值"])
result = result.set_index('日期')
return result
2.6 月度累计值 计算 当季值
# 月度累计值 计算 当季值
def monthaddupToSeason(temp_data):
'''
temp_data,要计算的原始数据序列
'''
result = [] # 存放加工处理结果
min_riqi = min(temp_data.index)
max_riqi = max(temp_data.index)
rel_delta = relativedelta(months=3) # 日期间隔
# 开始标记日期进行设定
while min_riqi.month not in [3,6,9,12]:
min_riqi = min_riqi + relativedelta(months=1)
# 对范围内日期数据进行处理
flag_riqi = min_riqi
while flag_riqi < max_riqi:
temp_riqi = flag_riqi+rel_delta
# 当期值
try:
# dangqi = temp_data['index_val'][temp_riqi]
dangqi = float(temp_data.loc[temp_riqi])
except:
dangqi = None
# 上期值
try:
# shangqi = temp_data['index_val'][flag_riqi]
shangqi = float(temp_data.loc[flag_riqi])
except:
shangqi = None
if (temp_riqi.month)==3 and dangqi:
value = format(dangqi,'.2f')
elif dangqi and shangqi:
value = format((dangqi - shangqi),'.2f')
else:
value = None
result.append([temp_riqi-relativedelta(months=2),value]) # 指标结果
flag_riqi = temp_riqi # 更新日期
result = pd.DataFrame(result,columns=['日期','指标值'])
result = result.set_index('日期')
return result
2.7 贡献率
因为 占比、贡献率、拉动率 的计算,都是对两个指标数据本身的计算,因此可以用同一个函数来实现。
备注:
这里 贡献率 和 拉动率 的计算以 同比贡献率 和 同比拉动率 进行计算实现;
还有 环比贡献率 和 环比拉动率 一说。不过实现同理啦。
# 贡献率计算函数
def contributionRate(temp_data_fenzi,temp_data_fenmu,zhibiao_freq):
'''
temp_data_fenzi,要计算的原始数据序列
temp_data_fenmu,要计算的原始数据序列
zhibiao_freq,指标更新频率
'''
result = [] # 存放计算结果(嵌套列表)
# 判断指标的加工周期
if zhibiao_freq == '年':
rel_delta = relativedelta(years=1)
if zhibiao_freq == '季':
rel_delta = relativedelta(months=3)
if zhibiao_freq == '月':
rel_delta = relativedelta(months=1)
# 起止日期时间
min_riqi = min(temp_data_fenmu.index)
max_riqi = max(temp_data_fenmu.index)
# 对范围内日期数据进行占比加工计算,单位(%)
flag_riqi = min_riqi
tongbi_delta = relativedelta(years=1)
while flag_riqi <= max_riqi-tongbi_delta:
temp_riqi = flag_riqi+tongbi_delta
# 分子增量值计算
# 当期值
try:
fenzi_dangqi = float(temp_data_fenzi.loc[temp_riqi])
except:
fenzi_dangqi = None
# 上期值
try:
fenzi_shangqi = float(temp_data_fenzi.loc[flag_riqi])
except:
fenzi_shangqi = None
# 分子增量结果
if fenzi_dangqi and fenzi_shangqi:
fenzi = format(fenzi_dangqi - fenzi_shangqi,'.2f')
else:
fenzi = None
# 分母值增量值计算
# 当期值
try:
fenmu_dangqi = float(temp_data_fenmu.loc[temp_riqi])
except:
fenmu_dangqi = None
# 上期值
try:
fenmu_shangqi = float(temp_data_fenmu.loc[flag_riqi])
except:
fenmu_shangqi = None
# 分母增量结果
if fenmu_dangqi and fenmu_shangqi:
fenmu = format(fenmu_dangqi - fenmu_shangqi,'.2f')
else:
fenmu = None
# 结果值计算
if fenzi and fenmu:
value = format(float(fenzi)/ float(fenmu) *100,'.2f')
else:
value = None
result.append([temp_riqi,value]) # 指标结果
flag_riqi = flag_riqi + rel_delta # 更新日期
result = pd.DataFrame(result,columns=['日期','指标值'])
result = result.set_index('日期')
return result
2.8 拉动率
# 拉动率 计算函数
def pullRate(temp_data_fenzi,temp_data_fenmu,zhibiao_freq):
'''
temp_data_fenzi,要计算的原始数据序列
temp_data_fenmu,要计算的原始数据序列
zhibiao_freq,指标更新频率
'''
result = [] # 存放计算结果(嵌套列表)
# 判断指标的加工周期
if zhibiao_freq == '年':
rel_delta = relativedelta(years=1)
if zhibiao_freq == '季':
rel_delta = relativedelta(months=3)
if zhibiao_freq == '月':
rel_delta = relativedelta(months=1)
# 起止日期时间
min_riqi = min(temp_data_fenmu.index)
max_riqi = max(temp_data_fenmu.index)
# 对范围内日期数据进行占比加工计算,单位(%)
flag_riqi = min_riqi
tongbi_delta = relativedelta(years=1)
while flag_riqi <= max_riqi-tongbi_delta:
temp_riqi = flag_riqi+tongbi_delta
# 分子增量值计算
# 当期值
try:
fenzi_dangqi = float(temp_data_fenzi.loc[temp_riqi])
except:
fenzi_dangqi = None
# 上期值
try:
fenzi_shangqi = float(temp_data_fenzi.loc[flag_riqi])
except:
fenzi_shangqi = None
# 分子增量结果
if fenzi_dangqi and fenzi_shangqi:
fenzi = format(fenzi_dangqi - fenzi_shangqi,'.2f')
else:
fenzi = None
# 分母值计算
try:
fenmu = float(temp_data_fenmu.loc[flag_riqi])
except:
fenmu = None
# 结果值计算
if fenzi and fenmu:
value = format(float(fenzi)/ float(fenmu) *100,'.2f')
else:
value = None
result.append([temp_riqi,value]) # 指标结果
flag_riqi = flag_riqi + rel_delta # 更新日期
result = pd.DataFrame(result,columns=['日期','指标值'])
result = result.set_index('日期')
return result
2.9 占比
# 占比 计算函数
def proportion(temp_data_fenzi,temp_data_fenmu,zhibiao_freq):
'''
temp_data_fenzi,要计算的原始数据序列
temp_data_fenmu,要计算的原始数据序列
zhibiao_freq,指标更新频率
'''
result = [] # 存放计算结果(嵌套列表)
# 判断指标的加工周期
if zhibiao_freq == '年':
rel_delta = relativedelta(years=1)
if zhibiao_freq == '季':
rel_delta = relativedelta(months=3)
if zhibiao_freq == '月':
rel_delta = relativedelta(months=1)
# 起止日期时间
min_riqi = min(temp_data_fenmu.index)
max_riqi = max(temp_data_fenmu.index)
flag_riqi = min_riqi
while flag_riqi <= max_riqi:
# 分子值
try:
fenzi = float(temp_data_fenzi.loc[flag_riqi])
except:
fenzi = None
# 分母值
try:
fenmu = float(temp_data_fenmu.loc[flag_riqi])
except:
fenmu = None
# 结果值计算
if fenzi and fenmu:
value = format(fenzi/ fenmu *100,'.2f')
else:
value = None
result.append([flag_riqi,value]) # 指标结果
flag_riqi = flag_riqi+rel_delta # 更新日期
result = pd.DataFrame(result,columns=['日期','指标值'])
result = result.set_index('日期')
return result
2.10 同期差值
# 同期差值 计算函数
def samePeriodDiff(temp_data_fenzi,temp_data_fenmu,zhibiao_freq):
'''
temp_data_fenzi,要计算的原始数据序列
temp_data_fenmu,要计算的原始数据序列
zhibiao_freq,指标更新频率
'''
result = [] # 存放计算结果(嵌套列表)
# 判断指标的加工周期
if zhibiao_freq == '年':
rel_delta = relativedelta(years=1)
if zhibiao_freq == '季':
rel_delta = relativedelta(months=3)
if zhibiao_freq == '月':
rel_delta = relativedelta(months=1)
# 起止日期时间
min_riqi = min(temp_data_fenmu.index)
max_riqi = max(temp_data_fenmu.index)
flag_riqi = min_riqi
while flag_riqi <= max_riqi:
# 分子值
try:
fenzi = float(temp_data_fenzi.loc[flag_riqi])
except:
fenzi = None
# 分母值
try:
fenmu = float(temp_data_fenmu.loc[flag_riqi])
except:
fenmu = None
# 结果值计算
if fenzi and fenmu:
value = format(fenzi- fenmu ,'.2f')
else:
value = None
result.append([flag_riqi,value]) # 指标结果
flag_riqi = flag_riqi+rel_delta # 更新日期
result = pd.DataFrame(result,columns=['日期','指标值'])
result = result.set_index('日期')
return result
2.11 月度/季度数据 在 一年中的均值
# 月度/季度数据 在 一年中的均值 计算函数
def monthInYearMean(temp_data,zhibiao_freq):
'''
temp_data,要计算的原始数据序列
zhibiao_freq,指标更新频率
'''
result = temp_data.copy()
min_riqi = min(temp_data.index)
max_riqi = max(temp_data.index)
for year in range(min_riqi.year,max_riqi.year+1):
temp = temp_data.loc[str(year)]
temp = temp.iloc[[not f for f in temp.isnull()]]
temp = [float(f) for f in temp]
try:
result.loc[str(year)] = sum(temp)/len(temp)
except:
result.loc[str(year)] = None
result = pd.DataFrame(result)
result.columns = ['指标值']
result.index.name = '日期'
return result
2.12 弹性系数
# 弹性系数 计算函数
def elasticCoefficient(temp_data_fenzi,temp_data_fenmu,zhibiao_code,yuanxing_name,zhibiao_freq):
'''
temp_data_fenzi,要加工计算的原始数据-分子位置
temp_data_fenmu,要加工计算的原始数据-分母位置
yuanxing_name,原型的指标名称
zhibiao_code,指标对应的编码
zhibiao_freq,指标更新频率
'''
# 弹性系数:"当期及同比及占比"
fenzi = monthaddupToSeason(temp_data_fenzi)
fenzi = yearOnYear(fenzi,zhibiao_freq)
fenmu = currentPeriod(temp_data_fenmu,zhibiao_freq)
fenmu = yearOnYear(fenmu['指标值'],zhibiao_freq)
for ind in fenmu.index:
try:
fenmu.loc[ind,'指标值'] = float(fenzi.loc[ind,'指标值']) / float(fenmu.loc[ind,'指标值'])
except:
fenmu.loc[ind,'指标值'] = None
return fenmu
2.13 1-占比
# 1-占比 计算函数
def oneToShare(temp_data_fenzi,temp_data_fenmu,zhibiao_freq):
"""
temp_data_fenzi,要加工计算的原始数据-分子位置
temp_data_fenmu,要加工计算的原始数据-分母位置
zhibiao_freq,指标更新频率
"""
result = proportion(temp_data_fenzi,temp_data_fenmu,zhibiao_freq)
for i in range(len(result)):
if result['指标值'].iloc[i]:
result['指标值'].iloc[i] = 100 - float(result['指标值'].iloc[i])
return result
2.14 数据进行拼接求行和
# 对 需求加工字典 中对应的原始数据指标名称 对应的数据进行拼接求行和
def windDataConcatSum(databaseData,names_list):
"""
databaseData : 万德入库的数据
names_list : 需要提取对应的wind指标名称字符串,多个名称以 \n 作为分隔
"""
result = pd.DataFrame() # 结果存放
# 将数据进行拼接
for fenzi_name in names_list:
if sum(databaseData['index_nm'] == fenzi_name) == 0:
print("指标 %s 还未入库,请先入库"%fenzi_name)
return result,None
t_data = databaseData['index_val'][databaseData['index_nm'] == fenzi_name]
t_data = pd.DataFrame({"stat_dt":t_data.index,fenzi_name:t_data.values})
if result.empty:
result = t_data
else:
result = pd.merge(result,t_data,left_on=['stat_dt'],right_on=['stat_dt'],how='outer')
zhibiao_freq = databaseData.loc[databaseData['index_nm']==names_list[0].strip(),:]['frequency_type'].iloc[0] # 指标加工频率
result = result.set_index('stat_dt')
result.sort_index(inplace=True)
result.index.name = "日期"
result = pd.DataFrame((result).sum(axis=1))
return result,zhibiao_freq
2.15 数据库中的原始数据提取 和 处理
# 数据库中的原始数据提取 和 处理
def dataBaseExtract(username,password,host,database,tablename):
'''
engine = create_engine('dialect+driver://username:password@host:port/database')
dialect -- 数据库类型
driver -- 数据库驱动选择
username -- 数据库用户名
password -- 用户密码
host 服务器地址
port 端口
database 数据库
'''
# 读取 公司数据库中的wind原始数据
gongsi_engine = create_engine('postgresql+psycopg2://{username}:{password}@{host}:5432/{database}'.format(
username=username,password=password,host=host,database=database))
# 从公司数据库读取 原始的入库 数据表
try:
databaseData = pd.read_sql("select * from biz_temp.%s"%(tablename),con=gongsi_engine)
databaseData['index_nm'] = [name.strip() for name in databaseData['index_nm']]
databaseData['stat_dt'] = pd.to_datetime(databaseData['stat_dt'])
databaseData = databaseData.set_index('stat_dt') # 导入库中的wind数据
except:
print("请返回数据库,查看数据库表的字段名称是否匹配.......")
return databaseData
2.16 提取 和 对应的 wind 或 统计局原始 数据返回
# 需求加工字典表 中的信息进行提取 和 对应的 wind 或 统计局原始 数据返回
def requestDictDataInfo(req_data,wind_data,nation_data,cateCal_dict,req_row_num):
"""
req_data, 需求加工字典表
wind_data, 入库的wind数据
nation_data,入库的统计局数据
req_row_num,要加工计算的指标 对应的需求加工字典中的 所在行数
"""
calculate_class = req_data['计算类别'].iloc[req_row_num]
zhibiao_code = req_data['指标编码'].iloc[req_row_num]
yuanxing_name = req_data['原型指标名称'].iloc[req_row_num]
move_num = req_data['移动均值期数'].iloc[req_row_num]
if str(move_num) != "nan":
move_num = int(move_num)
# 要加工的分子对应wind指标名称
try:
fenzi_origin_names = req_data['计算分子对应wind指标名称'].iloc[req_row_num].strip().split('\n')
except:
# print("%s 该指标暂时不满足数据要求!"%yuanxing_name)
return ['','',zhibiao_code,yuanxing_name,'',calculate_class,move_num]
# 将分子数据进行拼接
if calculate_class == "北京市统计局":
temp_data_fenzi,zhibiao_freq = windDataConcatSum(nation_data,fenzi_origin_names)
else:
temp_data_fenzi,zhibiao_freq = windDataConcatSum(wind_data,fenzi_origin_names)
if len(temp_data_fenzi)==0:
print(fenzi_origin_names," 中存在指标还未入库")
# zhibiao_freq = databaseData.loc[databaseData['index_nm']==fenzi_origin_names[0],:]['frequency_type'][0] # 指标加工频率
if cateCal_dict[calculate_class] == "双指标":
# 要加工的分母对应wind指标名称
fenmu_origin_names = req_data['计算分母对应wind指标名称'].iloc[req_row_num].strip().split('\n')
# 将分母数据进行拼接
temp_data_fenmu,zhibiao_freq= windDataConcatSum(wind_data,fenmu_origin_names)
return [temp_data_fenzi,temp_data_fenmu,zhibiao_code,yuanxing_name,zhibiao_freq,calculate_class,move_num]
elif cateCal_dict[calculate_class] == "双库指标":
# 要加工的分母对应的 北京市统计局指标名称
fenmu_origin_names = req_data['计算分母对应wind指标名称'].iloc[req_row_num].strip().split('\n')
# 将分母数据进行拼接
temp_data_fenmu,zhibiao_freq= windDataConcatSum(nation_data,fenmu_origin_names)
return [temp_data_fenzi,temp_data_fenmu,zhibiao_code,yuanxing_name,zhibiao_freq,calculate_class,move_num]
return [temp_data_fenzi,"",zhibiao_code,yuanxing_name,zhibiao_freq,calculate_class,move_num]
2.17 指定指标数据提取
# 提取 加工字典表中,不需要加工的 wind 指标 或者 统计局的指标
def windOrNationFeature(req_data,databaseData,req_row_num):
"""
req_data, 加工字典数据表
databaseData, 入库的数据表 数据
zhibiao_code,指标编码
yuanxing_name,原型中的指标名称
zhibiao_freq,指标频率
req_row_num,对应的加工字典的 第几行,
"""
# 要加工的分子对应wind指标名称
fenzi_origin_names = req_data['计算分子对应wind指标名称'].iloc[req_row_num].strip().split('\n')
# 将分子数据进行拼接
result,zhibiao_freq = windDataConcatSum(databaseData,fenzi_origin_names)
result.columns = ["指标值"]
# result.loc[:,"指标编码"] = zhibiao_code
# result.loc[:,"原型指标名称"] = yuanxing_name
# result.loc[:,'频率'] = zhibiao_freq
# columns=['指标编码','原型指标名称','指标值','频率']
# result = result[columns]
return result
2.18 进度
# 进度 计算函数
def progressSpeed(temp_data_fenzi,temp_data_fenmu,zhibiao_freq):
'''
temp_data_fenzi,要计算的原始数据序列
temp_data_fenmu,要计算的原始数据序列
zhibiao_freq,指标更新频率
'''
result = temp_data_fenzi.copy()
min_riqi = min(temp_data_fenzi.index)
max_riqi = max(temp_data_fenzi.index)
for year in range(min_riqi.year,max_riqi.year+1):
fenzi = temp_data_fenzi.loc[str(year)]
try:
fenmu = temp_data_fenmu.loc[str(year)]
except:
result.loc[str(year)] = None
continue
for t in fenzi.index:
try:
result.loc[t] = round(float(fenzi.loc[t].values[0])/float(fenmu.iloc[0,0])*100,2)
except:
result.loc[t] = None
result = pd.DataFrame(result)
result.columns = ['指标值']
result.index.name = '日期'
return result
2.19 汇总函数
# 指标加工类型 汇总函数
def FeatureCalculate(req_data , wind_data , nation_data , req_row_num ,
temp_data_fenzi,temp_data_fenmu,zhibiao_code,yuanxing_name,zhibiao_freq,cal_class,move_num=0):
'''
req_data, 需求加工字典表
wind_data, 入库的wind数据
nation_data,入库的统计局数据
req_row_num,要加工计算的指标 对应的需求加工字典中的 所在行数
temp_data_fenzi,要加工计算的原始数据-分子位置
temp_data_fenmu,要加工计算的原始数据-分母位置
zhibiao_code,指标对应的编码
yuanxing_name,原型中的指标名称名称
zhibiao_freq,指标更新频率
cal_class,指标加工类型
move_num , 移动均值 移动期数
'''
if cal_class == "wind":
result = windOrNationFeature(req_data,wind_data,req_row_num)
elif cal_class == "北京市统计局":
result = windOrNationFeature(req_data,nation_data,req_row_num)
elif cal_class=="环比":
result = monthOnMonth(temp_data_fenzi,zhibiao_freq)
elif cal_class=="同比":
result = yearOnYear(temp_data_fenzi,zhibiao_freq)
elif cal_class == "当期值":
result = currentPeriod(temp_data_fenzi,zhibiao_freq)
elif cal_class == "当期及同比":
result = currentPeriod(temp_data_fenzi,zhibiao_freq)
result = yearOnYear(result['指标值'],zhibiao_freq)
elif cal_class == "累计值":
result = monthToMonthAddUp(temp_data_fenzi,zhibiao_freq)
elif cal_class == "移动均值":
result = moveAverage(temp_data_fenzi,zhibiao_freq,move_num)
elif cal_class == "当期及移动均值":
result = currentPeriod(temp_data_fenzi,zhibiao_freq)
result = moveAverage(result['指标值'],zhibiao_freq,move_num)
elif cal_class == "同比及移动均值":
result = yearOnYear(temp_data_fenzi,zhibiao_freq)
result = moveAverage(result['指标值'],zhibiao_freq,move_num)
elif cal_class == "当期及同比及移动均值":
result = currentPeriod(temp_data_fenzi,zhibiao_freq)
result = yearOnYear(result['指标值'],zhibiao_freq)
result = moveAverage(result['指标值'],zhibiao_freq,move_num)
elif cal_class == "占比": # 涉及双指标
result = proportion(temp_data_fenzi,temp_data_fenmu,zhibiao_freq)
elif cal_class == "1-占比":
result = oneToShare(temp_data_fenzi,temp_data_fenmu,zhibiao_freq)
elif cal_class == "同期差值":
result = samePeriodDiff(temp_data_fenzi,temp_data_fenmu,zhibiao_freq)
elif cal_class == "同比及同期差值":
fenzi_data = yearOnYear(temp_data_fenzi,zhibiao_freq)
result = samePeriodDiff(fenzi_data,temp_data_fenmu,zhibiao_freq)
elif cal_class == "贡献率":
result = contributionRate(temp_data_fenzi,temp_data_fenmu,zhibiao_freq)
elif cal_class == "拉动率":
result = pullRate(temp_data_fenzi,temp_data_fenmu,zhibiao_freq)
elif cal_class == "弹性系数":# 弹性系数:"当期及同比及占比"
result = elasticCoefficient(temp_data_fenzi,temp_data_fenmu,zhibiao_code,yuanxing_name,zhibiao_freq)
elif cal_class == "月度占比年度均值":
result = proportion(temp_data_fenzi,temp_data_fenmu,zhibiao_freq)
result = monthInYearMean(result['指标值'],zhibiao_freq)
elif cal_class == "进度":
result = progressSpeed(temp_data_fenzi,temp_data_fenmu,zhibiao_freq)
else:
return None
result.loc[:,"指标编码"] = zhibiao_code
result.loc[:,"原型指标名称"] = yuanxing_name
result.loc[:,'频率'] = zhibiao_freq
columns=['指标编码','原型指标名称','指标值','频率']
result = result[columns]
return result
三、 具体实现案例
import pandas as pd
import datetime
from dateutil.relativedelta import *
import pandas as pd
import time
################################# 主程序 ####################################
if __name__=='__main__':
# 初始化变量名
# 从公司数据库读取需要的数据表
username = "xxxxxx" #
password = "xxxxxx"
host = "xxxxxxxxxx"
database = "xxxxxxxxx"
wind_tablename = "xxxxxxxxxx" # wind 入库的数据表名
nation_tablename = "xxxxxxxxx" # 北京市统计局入库的数据表名
# 本地数据库信息
# 需求加工字典表 全地址名称
req_data_name = r'./宏观经济数据库表/宏观经济分析指标基需求加工字典.xls'
# 从公司数据库读取 原始的入库 数据表
wind_data = dataBaseExtract(username,password,host,database,wind_tablename) # wind入库的数据
nation_data = dataBaseExtract(username,password,host,database,nation_tablename)# 北京市统计局入库的数据
# 读取 需求加工字典数据
req_data = pd.read_excel(req_data_name)
cateCal_dict = {
'环比': '单指标',
'当期及同比': '单指标',
'当期及同比及移动均值':'单指标',
'当期及移动均值': '单指标',
'当期值': '单指标',
'累计值': '单指标',
'同比': '单指标',
'同比及移动均值': '单指标',
'移动均值': '单指标',
'占比': '双指标',
'弹性系数': '双指标',
'同比及同期差值': '双指标',
'1-占比': '双指标',
'贡献率': '双指标',
'拉动率': '双指标',
'同期差值': '双指标',
'月度占比年度均值': '双指标',
'wind': '单指标',
'北京市统计局': '单指标',
'进度': '双库指标'
}
all_yuanxing_data = pd.DataFrame() # 存放所有原型中的数据,纵向拼接
time_start = time.time() # 程序开始计时
for req_row_num in range(len(req_data)):
try:
# 提取需要的基础数据信息
temp_data_fenzi,temp_data_fenmu,zhibiao_code,yuanxing_name,zhibiao_freq,cal_class,move_num = \
requestDictDataInfo(req_data,wind_data,nation_data,cateCal_dict,req_row_num)
if str(cal_class)=="nan":
continue
# 需要的指标信息
one_yuanxing_data = FeatureCalculate(req_data , wind_data , nation_data , req_row_num ,
temp_data_fenzi,temp_data_fenmu,zhibiao_code,yuanxing_name,zhibiao_freq,cal_class,move_num)
if req_row_num%50 == 0:
print("加工到 %s 行了,对应的指标编码为:%s"%(req_row_num+2,zhibiao_code))
# 数据拼接
if all_yuanxing_data.empty:
all_yuanxing_data = one_yuanxing_data
else:
all_yuanxing_data = pd.concat([all_yuanxing_data,one_yuanxing_data])
except:
print('忽略了需求表中第%s行的数据,对应的指标编码为:%s'%(req_row_num+2,zhibiao_code))
time_end = time.time() # 程序结束时间
print('\n运行结束,程序耗时:%s'%(time_end-time_start))
req_data数据样例
result_tongbi 加工结果样例:
四、小感
本来以为 同比、环比、占比、贡献率、拉动率 这些日常见到的名词,应该挺简单的,动手一整理,发现其中还是有很多的“坑坑道道”,