本文へスキップ
からだにいいもの

Rのトピックスを中心に『まだ、まだ、知らない、役に立つ情報?』を発信します。

Rで解析:時刻データフレームを期間ごとにサブセット・フラグ付けする「timeDF」パッケージの紹介

時系列データの解析や可視化は、多くの分野において重要な作業です。特に、経済や金融などの領域では、時間を軸としたデータの分析が不可欠です。しかしながら、日付や時刻情報を含む大規模なデータセットを扱う場合、データのサブセット化や期間ごとの区分けは非常に困難な作業です。

本パッケージでは、データフレームに時刻情報を付与してtimeDFオブジェクトとして扱い、periodDFオブジェクトで定義した期間ごとにデータをサブセット化・フラグ付けすることができます。例えば、特定の期間に含まれるレコードだけを抽出したり、一定の時間間隔でデータを分割したりすることが可能です。

時刻情報を持つデータフレームを統一的に扱えるのが特徴です。期間はtime(時刻の範囲)、date(日付の範囲)、time_in_a_day(1日の中の時間帯)の3種類で用途に応じて使い分けが考えられます。

パッケージバージョンは0.9.1。Windows 11 x64 (build 26200)のR version 4.6.1で確認しています。

パッケージのインストール

下記コマンドを実行してください。

# パッケージのインストール
install.packages("timeDF")
# パッケージの読み込み
library("timeDF")
スポンサーリンク

コマンド例

詳細はコメント、パッケージのヘルプを確認してください。

時刻情報を持つデータフレームをtimeDFオブジェクトに変換:as.timeDFコマンド

オプション意味初期値
df時刻の列を文字列として持つデータフレーム
time_varデータフレーム内の時刻列の列名を指定“time”
format時刻の形式を指定;”as_is”を指定すると変換せずそのまま使用(列はUTCタイムゾーンのPOSIXltである必要がある)“%Y-%m-%d %H:%M:%S”
# 時刻データフレームを作成
time_df = data.frame(
    time = c("2023-12-01 01:00:00",
             "2023-12-01 02:00:00",
             "2023-12-01 03:00:00",
             "2023-12-01 04:00:00"),
    value = c(123,
              144,
              150,
              100)
)
# timeDFオブジェクトに変換
as.timeDF(time_df)

実行結果:

time value
1 2023-12-01 01:00:00   123
2 2023-12-01 02:00:00   144
3 2023-12-01 03:00:00   150
4 2023-12-01 04:00:00   100

リストにまとめられた時系列データを1つのtimeDFオブジェクトに変換:listTimeDF_to_timeDFオプション

オプション意味初期値
listTimeDF時系列データのリスト
name_var元のリストから取得した名前を保持する列名“name”
# 時刻データフレームを作成
time_df = as.timeDF(
    data.frame(
        time = c("2024-01-01 01:00:00",
                 "2024-02-02 02:00:00",
                 "2024-03-03 03:00:00",
                 "2024-04-04 04:00:00",
                 "2024-05-05 05:00:00"),
        value = c(123,
                  144,
                  150,
                  100,
                  180)
    ))
# 期間データフレームを作成
period_df = as.periodDF(
    data.frame(
        start = c(
            "2024-01-01",
            "2024-02-01",
            "2024-03-01",
            "2024-04-01",
            "2024-05-01"
        ),
        end = c(
            "2024-01-31",
            "2024-02-29",
            "2024-03-31",
            "2024-04-30",
            "2024-05-31"
        ),
        label = c(
            "Jan",
            "Feb",
            "Mar",
            "Apr",
            "May"
        )
    ),
    period_type = "date",
    label_var = "label"
    )

# 期間ごとに時刻データフレームを抽出してリスト化
listTimeDF = extract_with_periodDF(
                 time_df,
                 period_df,
                 include="both")
# リストを1つのtimeDFオブジェクトにまとめる
listTimeDF_to_timeDF(listTimeDF)

実行結果:

time value name
1 2024-01-01 01:00:00   123  Jan
2 2024-02-02 02:00:00   144  Feb
3 2024-03-03 03:00:00   150  Mar
4 2024-04-04 04:00:00   100  Apr
5 2024-05-05 05:00:00   180  May

日付や時間の区間を表すperiodDFオブジェクトを作成:as.periodDFコマンド

