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

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

Rで解析:コードと範囲を分かりやすいラベルへ変換する「ksformat」パッケージ

データ分析の現場では、コードや数値をそのまま扱うよりも、意味の分かるラベルへ置き換えて集計すると結果が伝わりやすくなります。しかし、区分ごとの対応表や範囲の判定条件をスクリプトのなかへ個別に書き込む作業には手間がかかります。

本パッケージは、値とラベルの対応づけを「書式」として定義し、繰り返し利用することを簡単におこなえるパッケージです。離散値の対応づけ、数値や日付の範囲によるラベル付け、複数のラベルが同時に一致する多重ラベルの取得、ラベルから元の値への逆引きをおこなうコマンドが収録されています。さらに、SASの「PROC FORMAT」に近い書式でテキストから定義を読み込むことや、定義した書式をテキストとして書き出すことも可能です。本パッケージの利用で、コードとラベルの対応づけを一元的に管理し、分析結果の可読性を高められるのではないかと考えます。

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

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

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

# パッケージのインストール
install.packages("ksformat")

# パッケージの読み込み
library("ksformat")
スポンサーリンク

コマンド例

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

本パッケージが再現しているSASの「PROC FORMAT」は、数値や文字列に対してラベルを割り当てる対応表を定義しておき、集計や出力の際に呼び出して利用する機能です。ksformatでは、定義した書式へ名前を付けてグローバルな書式ライブラリへ登録し、名前を指定して何度でも呼び出す方式を採用しています。

以下のコマンド例では、架空の「みなと市立図書館」における貸出管理データを題材としています。会員区分コード、資料区分コード、延滞日数、館内滞在時間などを、集計や帳票に適したラベルに変換していきます。

書式定義の作成:fnewコマンド

値とラベルの対応関係を定義し、書式オブジェクトを作成します。nameを指定すると書式ライブラリへ自動的に登録されます。

なお、数値パターンで小数桁を 0 かつ幅指定なしで指定する、例えば「fnew(“%,.0f円”, name = “entai_ryokin”, type = “numeric”)」だとfputnコマンドなどでformatC(width = 0) が「width cannot be zero」で停止するバグ?があるようです。

オプション意味初期値
値とラベルの対応を定義する名前付き引数、名前付きベクトル、リスト、fmapコマンドの結果、数値パターン文字列、および.missingや.otherといった特殊指定なし
name書式に付ける名前で、指定すると書式ライブラリへ自動登録されるNULL
type書式の型で、”character”、”numeric”、”Date”、”POSIXct”、”logical”、”date_range”、”datetime_range”、”auto”から指定“auto”
defaultどの対応にも一致しない値へ付けるラベルで、.otherの指定を上書きするNULL
multilabel範囲の重複を許可し、1つの値が複数のラベルへ一致することを認めるかの指定FALSE
ignore_case文字型の書式で、キーの照合時に大文字と小文字を区別しないかの指定FALSE
date_format日付や日時の範囲キーを解析する際に用いるstrptime形式の文字列で、NULLの場合はISO 8601形式で解析するNULL
range_subtypetype = “stratified_range”の場合に、範囲部分の解析方法を”numeric”、”date”、”datetime”から指定“numeric”
strata_septype = “stratified_range”の場合に、層の識別子と範囲キーを区切る文字“|”
verbose作成した書式オブジェクトを可視で返すかの指定FALSE
# 会員区分コードとラベルの対応を定義し、書式ライブラリへ登録
fnew(
  "IP" = "一般",
  "GK" = "学生",
  "SN" = "シニア",
  "HG" = "法人",
  .missing = "区分未登録",
  .other = "対象外区分",
  name = "kaiin")

# 登録した書式を名前で呼び出して適用
fput(c("IP", "GK", "SN", NA, "ZZ"), "kaiin")

# 年齢の範囲へ年代区分ラベルを定義し、範囲の重複を許可
fnew(
  "0,12,TRUE,TRUE"   = "児童",
  "13,17,TRUE,TRUE"  = "生徒",
  "18,64,TRUE,TRUE"  = "一般成人",
  "65,Inf,TRUE,TRUE" = "高齢者",
  "0,17,TRUE,TRUE"   = "未成年",
  name = "nenrei",
  type = "numeric",
  multilabel = TRUE)

