見出し画像

日本の元号の持続期間をpythonを使ってグラフ化してみる試み

この記事は、前半と後半で内容が大きく変わります。
pythonに興味ある方は前半だけ、元号に興味ある方は後半だけを読んでいただければよいと思います。


前置き

2025年は日本における元号制定から1380年目になります

いまさらですが2025年の干支はへび年、もっと詳しくは乙巳 きのとみです。乙巳と言えば想起するのが、乙巳 いっしの変。中大兄皇子と中臣鎌足が皇極天皇の面前で蘇我入鹿を暗殺した事件です。
私が学生の頃は「大化の改新」と習ったのですが、今ではこの事件を「乙巳の変」、その後の政治改革を「大化の改新」と呼ぶそうです。

「大化の改新」では、日本における初めての元号「大化」が制定されました。乙巳の変は西暦645年で今年は2025年なので、今年は大化の改新から1380年後の世界です。日本で元号が使われ始めてから、干支が1380÷60=23巡したことになります。
日本では南北朝時代を除くと元号を制定する天皇家が乱立することがなく、全国で単一の元号が使われてきました。1380年もの間、一貫して元号という制度が保たれてきたことを考えると少し気が遠くなってしまいます。
(中国、韓国、ベトナムでもかつて元号が使われていたのですが、群雄割拠した複数の地方国家が個別に元号を定めたため、いくつもの元号が同時に乱立することも多かったそうです。)

昔は元号が頻繁に変わりすぎ問題

最近、昔に書かれた本を少しずつ読み進めているのですが、元号改定に関する記載が極めて頻繁にみられることに気づきました。

元号が変わったぞ
あれ?まだ3年もたっていないのに元号変わった?
また元号変わったぞ?こんなん覚えきれるのか?

明治以降は「一世一元の制」というのができて、天皇一代につき元号ひとつになったのに対して、昔は一人の天皇がいくつも元号を定めたというくらいの知識はあったのですが、こんなに頻繁に元号が変わっていたというのは認識していませんでした。
ということで、この記事は過去の元号持続期間をデータとしてまとめてみた試みについて書いてみます。

手作業とpythonを組み合わせて、元となるエクセルをつくってみる

元号の一覧はWikipediaを参照

「元号」「一覧」で検索するといくつかページがみつかるのですが、元号の持続期間がすぐに取り出せる形のデータは見つかりませんでした。もっとも希望に近いのがWikipediaの「元号一覧_(日本)」のページです。

元データとしては申し分ないのですが、「年数」のところは年単位の精度しかなく、何日持続したかの日単位でのデータが記載されていません。
それなので、エクセルを使って自分で計算してみようと思うのですが、そのままコピペしてエクセルに貼り付けると、

  • 元号名のセルが結合されて複数行にまたがっている

  • 始期と終期の表記が「(593年1月15日)」のようになっていて、そのままではデータとして扱いづらい

ということで、このデータから直接元号の持続期間を計算するのはちょっと大変そうだなと判断しました。

Wikipediaからそのままエクセルにコピペしたらこうなります

pythonで処理する前に、エクセルを手作業で成形

とりあえずは、元号名と始期、終期の「(593年1月15日)」の行をそろえるために、元号名の列だけ一行挿入してみました。また、後のことを考えて、エクセルの置換機能を使って

(593年1月15日)→(0593年01月15日)

のように、ゼロ埋めにより西暦を4桁、月と日を二けたに成形しました。

エクセルによる成型後

その他、以下を手作業で実施してpythonでデータ処理できる形式に修正しました。なお、令和はまだ終わっていないので今回はデータに含めていません。

  • 南北朝時代については両方の元号を使うと複雑なので、後醍醐天皇の大覚寺統と南朝のデータに統一

  • 分裂直前の「元徳」について記載を修正

  • 始期がはっきりしないために記載されていない「文中」については註をもとに新暦4月26日と記載

  • [注釈1]などの註に関する文字を削除

  • 明治以降はフォーマットが変わっているので手作業で入力

それではpythonで、それぞれの元号期間を計算してみよう

作ってみたコードはこんな感じ

import pandas as pd

loadfilepass = r"C:\Users\dummy\Desktop\gengo_input.xlsx"
savefilepass = r"C:\Users\dummy\Desktop\gengo_output.xlsx"

df_load = pd.read_excel(loadfilepass) 
df_load = df_load[df_load["期間"].str.contains("(", na=False)]

df_load['期間'] = df_load['期間'].str.replace('(', '').str.replace('年', '-').str.replace('月', '-').str.replace('日)', '')
df_load['Unnamed: 3'] = df_load['Unnamed: 3'].str.replace('(', '').str.replace('年', '-').str.replace('月', '-').str.replace('日)', '')