オプション意味初期値
df期間の定義データフレーム
period_type指定する期間の種類を定義する要素:”time”、”date”、”time_in_a_day”のいずれか
formatstart・end列の日時形式を指定;”auto”の場合はperiod_typeに応じて自動選択、”as_is”の場合は変換せずそのまま使用(timeはUTCタイムゾーンのPOSIXltまたはPOSIXct、dateはDate、time_in_a_dayは0~86400の数値である必要がある)“auto”
start_var開始日時の列名を指定“start”
end_var終了日時の列名を指定“end”
label_varラベル列名を指定NULL
# 時刻の期間データフレームを作成
period_time = data.frame(
     start = c("2023-12-01 01:00:00",
               "2023-12-01 02:00:00",
               "2023-12-01 03:00:00",
               "2023-12-02 04:00:00"),
     end = c("2023-12-01 02:00:00",
             "2023-12-01 03:00:00",
             "2023-12-01 04:00:00",
             "2023-12-02 05:00:00")
)
# periodDFオブジェクトに変換
as.periodDF(period_time, "time")

# 日付の期間データフレームを作成
period_date = data.frame(
    start = c("2023-01-01",
              "2023-02-01",
              "2023-03-01"),
    end = c("2023-01-14",
            "2023-02-14",
            "2023-03-14"),
    label = c("Jan", "Feb", "Mar")
)
# periodDFオブジェクトに変換
as.periodDF(period_date, "date")

# 1日の時間帯の期間データフレームを作成
period_time_in_a_day = data.frame(
    start = c("04:00",
              "11:00",
              "17:00"),
    end = c("11:00",
            "17:00",
            "24:00"),
    label = c("morning",
              "afternoon",
              "evening")
)
# periodDFオブジェクトに変換(ラベル付き)
as.periodDF(period_time_in_a_day,
            "time_in_a_day",
            label_var = "label")

実行結果:

# periodDFオブジェクトに変換
> as.periodDF(period_time, "time")
                start                 end
1 2023-12-01 01:00:00 2023-12-01 02:00:00
2 2023-12-01 02:00:00 2023-12-01 03:00:00
3 2023-12-01 03:00:00 2023-12-01 04:00:00
4 2023-12-02 04:00:00 2023-12-02 05:00:00

# periodDFオブジェクトに変換
> as.periodDF(period_date, "date")
       start        end label
1 2023-01-01 2023-01-14   Jan
2 2023-02-01 2023-02-14   Feb
3 2023-03-01 2023-03-14   Mar

# periodDFオブジェクトに変換(ラベル付き)
> as.periodDF(period_time_in_a_day,
+             "time_in_a_day",
+             label_var = "label")
  start   end     label
1 14400 39600   morning
2 39600 61200 afternoon
3 61200 86400   evening

指定された期間の開始と終了の時刻を要約する例:summary.periodDFコマンド

オプション意味初期値
objectS3期間クラス
# 期間データフレームを作成
period_time = data.frame(
    start = c("2023-12-01 01:00:00",
             "2023-12-01 02:00:00",
             "2023-12-01 03:00:00",
             "2023-12-02 04:00:00"),
    end = c("2023-12-01 01:00:00",
             "2023-12-01 02:00:00",
             "2023-12-01 03:00:00",
             "2023-12-02 04:00:00")
)
# periodDFオブジェクトに変換
periodDF = as.periodDF(period_time, "time")
# 概要を要約
summary(periodDF)

実行結果:

# 概要を要約
summary(periodDF)
$class
[1] "periodDF"

$period_type
[1] "time"

$`# of rows`
[1] 4

$start_var
[1] "start"

$end_var
[1] "end"

$label_var
NULL

$`start range`
[1] "2023-12-01 01:00:00 - 2023-12-02 04:00:00"

$`end range`
[1] "2023-12-01 01:00:00 - 2023-12-02 04:00:00"

timeDFオブジェクトの概要を要約:summary.timeDFコマンド

オプション意味初期値
objectS3時間クラス
# 時刻データフレームを作成
time_df = data.frame(
        time = c("2023-12-01 01:00:00",
                 "2023-12-01 02:00:00",
                 "2023-12-01 03:00:00",
                 "2023-12-02 04:00:00"),
        value = c(123,
                  144,
                  150,
                  100)
    )
# timeDFオブジェクトに変換
timeDF = as.timeDF(time_df)
# timeDFオブジェクトの概要を表示
summary(timeDF)

実行結果:

# timeDFオブジェクトの概要を表示
summary(timeDF)
$class
[1] "timeDF"

$`# of rows`
[1] 4

$time_var
[1] "time"

$`time range`
[1] "2023-12-01 01:00:00 - 2023-12-02 04:00:00"

特定の期間内で、指定された時間の記録を抽出:extract_with_periodDFコマンド