# 一致した範囲のうち1件のみを取得
fput(c(9, 15, 42, 78), "nenrei")
[1] "児童"     "未成年"   "一般成人" "高齢者"  

# 一致したすべての範囲のラベルをリストで取得
fput_all(c(9, 15, 42, 78), "nenrei")
[[1]]
[1] "児童"   "未成年"

[[2]]
[1] "未成年" "生徒"  

[[3]]
[1] "一般成人"

[[4]]
[1] "高齢者"

# 延滞料金を通貨表記へ変換する数値パターン書式を定義
fnew("%,1.0f円", name = "entai_ryokin", type = "numeric")

### 数値パターンで小数桁を 0 かつ幅指定なしで指定すると
### fputnコマンドなどでformatC(width = 0) が「width cannot be zero」で停止する
### fnew("%,.0f円", name = "entai_ryokin", type = "numeric")

# 数値ベクトルへ数値パターン書式を適用
fputn(c(120, 3400, 0), "entai_ryokin")
[1] "120円"   "3,400円" "0円"   

# 書式ライブラリを初期化
fclear()
All formats cleared from library.

書式の適用:fputコマンド

定義済みの書式をベクトルへ適用します。ラベルをeコマンドで囲むと、適用時に評価されるR式として扱われ、追加引数を差し込んだ文字列を生成できます。

オプション意味初期値
x書式を適用する値のベクトルなし
formatks_formatオブジェクト、または書式ライブラリへ登録済みの書式名なし
式ラベルへ渡す追加引数で、位置の順に.x1、.x2として参照されるなし
keep_naTRUEの場合、欠損値へ.missingのラベルを適用せずNAのまま保持するFALSE
# 資料区分コードの書式を定義
fnew(
  "TS" = "図書",
  "ZS" = "雑誌",
  "AV" = "視聴覚資料",
  .missing = "未分類",
  name = "shiryo")

# 欠損値へ.missingで指定したラベルを適用
fput(c("TS", "ZS", NA, "AV"), "shiryo")
[1] "図書"       "雑誌"       "未分類"     "視聴覚資料"

# keep_naをTRUEとして欠損値をNAのまま保持
fput(c("TS", "ZS", NA, "AV"), "shiryo", keep_na = TRUE)
[1] "図書"       "雑誌"       NA           "視聴覚資料"

# 延滞日数の範囲ごとに、適用時へ評価される式ラベルを定義
fnew(
  "0,0,TRUE,TRUE"   = "延滞なし",
  "1,7,TRUE,TRUE"   = e('paste0(.x1, "様:返却期限を過ぎています")'),
  "8,Inf,TRUE,TRUE" = e('paste0(.x1, "様:至急ご返却をお願いします")'),
  name = "tokusoku",
  type = "numeric")

# 利用者名のベクトルを.x1として渡し、氏名を差し込んだ督促文面を生成
fput(c(0, 3, 20), "tokusoku", c("青木", "井上", "梅田"))
[1] "延滞なし"                         "井上様:返却期限を過ぎています"   "梅田様:至急ご返却をお願いします"

# 書式ライブラリを初期化
fclear()
All formats cleared from library.

キーと値の対応関係の作成:fmapコマンド

キーのベクトルと値のベクトルから、書式の材料となる対応関係を作成します。データフレームの列などから対応表を組み立てる場合に利用します。

オプション意味初期値
keys照合に用いる入力キーの文字ベクトルなし
values出力するラベルやオブジェクトのベクトルで、文字型のほか数値型、Date型、POSIXct型、論理型を指定できるなし
# 分館コードのベクトルを作成
bunkan_code <- c("HON", "MIN", "KIT")

# 分館名のベクトルを作成
bunkan_name <- c("本館", "港南分館", "北浜分館")

# コードと名称の対応関係を作成し、そのまま書式として登録
fmap(bunkan_code, bunkan_name) |> fnew(name = "bunkan")

# 分館コードへ書式を適用
fput(c("KIT", "HON"), "bunkan")
[1] "北浜分館" "本館"

# 蔵書IDのベクトルを作成
zosho_id <- c("B-1001", "B-1002", "B-1003")

