8月は暑くなっているのか!?

SNSなどで「最近の夏は暑くなっている」という話を見聞きします。私自身は、何度か転居しているので最近の夏や暑くなっているのかどうかの判断を体感ですることはできなので、少しデータを弄って調べてみました。というか、前回の記事のコードをちょこっと書き換えればできそうだったのでやってみたというのが正直なところです。

[R]POSIXct(POSIXlt)型を使って特定の月(年・日etc)の値を抽出する

さて、まずはデータのダウンロードです。気象庁の「過去の気象データ・ダウンロード」から8月の最高気温と最低気温をダウンロードしました。ここで、最高気温を「data_max.csv」、最低気温を「data_min.csv」とリネームしています。なお「特定の期間を複数年分、表示する」にチェックを入れると、8月だけの気温をダウンロードすることができます。

8月の気温だけをダウンロード(赤枠は当方加筆)

まず、8月の最高気温を年別にまとめて、最大値・中央値・最小値・平均値を求めてみました。まず、中央値と平均値を比較するとそれほど大きな差は無いようです。次に、最大値・中央値・平均値は少しずつ上昇する傾向が見られますが、最低値については上昇する傾向はハッキリしません。東京で最高気温が低くなるような日といえば、北東気流が入るような日が多いと思いますが、その気温はあまり変わっていないというのは示唆的です。親潮の水温が上昇したりすると、この先どうなるのでしょうか。

年別の8月の最高気温(最大値・中央値・最小値・平均値)

次に最低気温を見てみます。こちらは最高気温以上に上昇する傾向がハッキリとしています(ただし、軸のレンジが違っているのに要注意)。特に最低気温の最大値を見ると1930年頃までは25℃を上回らない年もあります。このような年は熱帯夜がなかったと言うことになります。最高気温よりも最低気温の上昇幅が大きいのは、建物によって風の流れが阻害されたり、コンクリート等の熱容量が大きく吸水性に乏しい建材等の蓄熱で夜の気温が下がりにくくなったことが一因でしょう(地球温暖化だったり、土壌や空気中の水や水蒸気の挙動など色々と考えられますが、ここでは原因には踏み込まないことにします)。

年別の8月の最低気温(最大値・中央値・最小値・平均値)

最後に、年別の猛暑日、真夏日、熱帯夜の日数を年別に集計しました。また、猛暑日と真夏日の中間として最高気温が32.5℃以上の日数も年別に集計しました。なお、ここで真夏日とは最高気温30℃以上の日としており、猛暑日も真夏日に含んでいます。

年別の日数(真夏日・猛暑日・熱帯夜)

複数の要素を一つのグラフに載せてしまったので見づらいですが、1930年頃までは猛暑日も熱帯夜もほとんどありません。それが1930年頃から熱帯夜や猛暑日の日数が増えているのがよくわかります。その一方で、真夏日の日数は猛暑日や熱帯夜のように最近になるほど増加する傾向はあまり見られません。

以上をまとめてみると、東京の気温を見る限りだと最低気温と最高気温の上昇を比較すると最低気温の上昇が大きいこと、また最近は猛暑日や熱帯夜の日数が増えているということは言えそうです。その一方で、猛暑日にしろ熱帯夜にしろ、年別の該当日数は短周期での変動が大きいため、長期間のトレンドを見るのは難しいと考えられます。


最後に、グラフを書いたRのコードを貼り付けておきます。

setwd("D:/hogehoge")

#ヘッダ行数(最低気温・最高気温:6、平均気温:5)
iSkip <- 6

#データ読み込み
dfAll <- read.csv("data_min.csv",  skip=iSkip, header=F, stringsAsFactors=F)

#正常値の行(品質情報=8)のみを抽出、日付を文字列からPOSIXltに変換
dats <- as.POSIXct(dfAll[dfAll$V3==8,]$V1, format="%Y/%m/%d", tz = "Japan")
temp <- dfAll[dfAll$V3==8,]$V2

#データフレームに
dfTemp <- data.frame(Dat=dats, Temp=temp)

#データの期間
iYs <- min(as.integer(format(dfTemp$Dat,"%Y"), "%d")):max(as.integer(format(dfTemp$Dat,"%Y"), "%d"))

#指定した年の気温を抽出
fYTmp <- function(x){dfTemp[as.integer(format(dfTemp$Dat,"%Y"), "%d")==x,]$Temp}

#年別:最大、75%ile、中央値(50%ile)、平均値、25%ile、最低
t_max <- sapply(iYs, function(x){max(fYTmp(x))})
t_50  <- sapply(iYs, function(x){median(fYTmp(x))})
t_min <- sapply(iYs, function(x){min(fYTmp(x))})
t_mean <- sapply(iYs, function(x){mean(fYTmp(x))})