オプション意味初期値
timeDF時系列オブジェクト
periodDF期間オブジェクト
include期間の両端を含めるかどうかを指定;”both”(両端)、”right”(右端のみ)、”left”(左端のみ)、”none”(含めない)のいずれか
modStart期初に加算する値0
modEnd期末に加算する値0
modUnitsmodStart・modEndの値の単位NULL
outputAsBool真偽値;TRUEの場合、返り値は抽出するレコードを表すブール値ベクトル(またはそのリスト)FALSE
unitsmodUnitsに置き換えられる非推奨の引数NULL
# 時刻データフレームを定義
time_df = data.frame(
    time = c("2023-01-01 12:00:00",
             "2023-01-21 12:00:00",
             "2023-02-10 12:00:00",
             "2023-03-02 12:00:00",
             "2023-03-22 12:00:00",
             "2023-04-11 12:00:00"
    ),
    value = c(123, 144, 150, 100, 130, 145)
)
# 時刻データフレームを変換
timeDF = as.timeDF(time_df)

# 抽出範囲を指定
period_df = data.frame(
    start = c("2023-01-01",
              "2023-02-01",
              "2023-03-01"),
    end = c("2023-01-31",
            "2023-02-28",
            "2023-03-31"),
    label = c("Jan", "Feb", "Mar")
)
# 抽出範囲をデータフレームに変換
periodDF = as.periodDF(period_df, "date", label_var = "label")

# 時刻データフレームから指定の期間で抽出
extract_with_periodDF(timeDF, periodDF, "both")

実行結果:

$Jan
                 time value
1 2023-01-01 12:00:00   123
2 2023-01-21 12:00:00   144

$Feb
                 time value
3 2023-02-10 12:00:00   150

$Mar
                 time value
4 2023-03-02 12:00:00   100
5 2023-03-22 12:00:00   130

一定間隔で区切られた時間の範囲に分割:split_timeDF_by_intervalsコマンド

オプション意味初期値
timeDF時系列オブジェクト
byN間隔の数値
byUnits間隔の単位:”days”、”hours”、”mins”のいずれか
modStart間隔の始まりに加える値0
modEnd間隔の終わりに加える値0
modUnitsmodStart・modEndの値の単位“auto”
# 時刻データフレームの作成
time_df = data.frame(
    time = c("2023-01-01 08:00:00",
             "2023-01-01 12:00:00",
             "2023-01-01 16:00:00",
             "2023-01-02 08:00:00",
             "2023-02-02 10:00:00",
             "2023-03-03 11:00:00",
             "2023-03-03 16:00:00",
             "2023-03-05 12:00:00"
    ),
    value = c(123, 144, 150, 100,
              130, 145, 180, 100)
)
# 時刻データフレームに変換
timeDF = as.timeDF(time_df)
# 時刻データを日単位で分割
split_timeDF_by_intervals(timeDF, 1, "days")

実行結果:

# 時刻データを日単位で分割
$`2023-01-01`
                 time value
1 2023-01-01 08:00:00   123
2 2023-01-01 12:00:00   144
3 2023-01-01 16:00:00   150

$`2023-01-02`
                 time value
4 2023-01-02 08:00:00   100

$`2023-01-03`
[1] time  value
<0 rows> (or 0-length row.names)

$`2023-01-04`
[1] time  value
<0 rows> (or 0-length row.names)

$`2023-01-05`
[1] time  value
…(以下略)

ベクトルから日付や時間の区間を表すperiodDFオブジェクトを作成:vec_to_periodDFコマンド

オプション意味初期値
vec期間の始まりを表すベクトル;pre_marginが指定された場合、各期間は始まりから前方に計算
period_type指定する期間の種類を定義する要素:”time”、”date”、”time_in_a_day”のいずれか
duration各期間の長さを表す数値
unitsdurationの単位を表す要素
formatvecの日時形式を指定;”auto”の場合はperiod_typeに応じて自動選択、”as_is”の場合は変換せずそのまま使用(timeはUTCタイムゾーンのPOSIXltまたはPOSIXct、dateはDate、time_in_a_dayは0~86400の数値である必要がある)“auto”
labels各期間ごとの使用ラベルNULL
pre_margin数値;指定すると、各期間がvecで指定された開始位置から前方に計算0
# 時刻の配列を定義
start_time = c("2023-12-01 01:00:00",
               "2023-12-02 02:00:00",
               "2023-12-03 03:00:00",
               "2023-12-04 04:00:00")
# 時刻の期間オブジェクトを作成
vec_to_periodDF(start_time, "time", 1, "hours")

# 日付の配列を定義
start_date = c("2023-01-01",
               "2023-02-01",
               "2023-03-01")
# 日付の期間オブジェクトを作成し、ラベルを設定
vec_to_periodDF(start_date, "date", 14, "days",
                      labels = c("Jan", "Feb", "Mar"))