# 受入日のベクトルをDate型で作成
ukeire_bi <- as.Date(c("2024-05-13", "2025-01-20", "2026-03-02"))

# 値をDate型のまま保持する書式として登録
fmap(zosho_id, ukeire_bi) |> fnew(type = "Date", name = "ukeirebi")

# 蔵書IDから受入日を取得
fput(c("B-1003", "B-1001"), "ukeirebi")
[1] "2026-03-02" "2024-05-13"

# 書式ライブラリを初期化
fclear()
All formats cleared from library.

範囲の対応関係の構築:fmap_rangesコマンド

数値や日付の範囲と、それぞれに対応するラベルから、範囲ベースの対応関係を構築します。境界を含めるかどうかを範囲ごとに指定できます。

オプション意味初期値
low各範囲の下限のベクトルで、数値型、Date型、POSIXct型を指定できるなし
high各範囲の上限のベクトルで、lowと同じ長さを指定するなし
label各範囲へ対応するラベルの文字ベクトルなし
inc_low下限を範囲へ含めるかの論理値で、長さ1またはlowと同じ長さを指定するTRUE
inc_high上限を範囲へ含めるかの論理値で、長さ1またはlowと同じ長さを指定するFALSE
date_formatDate型やPOSIXct型の境界をキー文字列へ変換する際に用いるstrptime形式の文字列NULL
# 延滞日数の範囲と対応する区分ラベルを構築
entai_han <- fmap_ranges(
  low      = c(0, 1, 8, 31),
  high     = c(1, 8, 31, Inf),
  label    = c("期限内", "軽度延滞", "中度延滞", "長期延滞"),
  inc_high = c(FALSE, FALSE, FALSE, TRUE))

# 構築した範囲の対応関係を数値型の書式として登録
fnew(entai_han, type = "numeric", name = "entai_kubun")

# 延滞日数のベクトルへ書式を適用
fput(c(0, 5, 20, 95), "entai_kubun")
[1] "期限内"   "軽度延滞" "中度延滞" "長期延滞"

# 書式ライブラリを初期化
fclear()
All formats cleared from library.

書式からの範囲情報の抽出:frangesコマンド

定義済みの書式から、範囲の下限、上限、境界の扱い、ラベルをデータフレームとして取り出します。値とラベルの対応を一覧する場合は、flevelsコマンドを利用します。

オプション意味初期値
fmtks_formatオブジェクト、または書式ライブラリへ登録済みの書式名なし
# 館内滞在時間の範囲と対応する区分ラベルを構築
zaikan <- fmap_ranges(
  low      = c(0, 30, 120),
  high     = c(30, 120, Inf),
  label    = c("短時間滞在", "標準滞在", "長時間滞在"),
  inc_high = c(FALSE, FALSE, TRUE))

# defaultで範囲外の値へ付けるラベルを指定して登録
fnew(zaikan, type = "numeric", name = "zaikan_kubun", default = "記録なし")

# 登録した書式から範囲の定義部分のみを抽出
franges("zaikan_kubun")
  low high inc_low inc_high      label
1   0   30    TRUE    FALSE 短時間滞在
2  30  120    TRUE    FALSE   標準滞在
3 120  Inf    TRUE     TRUE 長時間滞在

# 書式のキーとラベルの対応を一覧として抽出
flevels("zaikan_kubun")
   value      label
1   0,30,TRUE,FALSE 短時間滞在
2 30,120,TRUE,FALSE   標準滞在
3 120,Inf,TRUE,TRUE 長時間滞在

# 書式ライブラリを初期化
fclear()
All formats cleared from library.

層別範囲の対応関係の構築:fmap_strataコマンド

層の識別子と範囲を区切り文字で連結した、層別の対応関係を構築します。適用にはfputkコマンドを用い、層の識別子と数値を複合キーとして渡します。