#グラフ設定
png("最高気温.png", height=600, width=1200, res=200)
par(mar=c(3, 3, 1.5, 1)) #余白設定
par(mgp=c(2, 0.7, 0))  #グラフ枠と軸との間隔設定
par(xaxs = "i")        #データ範囲とグラフの範囲(X軸)
par(yaxs = "i")        #データ範囲とグラフの範囲(Y軸)

#枠だけ作る
plot(iYs, t_max, type="n", xlim=c(min(iYs),max(iYs)), ylim=c(18,40),
xlab="西暦[年]", ylab="最高気温[℃]")

#プロット①
lines(iYs, t_max, type="b", pch=20, col=rgb(1,0,0), lty=1)
lines(iYs, t_50, type="b", pch=17, col=rgb(0,0,0), lty=1)
lines(iYs, t_min, type="b", pch=20, col=rgb(0,0,1), lty=1)
lines(iYs, t_mean, type="b", pch=1, col=gray(0), lty=1)

#凡例
legend("topleft", pch=c(20,17,20,1), col=c(rgb(1,0,0),rgb(0,0,0),rgb(0,0,1),gray(0)),lty=c(1,1,1,1),ncol=2,
 legend=c("最大値","中央値","最小値","平均値")
)

setwd("D:/hogehoge")

#ヘッダ行数(最低気温・最高気温:6、平均気温:5)
iSkip <- 6

#データ読み込み
dfAll <- read.csv("data_max.csv",  skip=iSkip, header=F, stringsAsFactors=F)
dfAll_l <- read.csv("data_min.csv",  skip=iSkip, header=F, stringsAsFactors=F)


#正常値の行(品質情報=8)のみを抽出、日付を文字列からPOSIXltに変換
dats <- as.POSIXct(dfAll[dfAll$V3==8,]$V1, format="%Y/%m/%d", tz = "Japan")
temp <- dfAll[dfAll$V3==8,]$V2
dats_l <- as.POSIXct(dfAll_l[dfAll_l$V3==8,]$V1, format="%Y/%m/%d", tz = "Japan")
temp_l <- dfAll_l[dfAll_l$V3==8,]$V2

#データフレームに
dfTemp <- data.frame(Dat=dats, Temp=temp)
dfTemp_l <- data.frame(Dat=dats_l, Temp=temp_l)

#データの期間
iYs <- min(as.integer(format(dfTemp$Dat,"%Y"), "%d")):max(as.integer(format(dfTemp$Dat,"%Y"), "%d"))

#指定した年の気温を抽出
fYLTmp <- function(tl,yr){dfTemp[as.integer(format(dfTemp$Dat,"%Y"), "%d")==yr&tl<=dfTemp$Temp,]$Temp}
fYLTmp_l <- function(tl,yr){dfTemp_l[as.integer(format(dfTemp_l$Dat,"%Y"), "%d")==yr&tl<=dfTemp_l$Temp,]$Temp}

#年別:猛暑日、最高32.5℃以上、真夏日、熱帯夜
t_35 <- mapply(function(x,y){length(fYLTmp(x,y))}, rep(35,times=length(iYs)),iYs)
t_325 <- mapply(function(x,y){length(fYLTmp(x,y))}, rep(32.5,times=length(iYs)),iYs)
t_30 <- mapply(function(x,y){length(fYLTmp(x,y))}, rep(30,times=length(iYs)),iYs)
t_25 <- mapply(function(x,y){length(fYLTmp_l(x,y))}, rep(25,times=length(iYs)),iYs)

#グラフ設定
png("真夏日猛暑日熱帯夜.png", height=800, width=1200, res=200)
par(mar=c(3, 3, 1.5, 1)) #余白設定
par(mgp=c(2, 0.7, 0))  #グラフ枠と軸との間隔設定
par(xaxs = "i")        #データ範囲とグラフの範囲(X軸)
par(yaxs = "i")        #データ範囲とグラフの範囲(Y軸)

#枠だけ作る
plot(iYs, t_35, type="n", xlim=c(min(iYs),max(iYs)), ylim=c(0,30),
xlab="西暦[年]", ylab="該当日数[日]")

#プロット①
lines(iYs, t_35, type="b", pch=20, col=rgb(1,0,0), lty=1)
lines(iYs, t_325, type="b", pch=1, col=gray(0.5), lty=2)
lines(iYs, t_30, type="b", pch=20, col=rgb(0,0,1), lty=1)
lines(iYs, t_25, type="b", pch=18, col=rgb(0,0.5,0), lty=1)

#凡例
legend("topleft", pch=c(20,1,20,18), col=c(rgb(1,0,0),gray(0.5),rgb(0,0,1),rgb(0,0.5,0)),lty=c(1,2,1,1),
 legend=c("猛暑日","最高:32.5℃以上","真夏日","熱帯夜")
)
dev.off()