df_load['期間'] = pd.to_datetime(df_load['期間'], format='%Y-%m-%d')
df_load['Unnamed: 3'] = pd.to_datetime(df_load['Unnamed: 3'], format='%Y-%m-%d')

大したコードではないですが一応解説すると

loadfilepass = r"C:\Users\dummy\Desktop\gengo_input.xlsx"
savefilepass = r"C:\Users\dummy\Desktop\gengo_output.xlsx"

これはファイルパスを指定しただけです。PC名「dummy」のところは、使用する環境によって適当に書き換えましょう。
動作前に成形したエクセルを「gengo_input.xlsx」に保存しておきます。

df_load = pd.read_excel(loadfilepass) 
df_load = df_load[df_load["期間"].str.contains("(", na=False)]

ここは、「(0593年01月15日)」とかが含まれない行が邪魔なので削除しています。

df_load['期間'] = df_load['期間'].str.replace('(', '').str.replace('年', '-').str.replace('月', '-').str.replace('日)', '')
df_load['Unnamed: 3'] = df_load['Unnamed: 3'].str.replace('(', '').str.replace('年', '-').str.replace('月', '-').str.replace('日)', '')

そして、西暦年の記載形式を

(0593年01月15日) → 0593-01-15

のようにdatetime型に変換しやすくしています。

最後に

df_load['期間'] = pd.to_datetime(df_load['期間'], format='%Y-%m-%d')
df_load['Unnamed: 3'] = pd.to_datetime(df_load['Unnamed: 3'], format='%Y-%m-%d')

で「0593-01-15」などの部分をdatetime型に変換して完成。あとは、日付の引き算などで自由自在。完璧です。

pythonのdatetimeでは古代の暦は計算できないというワナ

ということで早速動作させてみました。

あれ?なんか出てきたぞ。
なんか見たことないエラー発生。

「OutOfBoudsDatetime」なる謎のエラーが発生しました。ネットで調べたところ「pythonのdatetimeは1677年9月22日から2262年4月11日までしか処理できない」という衝撃の事実が判明しました。なにこれ…。
そして、エラー回避方法としては「処理できない範囲の日付はdatetime型への処理をしないようにしましょう」という身もふたもないものしか見つかりませんでした。マジっすか…。

あきらめきれずにいろいろ探すと、AmazonのKDPで「Python 3.6による暦の作成 第6巻 日本古代の暦」なるマニアックな書籍を発見しましたが、めんどくさそうではあります。

そこで、完璧を目指さず、「一年を365日と固定しておおよその元号持続期間を求める」方針として再度コードをつくってみました。うるう年は考えないことにします。

完璧を目指さなければ、そんなに手間はかからない

ということで、作り直したコードは以下となります。

import pandas as pd

loadfilepass = r"C:\Users\hzh11\Desktop\gengotest.xlsx"
savefilepass = r"C:\Users\hzh11\Desktop\gengotest2.xlsx"

df_load = pd.read_excel(loadfilepass) 
df_load = df_load[df_load["期間"].str.contains("(", na=False)]

df_load['期間'] = df_load['期間'].str.replace('(', '').str.replace('年', '-').str.replace('月', '-').str.replace('日)', '')
df_load['Unnamed: 3'] = df_load['Unnamed: 3'].str.replace('(', '').str.replace('年', '-').str.replace('月', '-').str.replace('日)', '')

df_load['開始年'] = df_load['期間'].str[:4]
df_load['終了年'] = df_load['Unnamed: 3'].str[:4]
df_load["継続年"] = df_load["終了年"].astype(int) - df_load["開始年"].astype(int)
df_load['開始日'] = pd.to_datetime("2025" + df_load['期間'].str[4:])
df_load['終了日'] = pd.to_datetime("2025" + df_load['Unnamed: 3'].str[4:])
df_load["継続日"] = (df_load["終了日"] - df_load["開始日"]).map(lambda x: x.days)

df_load["継続日(合計)"] = df_load["継続年"]*365 + df_load["継続日"]

with pd.ExcelWriter(savefilepass,engine="openpyxl") as writer:
    df_load.to_excel(writer,sheet_name="sheet1")

主に追加したのは、以下となります。

df_load['開始年'] = df_load['期間'].str[:4]
df_load['終了年'] = df_load['Unnamed: 3'].str[:4]
df_load["継続年"] = df_load["終了年"].astype(int) - df_load["開始年"].astype(int)
df_load['開始日'] = pd.to_datetime("2025" + df_load['期間'].str[4:])
df_load['終了日'] = pd.to_datetime("2025" + df_load['Unnamed: 3'].str[4:])
df_load["継続日"] = (df_load["終了日"] - df_load["開始日"]).map(lambda x: x.days)

df_load["継続日(合計)"] = df_load["継続年"]*365 + df_load["継続日"]