オプション意味初期値
stratum層の識別子の文字ベクトルなし
low各範囲の下限のベクトルで、指定方法はfmap_rangesコマンドと同じなし
high各範囲の上限のベクトルで、指定方法はfmap_rangesコマンドと同じなし
label各範囲へ対応するラベルの文字ベクトルなし
inc_low下限を範囲へ含めるかの論理値で、長さ1またはlowと同じ長さを指定するTRUE
inc_high上限を範囲へ含めるかの論理値で、長さ1またはlowと同じ長さを指定するFALSE
sep層の識別子と範囲キーの間へ挿入する区切り文字で、fputkコマンドへ渡すsepと一致させる“|”
date_formatDate型やPOSIXct型の境界を変換する際に用いるstrptime形式の文字列NULL
# 館ごとに異なる貸出冊数の上限区分を層別範囲として構築
kashidashi <- fmap_strata(
  stratum  = c("HON", "HON", "MIN", "MIN"),
  low      = c(0, 11, 0, 6),
  high     = c(11, Inf, 6, Inf),
  label    = c("通常貸出", "上限超過", "通常貸出", "上限超過"),
  inc_high = c(FALSE, TRUE, FALSE, TRUE))

# 層別範囲の型を指定して書式ライブラリへ登録
fnew(kashidashi, type = "stratified_range", range_subtype = "numeric",
     name = "kashidashi_kubun")

# 館コードと貸出冊数を複合キーとして書式を適用
fputk(c("HON", "MIN"), c(8, 9), format = "kashidashi_kubun")
[1] "通常貸出" "上限超過"

# 書式ライブラリを初期化
fclear()
All formats cleared from library.

ラベルからの範囲境界の逆引き:fmap_to_rangesコマンド

ラベルを手がかりに、対応する範囲の境界値をデータフレームとして逆引きします。集計結果のラベルから元の区間を復元する場合に利用します。

オプション意味初期値
xラベルの照合に用いる値のベクトルで、照合前に文字型へ変換されるなし
fmtks_formatオブジェクト、または書式ライブラリへ登録済みの書式名なし
# 請求記号の番号帯と書架の対応関係を構築
tana <- fmap_ranges(
  low      = c(1, 101, 201),
  high     = c(100, 200, 300),
  label    = c("第1書架", "第2書架", "第3書架"),
  inc_high = TRUE)

# 構築した対応関係を数値型の書式として登録
fnew(tana, type = "numeric", name = "shoka")

# 番号帯から書架名を取得
fput(c(45, 260), "shoka")
[1] "第1書架" "第3書架"

# 書架名から元の番号帯を逆引き
fmap_to_ranges(c("第1書架", "第3書架"), "shoka")
  low high inc_low inc_high
1   1  100    TRUE     TRUE
2 201  300    TRUE     TRUE

# 書式ライブラリを初期化
fclear()
All formats cleared from library.

双方向書式の作成:fnew_bidコマンド

コードからラベルへ変換する書式と、ラベルからコードへ戻す逆変換用の書式を同時に作成します。逆変換用の書式には「名前_inv」という名前が自動的に付与されます。

オプション意味初期値
値とラベルの対応を定義する名前付き引数なし
name2つの書式へ共通で用いる基本名で、逆変換用の書式はpaste0(name, “_inv”)の名前で登録されるNULL
type書式の型“auto”
ignore_caseTRUEの場合、書式と逆変換用の書式の双方で大文字と小文字を区別せず照合するFALSE
# 貸出状態コードについて、順変換と逆変換の書式を同時に作成
fnew_bid(
  "K" = "貸出中",
  "H" = "返却済",
  "Y" = "予約中",
  name = "jotai")

# コードからラベルへ変換
fputc(c("K", "H", "Y"), "jotai")
[1] "貸出中" "返却済" "予約中"

# ラベルからコードへ逆変換
finputc(c("返却済", "貸出中"), "jotai_inv")
[1] "H" "K"

# 登録された書式名の一覧を取得
flist()
[1] "jotai"     "jotai_inv"

# 書式ライブラリを初期化
fclear()
All formats cleared from library.

複合ラベルによる値の逆引き:finputkコマンド

複数のベクトルを区切り文字で連結した複合ラベルをキーとして、finputコマンドで作成した逆変換用の書式から値を取り出します。単一のラベルから値を取り出す場合は、finputnコマンドを利用します。

