<- read.csv("co2.csv", header=FALSE)
co2 head(co2)
V1 V2 V3
1 2024/5/17 17:41:15 633
2 2024/5/17 17:41:18 633
3 2024/5/17 17:41:27 637
4 2024/5/17 17:41:30 638
5 2024/5/17 17:41:33 639
6 2024/5/17 17:41:36 639
CSVファイルはread.csv()
で読み込むことができます。 この函数は、data.frameと呼ばれる、リストに似たオブジェクト返します。 行や列に名前を付けて参照することができます。
二酸化炭素の測定をして、1列目が日付、2列目が時刻、3列目が測定値というCSVファイルが得られたとします。
<- read.csv("co2.csv", header=FALSE)
co2 head(co2)
V1 V2 V3
1 2024/5/17 17:41:15 633
2 2024/5/17 17:41:18 633
3 2024/5/17 17:41:27 637
4 2024/5/17 17:41:30 638
5 2024/5/17 17:41:33 639
6 2024/5/17 17:41:36 639
列に名前を付けましょう。
names(co2) <- c("date", "time", "co2")
名前を使ってco2$date
またはco2[["date"]]
とすると、列をベクトルとして取得できます。 co2$["date"]
はdate
を残したdata.frameを返します。
日付と時刻をPOSIXct
に変換しておくと、時系列データを扱うときに便利です。 POSIXct
はRの日時オブジェクトの一つで、基準時刻からの秒数で表します。 ct
はcalendar timeを意味します。 POSIXlt
はlocal timeで要素を整数のベクトルで表します。
$datetime <- as.POSIXct(paste(co2$date, co2$time))
co2head(co2)
date time co2 datetime
1 2024/5/17 17:41:15 633 2024-05-17 17:41:15
2 2024/5/17 17:41:18 633 2024-05-17 17:41:18
3 2024/5/17 17:41:27 637 2024-05-17 17:41:27
4 2024/5/17 17:41:30 638 2024-05-17 17:41:30
5 2024/5/17 17:41:33 639 2024-05-17 17:41:33
6 2024/5/17 17:41:36 639 2024-05-17 17:41:36
不要な列はNULL
を代入して削除します。
$date <- NULL
co2$time <- NULL co2
時間変化をプロットしてみましょう。
plot(co2$datetime, co2$co2, type="l", xlab="Date", ylab="CO2 concentration")
type="l"
は線グラフを指定します。xlab
とylab
で軸のラベルを指定します。
頻度分布を調べるために、ヒストグラムを描いてみましょう。
hist(co2$co2, breaks=20, main="CO2 concentration histogram", xlab="CO2 concentration")
箱ひげ図を描いてみましょう。
<- boxplot(co2$co2, main="CO2 concentration boxplot", ylab="CO2 concentration") bp
箱は四分位数を表し、箱の中の線は中央値を表します。 ひげは四分位範囲の1.5倍の範囲を表しその範囲を超える値は外れ値と言います。 点で示されている外れ値を取り除くには次のようにします。
<- co2[co2$co2 >= bp$stats[1] & co2$co2 <= bp$stats[5], ] co2
過去のAMeDASデータは、気象庁 > 各種データ・資料 > 過去の気象データ・ダウンロードから取得できます。 ファイル形式を参考にして読み解いていきます。 地点や変数等を選択します。 変数が多かったり、期間が長すぎたりすると、サイズの上限に達してしまいます。 その場合は、必要な変数や期間を絞ってください。 複数の地点を選択することもできますが、ここでは1地点を選んでください。 ここでは、一部に欠測とみなすデータが含まれている、四日市における降水量の合計(mm)、最高気温(℃)、日照時間(時間)について、2017年1年分の日別値を取得しました。
読み込んだデータはRを使って整理することができます。 例を見てみましょう。
列の名前は後でデータから拾ってつけるので、header=FALSE
とします。 第1~3行目はダウンロードした時刻、空行、地点名などですので、skip=3
で無視します。 R 4.2からはUTF-8が標準になりました。 AMeDASデータのファイル形式はShift JIS(cp932)なので、fileEncoding="cp932"
を渡します。
<- read.csv("data.csv", header=FALSE, skip=3, fileEncoding="cp932")
raw head(raw)
V1 V2 V3 V4 V5
1 年月日 降水量の合計(mm) 降水量の合計(mm) 降水量の合計(mm) 降水量の合計(mm)
2
3 現象なし情報 品質情報 均質番号
4 2017/1/1 0 1 8 1
5 2017/1/2 0 1 8 1
6 2017/1/3 0.0 0 8 1
V6 V7 V8 V9 V10
1 最高気温(℃) 最高気温(℃) 最高気温(℃) 日照時間(時間) 日照時間(時間)
2
3 品質情報 均質番号 現象なし情報
4 12.2 8 1 3.5 0
5 12.9 8 1 8.2 0
6 12.8 8 1 5.7 0
V11 V12
1 日照時間(時間) 日照時間(時間)
2
3 品質情報 均質番号
4 8 1
5 8 1
6 8 1
2行目のNA
を消しておきます。 raw[3,] == "品質情報"
は2行目の各要素が「品質情報」であればTRUE
、それ以外はFALSE
であるベクトルです。
3, is.na(raw[3,])] <- ""
raw[3,] == "品質情報" raw[
V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12
3 FALSE FALSE FALSE TRUE FALSE FALSE TRUE FALSE FALSE FALSE TRUE FALSE
これを列の論理添字としてTRUEの列について7より大きいか調べ、論理ベクトルを作ります。 出力が長いので
head(raw[,raw[3,] == "品質情報"] > 7)
V4 V7 V11
[1,] TRUE TRUE TRUE
[2,] FALSE FALSE FALSE
[3,] TRUE TRUE TRUE
[4,] TRUE TRUE TRUE
[5,] TRUE TRUE TRUE
[6,] TRUE TRUE TRUE
apply()
はRの強力な函数で、1番目の引数として渡す配列の次元(MARGIN、2番目の引数)に対して、3番目に渡す函数を適用します。 ここではall
を渡します。
head(apply(raw[,raw[3,] == "品質情報"] > 7, 1, all))
[1] TRUE FALSE TRUE TRUE TRUE TRUE
均質番号と品質情報以外のデータの列を特定します。
!(raw[3, ] == "均質番号" | raw[3,] == "品質情報")
V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12
3 TRUE TRUE TRUE FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE FALSE
品質情報が全て8(正常値)である行、データが含まれる列を残します。
<- raw[apply(raw[,raw[3,] == "品質情報"] > 7, 1, all),
filtered !(raw[3, ] == "均質番号" | raw[3,] == "品質情報")]
head(filtered)
V1 V2 V3 V6 V9
1 年月日 降水量の合計(mm) 降水量の合計(mm) 最高気温(℃) 日照時間(時間)
3 現象なし情報
4 2017/1/1 0 1 12.2 3.5
5 2017/1/2 0 1 12.9 8.2
6 2017/1/3 0.0 0 12.8 5.7
7 2017/1/4 0.0 0 12.9 3.4
V10
1 日照時間(時間)
3 現象なし情報
4 0
5 0
6 0
7 0
1行目と2行目をつなげて列の名前として使います。
names(filtered) <- paste(filtered[1,], filtered[2,])
names(filtered)
[1] "年月日 " "降水量の合計(mm) "
[3] "降水量の合計(mm) 現象なし情報" "最高気温(℃) "
[5] "日照時間(時間) " "日照時間(時間) 現象なし情報"
Rで負の添え字は、その添え字を取り除くことを意味します。 Numpyのように後ろから数えるのではないことに注意しましょう。 1~2行目はデータではないので削除します。
<- filtered[-(1:2),]
filtered head(filtered)
年月日 降水量の合計(mm) 降水量の合計(mm) 現象なし情報 最高気温(℃)
4 2017/1/1 0 1 12.2
5 2017/1/2 0 1 12.9
6 2017/1/3 0.0 0 12.8
7 2017/1/4 0.0 0 12.9
8 2017/1/5 0 1 10.0
9 2017/1/6 0 1 9.5
日照時間(時間) 日照時間(時間) 現象なし情報
4 3.5 0
5 8.2 0
6 5.7 0
7 3.4 0
8 7.7 0
9 7.6 0
大気の中には主要成分だけでなく、量は少ないが重要な働きをする微量成分があります。 二酸化炭素は人為起源の排出が原因で増加し続けています。 その様子をグラフにしてみましょう。 気象庁のWord Data Centre for Greenhouse Gases https://gaw.kishou.go.jp/publications/global_mean_mole_fractionsから年平均csvデータ(Global annual mean mole fractions)のCO2ファイルをダウンロードし、作業ディレクトに保存します。
<- read.csv("co2_annual_20221026.csv")
df plot(df$year, df$co2.global.mean.ppm.)
read.csv()
はコンマ区切り(CSV, comma separated value)のデータを読む函数です。 ファイル名は文字列であることを表すために""
で囲みます。 ファイル名の日付の部分は変わります。 グラフの種類を指定しないと、散布図になります。
df
には読んだ表の中身が入ります。df
はデータフレームと呼ばれるクラスのデータ構造です。データフレームは、値が行列に並んでいるだけでなく、行や列に名前がつけられます。
グラフにタイトルをつけ、軸のラベルを変更します。タイトルはmain
で、軸ラベルはxlab
、ylab
で指定します。
plot(df$year, df$co2.global.mean.ppm.,
main="Global mean CO2 concentration",
xlab="year", ylab="CO2 ppm")
次に月平均データ(Global monthly mean mole fractions)を使って簡単な時系列解析をしてみます。
<- read.csv("co2_monthly_20231115.csv") dfm
月毎の平均を求めてみます。
<- aggregate(mole.fraction.ppm. ~ month, data = dfm, mean)
co2.annual.cycle co2.annual.cycle
month mole.fraction.ppm.
1 1 378.0431
2 2 378.4523
3 3 378.7062
4 4 378.7826
5 5 378.3562
6 6 377.1728
7 7 375.5664
8 8 374.6354
9 9 375.1223
10 10 376.7510
11 11 378.3100
12 12 379.3197
プロットしてみましょう。
plot(co2.annual.cycle)
8月に一番少なく、1月に一番多くなっています。
<- dfm$mole.fraction.ppm.
co2.mon <- nrow(dfm)
n <- ts(co2.mon, start=c(dfm$year[1], dfm$month[1]), frequency=12)
co2.mon <- decompose(co2.mon)
co2.mon.decompplot(co2.mon.decomp)
ts()
は一つ目の引数のデータから時系列オブジェクトを作ります。 frequency=12
は1年を単位として12回の頻度であることを示します。 decompose()
はデータをトレンド、周期成分と残差に分解します。
残差をさらにスペクトル分解してみましょう。
spec.pgram(co2.mon.decomp$random, spans=c(7,7), na.action=na.omit)
abline(v=1)
abline(v=1/3)
spec.pgram
は高速フーリエ変換を利用して、ピリオドグラムを計算します。 spans
で修正ダニエル法に基づいた平滑化を施すことができます。 右上の青い線は信頼区間を表します。 co2.mon.decomp$random
には最初と最後に数値でない値(not a number)をna
が入っていますので、na.action
で無視します。 ピークに近い、周期1年と3年に対応するところに縦線を入れてみました。 それぞれ年々変動とエルニーニョ現象のような数年周期に対応しているものと考えられます。
Rでは、このように対話的な簡単な操作により、簡単に解析やグラフの作成ができます。
自分で計測したCO2データをグラフにしてみましょう。
df
というテーブルがあり、date
という名前の列に2024/7/15
、time
という列に12:00:00
などのようにデータが入っているとします。これらをRの日時を表す型に変換して、列として追加するには次のようにします。
$datetime <- as.POSIXct(paste(df$date, df$time)) df
POSIXct
型は1970年1月1日00:00:00からの秒数です。これを横軸に取ると良いでしょう。
気象庁は様々なデータをCSV形式で提供しています。 それらをRで読んでみましょう。 うまく読めるでしょうか。