作为日常可视化作品之一,今天分析一下自97年开始,60年内每次生日与立春(the Beginning of Spring)和雨水(the Rains)两个节气的相隔天数,看看哪一年会有重合的运气。
立春,十二节令之首,旧称正月节;雨水,十二中气立始。立春后,继之雨水,东风解冻、散而为雨,后鸿雁来,草木萌动。而正月初十这天,常是在立春与雨水之间不定。
这与农历历法相关,农历纪年取月相朔望变化,参考太阳回归年长度,设置闰月调整,使之相适应。因此农历和公历不同,需要天文台进行校准。立春常对应公历2月3、4日,雨水常对应公历2与18、19日,但正月初十与公历时间对应就比较混乱了。
1、统计立春、雨水与正月初十对应的公历日期
Python
中有一些公历与农历相转换的工具,如zhdate
,sxtwl
。但我是用百度查表查出来的,以如下格式存储成BirthdayRecord.csv
。对于日期间隔的计算,采用EXCEL
计算,使用Python
中的Pandas
计算也可以。
年份 | 历年生日 | 历年立春 | 历年雨水 | 立春间隔 | 雨水间隔 | 节气间隔 |
---|---|---|---|---|---|---|
1997 | 1997/2/16 | 1997/2/4 | 1997/2/18 | -12 | 2 | 14 |
1998 | 1998/2/6 | 1998/2/4 | 1998/2/19 | -2 | 13 | 15 |
2、Python绘图展示
a、导入需要的包
import pandas as pd
import numpy as np
import matplotlib.pylab as plt
# 一些matplotlib画图的设置
large = 16; med = 12; small = 10
params = {'axes.titlesize': large,
'legend.fontsize': med,
'figure.figsize': (10, 6),
'axes.labelsize': large,
'axes.titlesize': med,
'xtick.labelsize': med,
'ytick.labelsize': med,
'figure.titlesize': large}
plt.rcParams.update(params)
# 设置使用漫画绘图模式,禁用可以返回普通模式
plt.xkcd()
b、处理数据
data = pd.read_csv("BirthdayRecord.csv", encoding="gb2312")
# 查看data的统计信息
data.info()
获得输出结果
RangeIndex: 60 entries, 0 to 59
Data columns (total 7 columns):
年份 60 non-null int64
历年生日 60 non-null object
历年立春 60 non-null object
历年雨水 60 non-null object
立春间隔 60 non-null int64
雨水间隔 60 non-null int64
节气间隔 60 non-null int64
dtypes: int64(4), object(3)
memory usage: 3.4+ KB
c、成图
fig, ax = plt.subplots(figsize=(12,6), dpi=100)
# 画出间隔
for i in range(len(data)):
# 设置颜色
color1 = plt.cm.rainbow(np.abs(data.loc[i, "立春间隔"])/60 +0.7)
color2 = plt.cm.rainbow(np.abs(data.loc[i, "雨水间隔"])/30-0.5)
# 画点
ax.scatter(data.loc[i, "年份"], data.loc[i, "立春间隔"], color=color1, marker="o", s=np.abs(data.loc[i, "立春间隔"])+15, zorder=5, label="the Beginning of Spring" if i==2 else None)
ax.scatter(data.loc[i, "年份"], data.loc[i, "雨水间隔"], color=color2, marker="p", s=np.abs(data.loc[i, "雨水间隔"])+15, zorder=5, label="the Rains" if i==4 else None)
# 画图例
# 画直线
ax.plot(data["年份"], data["立春间隔"], color="red", linestyle="-", linewidth=0.5, alpha=0.3, zorder=0)
ax.plot(data["年份"], data["雨水间隔"], color="blue", linestyle="-", linewidth=0.4, alpha=0.3, zorder=0)
# 画直线
ax.hlines(0, 1996, 2056, color="gray", linestyle="--", linewidth=1, alpha=1, zorder=20)
ax.vlines(2020, -24, 23, color="gray", linestyle="--", linewidth=1, alpha=1, zorder=20)
# 画星星
zeroData = data[data["立春间隔"]==0]
ax.scatter(zeroData["年份"], zeroData["立春间隔"], marker="v", color="red", alpha=0.5, zorder=40)
# 画星星
zeroData = data[data["雨水间隔"]==0]
ax.scatter(zeroData["年份"], zeroData["雨水间隔"], marker="^", color="blue", alpha=0.6, zorder=40)
# 设置坐标轴范围
ax.set_xlim(1996, 2057)
ax.set_ylim(-31, 26)
# 设置x轴间隔
plt.xticks([data.loc[x, "年份"] for x in range(0, len(data), 6)])
# 设置文字
ax.set_xlabel("Year")
ax.set_ylabel("Interval /d")
ax.set_title("the Interval Between Birthday and the Two Solar Terms Each Year", size=large)
# 设置坐表轴隐藏
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
# 设置图例
ax.legend(loc="lower center", ncol=2)
# ax.grid(alpha=0.3, color="gray", zorder=10)
# 保存图片
plt.savefig("生日间隔统计.jpg", dpi=300)
成品图
3、讨论
- 由于
UbuntuServer
没有部分中文字体的版权,所以用英语标注了一下; - 2020年之后的节气间隔是推测出的,由于农历本身需要天文台挂测,所以只是做个参考;
- 立春与雨水的间隔变化很规律,但具体什么规律就没有深究,有学历法的同学可以私信一下;
- 红色与蓝色三角形代表重合的年份,然而并没有几次。
- 最后转载请注明出处!!!