オプション意味初期値
複合ラベルへ連結するベクトルで、pasteコマンドにより共通の長さへ再利用されるなし
invalue_name書式ライブラリへ登録済みの逆変換用書式の名前なし
sep連結する各要素の間へ挿入する区切り文字“|”
na_as_stringFALSEの場合は欠損値を伝播させ、TRUEの場合はpasteコマンドが生成する文字列の”NA”をそのまま保持するFALSE
# 館コードと資料区分を連結した複合ラベルから貸出期間を返す書式を作成
finput(
  fmap(paste(c("HON", "HON", "MIN"), c("TS", "AV", "TS"), sep = "|"),
       c(14, 7, 21)),
  name = "kigen_inv")

# 2つのベクトルを複合キーとして貸出期間を取得
finputk(c("HON", "MIN"), c("AV", "TS"), invalue_name = "kigen_inv")
[1]  7 21

# 会員区分のラベルから内部コードへ戻す書式を作成
finput("一般" = 1, "学生" = 2, "シニア" = 3, name = "kaiin_inv")
KS Invalue: kaiin_inv
Target Type: numeric 
Mappings:
  一般 => 1
学生 => 2
シニア => 3

# 単一のラベルから数値を取得
finputn(c("シニア", "一般"), "kaiin_inv")
[1] 3 1

# 書式ライブラリを初期化
fclear()
All formats cleared from library.

データフレーム列への書式の適用:fput_dfコマンド

データフレームの複数の列へ、列ごとに異なる書式をまとめて適用します。変換結果を新しい列として追加するか、元の列を置き換えるかを選択できます。

オプション意味初期値
data書式を適用するデータフレームなし
列名 = 書式オブジェクトまたは書式名の形式で指定する名前付き引数なし
suffix変換結果の列名へ付与する接尾辞“_fmt”
replaceTRUEの場合は元の列を置き換え、FALSEの場合は新しい列を追加するFALSE
# 貸出記録のデータフレームを作成
kashidashi_df <- data.frame(
  riyosha = c("A-001", "A-002", "A-003", "A-004"),
  kubun   = c("IP", "GK", "SN", "HG"),
  entai   = c(0, 5, 20, 95))

# 会員区分の書式を登録
fnew("IP" = "一般", "GK" = "学生", "SN" = "シニア", "HG" = "法人",
     name = "kaiin")

# 延滞日数の区分を範囲の書式として登録
fnew(
  fmap_ranges(
    low      = c(0, 1, 8, 31),
    high     = c(1, 8, 31, Inf),
    label    = c("期限内", "軽度延滞", "中度延滞", "長期延滞"),
    inc_high = c(FALSE, FALSE, FALSE, TRUE)
  ),
  type = "numeric", name = "entai_kubun"
)

# 2つの列へ異なる書式を適用し、接尾辞付きの列として追加
fput_df(kashidashi_df, kubun = "kaiin", entai = "entai_kubun")
   riyosha kubun entai kubun_fmt entai_fmt
1   A-001    IP     0      一般    期限内
2   A-002    GK     5      学生  軽度延滞
3   A-003    SN    20    シニア  中度延滞
4   A-004    HG    95      法人  長期延滞

# replaceをTRUEとして元の列を置き換え
fput_df(kashidashi_df, kubun = "kaiin", replace = TRUE)
  riyosha  kubun entai
1   A-001   一般     0
2   A-002   学生     5
3   A-003 シニア    20
4   A-004   法人    95

# 書式ライブラリを初期化
fclear()
All formats cleared from library.

テキストからの書式定義の読み込み:fparseコマンド

SASの「PROC FORMAT」に近い記法で記述したテキストやファイルから、書式の定義を読み込みます。複数の書式を1つのテキストへまとめて記述できます。