# 1日の時間帯の配列を定義
start_time_in_a_day = c("06:00",
                        "11:00",
                        "18:00")
# 1日の時間帯の期間オブジェクトを作成し、ラベルを設定
vec_to_periodDF(start_time_in_a_day, "time_in_a_day",
                      4, "hours",
                      labels = c("morning", "afternoon", "evening"))

実行結果:

# 時刻の期間オブジェクトを作成
vec_to_periodDF(start_time, "time", 1, "hours")
                start                 end
1 2023-12-01 01:00:00 2023-12-01 02:00:00
2 2023-12-02 02:00:00 2023-12-02 03:00:00
3 2023-12-03 03:00:00 2023-12-03 04:00:00
4 2023-12-04 04:00:00 2023-12-04 05:00:00

# 日付の期間オブジェクトを作成し、ラベルを設定
vec_to_periodDF(start_date, "date", 14, "days",
                labels = c("Jan", "Feb", "Mar"))
       start        end label
1 2023-01-01 2023-01-15   Jan
2 2023-02-01 2023-02-15   Feb
3 2023-03-01 2023-03-15   Mar

# 1日の時間帯の期間オブジェクトを作成し、ラベルを設定
vec_to_periodDF(start_time_in_a_day, "time_in_a_day",
                 4, "hours", labels = c("morning", "afternoon", "evening"))
  start   end     label
1 21600 14400   morning
2 39600 14400 afternoon
3 64800 14400   evening

指定された期間の開始と終了の時刻を調整:adjust_periodDFコマンド

オプション意味初期値
periodDFS3期間クラス
adjStart開始に加算する値
adjEnd終了に加算する値
unitsadjStart・adjEndの値の単位
# 時刻の期間データフレームを作成
period_time = data.frame(
     start = c("2023-12-01 03:00:00",
               "2023-12-01 20:00:00",
               "2023-12-02 05:00:00",
               "2023-12-03 21:00:00"),
     end = c("2023-12-01 04:00:00",
             "2023-12-01 21:00:00",
             "2023-12-02 06:00:00",
             "2023-12-03 22:00:00")
)

# periodDFオブジェクトに変換
periodTime = as.periodDF(period_time, "time")
# 開始を1時間前倒し、終了を3時間後ろ倒しに調整
adjust_periodDF(periodTime, -1, 3, units="hours")

# 日付の期間データフレームを作成
period_date = data.frame(
    start = c("2023-01-01",
              "2023-02-01",
              "2023-03-01",
              "2023-04-01"),
    end = c("2023-01-14",
            "2023-02-14",
            "2023-03-14",
            "2023-04-14"),
    label = c("One", "Two", "Three", "Four")
)
# periodDFオブジェクトに変換
periodDate = as.periodDF(period_date, "date")
# 開始を1日前倒し、終了を1日後ろ倒しに調整
adjust_periodDF(periodDate, -1, 1, units="days")

# 1日の時間帯の期間データフレームを作成
period_time_in_a_day = data.frame(
    start = c("04:00",
              "11:00",
              "17:00"),
    end = c("11:00",
            "17:00",
            "24:00"),
    label = c("morning",
              "afternoon",
              "evening")
)
# periodDFオブジェクトに変換(ラベル付き)
periodTimeInDay = as.periodDF(period_time_in_a_day, "time_in_a_day", label_var = "label")
# 開始・終了をそれぞれ1時間後ろ倒しに調整
adjust_periodDF(periodTimeInDay, 1, 1, "hours")

実行結果:

# 開始を1時間前倒し、終了を3時間後ろ倒しに調整
adjust_periodDF(periodTime, -1, 3, units="hours")
                start                 end
1 2023-12-01 02:00:00 2023-12-01 07:00:00
2 2023-12-01 19:00:00 2023-12-02 00:00:00
3 2023-12-02 04:00:00 2023-12-02 09:00:00
4 2023-12-03 20:00:00 2023-12-04 01:00:00

# 開始を1日前倒し、終了を1日後ろ倒しに調整
adjust_periodDF(periodDate, -1, 1, units="days")
       start        end label
1 2022-12-31 2023-01-15   One
2 2023-01-31 2023-02-15   Two
3 2023-02-28 2023-03-15 Three
4 2023-03-31 2023-04-15  Four

# 開始・終了をそれぞれ1時間後ろ倒しに調整
adjust_periodDF(periodTimeInDay, 1, 1, "hours")
   start   end     label
1  18000 43200   morning
2  43200 64800 afternoon
3  64800 86400   evening
31     0  3600   evening


この記事が誰かの役に立ちますように。

スポンサーリンク