これは、

  1. 「0593-01-15」を「0593」と「01-15」に分解

  2. 「01-15」の頭に「2025-」を追加して「2025-01-15」に成形したうえで、datetime型に変換

  3. 継続日(合計) = (終了年 - 開始年) x 365 + (終了日 - 開始日)
    にて元号の継続期間を算出

したものです。

できあがり。「継続日2」のところが元号の継続日数です。

いまさらの蛇足

この程度の処理だったら、わざわざpython使わなくてもエクセルだけでなんとかなったのではないか?という疑念が頭をよぎりますが、気づかなかったことにします。まさかdatetime型が古代に対応していないとは思っていなかったのですよ…。

それでは、いろいろグラフ書いてみます

まずはいつもの累積分布関数

元号の継続期間(累積分布関数)

史上最も長く続いた元号は昭和(約22643日)、次に明治(約16245日)、一つ飛んで平成(約11062日)なのですが、意外なことに明治と平成の間に「応永」なる元号(約12357日)が挟まりました

応永は1394年8月2日から1428年6月10日まで34年間にわたり継続した元号で、室町時代に使用されたそうです。Wikipediaによると

・(その前の明徳から応永への)この改元で義満は機嫌を損ねて、自分の生きている間には元号を変えさせなかった。
・元年に将軍に就任した義満の子の義持が応永に愛着を持っていたので、1408年(応永15年:義満死去に伴う)と1413年(応永20年:称光天皇即位に伴う)に出された改元の議を阻止した。実際、義持の死の直後に改元された。

という事情があったそうですが…。

あと、このグラフを見てわかるのは、全体の85%の元号の寿命は10年以下であり、96%は20年以下であるということです(20年以上続いた元号は、寛永、延喜、天文、正平、延暦、平成、応永、明治、昭和のみ)。「短い」という印象が強い大正時代も、相対的に見るとむしろ長命な元号に分類されます。
ただし、長く続いたから存在感が強いかというとそうでもないようにも思います。「寛永」は「寛永通宝」、「延喜」は「延喜の治」、「延暦」は「比叡山延暦寺」で聞き覚えがありますが「天文」とか「正平」なんて元号は、私自身は初めて知りました。

なお、短命に終わった元号を順番に並べると

  1. 暦仁 1238年12月30日~1239年3月13日 73日

  2. 天平感宝 749年5月4日~749年8月19日 107日

  3. 元仁 1224年12月31日~1225年5月28日 148日

  4. 康元 1256年10月24日~1257年3月31日 158日

  5. 朱鳥 686年8月14日~687年2月17日 187日

ということで、半年ももたない元号が4つありました。うち「暦仁」「元仁」「康元」はいずれも鎌倉時代の元号です。

元号が長命な時代と短命な時代があったのか?

元号の持続期間を前から並べてみることにします。

元号の持続期間を開始年を基準に並べてみる

平安時代中期から鎌倉にかけては、元号が頻繁に変更されていることがわかります。
923年5月29日に終了した貞観を最後に1347年に始まる正平までの400年以上にわたり、5000日以上使われた元号が登場しません(4000日以上使われた元号も1264年3月27日に始まった文永のみです)。この時代の人々にとっては、元号は数年おきに代わるのが当たり前という感覚だったのだと思います。

また、平安時代901年に始まる延喜の時代からに江戸末期1864年に始まる元治の時代に至るまで「甲子革令」「辛酉革命」といって、干支が甲子の年と辛酉の年には改元する習わしがありました。これは、甲子や辛酉の年には政治や社会において変革が起こるとされていたことから始まったものだそうです。

辛酉の年の3年後には甲子の年になるので、この期間はいくら長くても3年で改元されてしまいます。
また、甲子の年の57年後には辛酉になるので、原理上元号の寿命上限は57年に限られることとなります。よって、昭和のように60年以上続く元号が登場するには、「甲子革令」「辛酉革命」を廃止する必要があったのです。

まとめ

ということで、得た知見をまとめると以下になります。だからどうしたという話ではありますが…。

  • pythonのdatetimeは、1677年9月22日から2262年4月11日までしか処理できない。みんな古代の暦扱いたいときはどうしてるのだろうか…。

  • 元号の寿命が長い順に並べると「昭和」「明治」「応永」「平成」となり、「一世一元の制」以前では室町時代の「応永」が突出して長い

  • 全体の85%の元号の寿命は10年以下であり、96%は20年以下

  • 平安時代中期から鎌倉にかけては、元号が頻繁に変更されており、923年5月29日に終了した貞観を最後に1347年に始まる正平までの400年以上にわたり、5000日以上使われた元号が登場しない

  • 「甲子革令」「辛酉革命」にて干支が甲子の年と辛酉の年には改元する習わしがあったため、元号の持続期間には上限があった


いいなと思ったら応援しよう!