オプション意味初期値
text書式の定義を含む文字列または文字ベクトルで、ベクトルの場合は改行で連結されるNULL
file書式の定義を記述したテキストファイルのパスで、textとfileはどちらか一方のみを指定するNULL
verboseTRUEの場合、解析した書式をコンソールへ表示するFALSE
# 分類コードと予約件数の2つの書式をテキストから読み込み
fparse(text = '
VALUE bunrui (character)
  "SK" = "総記"
  "TG" = "哲学"
  "SZ" = "自然科学"
  .other = "その他分類"
;

VALUE yoyaku (numeric)
  [0, 1)   = "予約なし"
  [1, 5)   = "少数予約"
  [5, HIGH] = "多数予約"
;
')

# 読み込まれた書式名の一覧を取得
flist()
[1] "bunrui" "yoyaku"

# 文字型の書式を名前で指定して適用
fputc(c("TG", "SZ", "XX"), "bunrui")
[1] "哲学"       "自然科学"   "その他分類"

# 数値型の書式を名前で指定して適用
fputn(c(0, 3, 12), "yoyaku")
[1] "予約なし" "少数予約" "多数予約"

# 書式ライブラリを初期化
fclear()
All formats cleared from library.

日付書式の作成:fnew_dateコマンド

SASの日付書式名、またはRのstrftime形式の文字列から、日付や日時の表示用書式を作成します。「DATE9.」などの標準的なSAS書式名は、fnew_dateコマンドで明示的に定義しなくても利用できます。

オプション意味初期値
patternSASの書式名(”DATE9.”、”MMDDYY10.”、”TIME8.”、”DATETIME20.”など)、またはRのstrftime形式の文字列なし
name書式を登録する名前で、省略した場合はSASの書式名またはpatternの文字列がそのまま用いられるNULL
type書式の型で、”date”、”time”、”datetime”、”auto”から指定し、strftime形式を指定した場合は明示が必要“auto”
.missing欠損値へ付けるラベルNULL
# 貸出日のベクトルをDate型で作成
kashidashi_bi <- as.Date(c("2026-04-01", "2026-08-21"))

# SASの標準書式名を指定して適用
fputn(kashidashi_bi, "DATE9.")
[1] "0142026" "2182026"

# 別のSAS書式名を指定して適用
fputn(kashidashi_bi, "YYMMDD10.")
[1] "2026-04-01" "2026-08-21"

# 和文表記の日付書式をstrftime形式で作成
fnew_date("%Y年%m月%d日", name = "wafu_hizuke", type = "date")
KS Format:wafu_hizuke
Type: date 
Pattern: %Y年%m月%d日 

# 作成した書式を名前で指定して適用
fputn(kashidashi_bi, "wafu_hizuke")
[1] "2026年04月01日" "2026年08月21日"

# 利用した書式が自動で登録されていることを確認
flist()
[1] "DATE9."      "wafu_hizuke" "YYMMDD10." 

# 書式ライブラリを初期化
fclear()
All formats cleared from library.

書式ライブラリの書き出し:fexportコマンド

登録済みの書式を、SASの「PROC FORMAT」に近い形式のテキストとして書き出します。書式ライブラリの一覧はflistコマンド、内容の表示はfprintコマンド、削除はfclearコマンドでおこないます。

オプション意味初期値
書き出す対象の、名前付きのks_formatオブジェクトまたはks_invalueオブジェクトなし
formats書式オブジェクトの名前付きリストで、…の代わりに指定できるNULL
file書き出し先のファイルパスで、NULLの場合はテキストを文字列として返すNULL
# 会員区分の書式を登録
fnew("IP" = "一般", "GK" = "学生", "SN" = "シニア", name = "kaiin")

# 貸出状態の書式を登録
fnew("K" = "貸出中", "H" = "返却済", name = "jotai")

# 登録済みの書式名の一覧を取得
flist()
[1] "jotai" "kaiin"

# 特定の書式の内容を表示
fprint("kaiin")
KS Format:kaiin
Type: character 
Mappings:
  IP => 一般
GK => 学生
SN => シニア

# format_getで取り出した書式をテキストとして書き出し
writeLines(fexport(kaiin = format_get("kaiin"), jotai = format_get("jotai")))
VALUE kaiin (character)
"IP" = "一般"
"GK" = "学生"
"SN" = "シニア"
;

VALUE jotai (character)
"K" = "貸出中"
"H" = "返却済"
;

# 特定の書式のみを削除
fclear("jotai")
Format "jotai" removed from library.

# 削除後の一覧を確認
flist()
[1] "kaiin"

# 書式ライブラリを初期化
fclear()
All formats cleared from library.

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

スポンサーリンク
価格および配送状況は変更される場合があります。購入時は商品ページをご確認ください。
当サイトに表示されている商品情報はAmazonから提供されたものであり、更新または削除される場合があります。
karada-goodはAmazonアソシエイトとして、適格販売により収入を得ています。