見出し画像

ChatGPTとRで、手持ちのレンズの焦点距離をまとめた図を作る


背景と趣旨

 ある日、手持ちのレンズの焦点距離をまとめた図を作ろうと思い立った。図を作成することで手持ちのレンズの焦点距離が必要十分であることを可視化し、なんとなく新しいレンズを購入したいという愚かな願望を抑制しようと考えたのである。
 図を作るだけならExcelでもPowerpointでもよいが、どうせならプログラミングで出力しメンテナンスを簡単にしたいなと思った。そこで、ChatGPT(無料版のGPT 3.5)とオープンソースの統計解析ソフトウェア「GNU R(以下、R)」を使って図を出力することにした。

結果

 こんな図を出力することができた。

 うーん、超望遠単焦点レンズが欲しい。Sigmaの500mmとか……ほら……x軸を600mmまで描画してごらんなさい……欠けていることがよくわかるだろう?

前提

 この記事では以下の2つを前提とする。

前提1: PCにRがインストール済み

 Rが使用できる環境が必要である。この記事ではR 4.3.1を使用して図を出力した。Rの導入方法は下記をご参照いただきたい。

R: The R Project for Statistical Computing (r-project.org)
R のインストール - RjpWiki (okadajp.org)

前提2: レンズ名一覧を作成済み

 焦点距離(mm)の情報を含むレンズ名一覧が必要である。一覧は自分が図を作成したい順序で記載しておく。こんな図を出力したくなるような人なら既に作成済みだろう。

【例:この記事で実際に使用した一覧】
HD PENTAX-DA FISH-EYE10-17mmF3.5-4.5ED
HD PENTAX-DA☆11-18mmF2.8ED DC AW
HD PENTAX-DA 15mmF4ED AL Limited
HD PENTAX-DA 21mmF3.2AL Limited
Kiron 28mm F2
18-35mm F1.8 DC HSM | Art
HD PENTAX-DA 35mmF2.8 Macro Limited
HD PENTAX-DA 20-40mmF2.8-4ED Limited DC WR
ULTRON 40mm F2 Aspherical SL II
HD PENTAX-DA 40mmF2.8 Limited
HD PENTAX-DA☆16-50mmF2.8ED PLM AW
smc PENTAX-A 50mm F1.2
smc FA 50mmF1.4 Classic
HD PENTAX-D FA☆50mmF1.4 SDM AW
Pinhole Pro (55mm, 0.1 to 0.8mm pinhole apertures)
NOKTON 58mm F1.4 SL II
HD PENTAX-DA 70mmF2.4 Limited
smc PENTAX SOFT 85mm F2.2
HD PENTAX-D FA MACRO 100mmF2.8ED AW
Vivitar 135mm F2.8 AUTO TELEPHOTO CLOSE FOCUSING
smc PENTAX-DA☆50-135mmF2.8ED[IF] SDM
smc PENTAX-DA☆200mmF2.8ED[IF] SDM
smc PENTAX-DA☆300mmF4ED[IF] SDM
HD PENTAX-DA 55-300mmF4.5-6.3ED PLM WR RE
HD PENTAX-D FA 150-450mmF4.5-5.6ED DC AW

※焦点距離を持たないリアコンバーター「HD PENTAX-DA AF REAR CONVERTER 1.4x AW」は一覧に含めず、別途図に記載した

データセットの作成

 さて、目標とする図を出力するためには、レンズ名、焦点距離の始点および焦点距離の終点の情報が必要である。加えて、私の場合はレンズをフォーカス方式で"AF" or "MF"という2つのカテゴリに分類したいと考えた。そこで、以下の2ステップでデータセットとなるCSVファイルを作成した。

STEP1: ChatGPTによるCSVファイル生成
 焦点距離(mm)の情報を含むレンズ名一覧をChatGPTで加工し、"lens_name", "forcal_length_start", "forcal_length_end" という3つの列を持つCSVファイル(カンマ区切り)を生成する。
STEP2: 分類の追記
 
作成したCSVファイルに4つめの列として"focus_method"を追加し、"AF" または "MF" というカテゴリを記載する。

STEP1: ChatGPTによるCSVファイル生成

 ChatGPTに以下のようなプロンプトを入力し、CSVファイルの中身を生成する。

レンズ名一覧を元に、"lens_name", "forcal_length_start", "forcal_length_end" という3つの列を持つCSVファイル(カンマ区切り)の内容を生成してください。レンズ名一覧は以下のとおりです。

HD PENTAX-DA FISH-EYE10-17mmF3.5-4.5ED
HD PENTAX-DA☆11-18mmF2.8ED DC AW
(中略)

"lens_name"はレンズ名、"forcal_length_start"は焦点距離の始点、"forcal_length_end"は焦点距離の終点です。"forcal_length_start"と"forcal_length_end"は無次元("mm"を含まない数値)としてください。

焦点距離は「15mm」のようにミリメートル単位で記載されています。焦点距離が「15mm」のように一つの数値の場合は、"forcal_length_start"と"forcal_length_end"の値は等しくなります。焦点距離が「20-40mm」のように、ハイフンで2つの数値をつなぐように記載されている場合、焦点距離は範囲を持ち、"forcal_length_start"と"forcal_length_end"の値は異なります。

※望んだ出力が得られない場合は対話しながら修正する

 出力結果は以下のようなplaintextとなる。この中身をコピーし、CSVファイルを作成する。今回はファイル名を「K.csv」とした。

STEP2: カテゴリ分類の追記

 先ほど作成したK.csvを適当なエディタ(メモ帳など)で開き、4列目として "focus_method" を追記する。以下のようになる。

図の出力

 さて、いよいよRで図を出力する。まずは解析に必要なパッケージを読み込む。使用する主なパッケージはdplyrとggplot2の2つである。

# 必要なパッケージを読み込む
if (!requireNamespace("pacman", quietly = TRUE)) {
  install.packages("pacman")
  }

library(pacman)
p_load(dplyr, ggplot2)

 つぎに、作成したデータセット(K.csv)を読み込んでから"order"という列を追加し、データセットの冒頭から順に連番(1, 2, 3…)を付与する。
 read.csv()関数の値はデータセットの相対パスまたは絶対パスであり、適宜変更が必要だ。
 "order"列はレンズの並び順を明示するために使用する。CSVファイルを作成する段階で"order"列を作成しても良いが、レンズは増えるものなのでこの辺りはRで自動処理する。

# CSVファイルを読み込み、"order"列を追加して連番を割り当てる
lens_data <- read.csv("./data/K.csv") %>%
  transform(order = 1:nrow(.))

 では、ggplot2で図を出力する。

# プロットを生成する
## データセットとマッピングを指定する
p <- lens_data %>%
  ggplot(aes(
    x = focal_length_start,
    xend = focal_length_end,
    y = order,
    yend = order,
    color = focus_method
  ))

## グラフの種類を指定する
p <- p +
  geom_vline(xintercept = seq(0, 450, 50),
             linetype = "dashed", linewidth = 0.25, color = "gray80") +
  geom_point(aes(x = focal_length_start), size = 1) +
  geom_point(aes(x = focal_length_end), size = 1) +
  geom_segment(linewidth = 2) +
  geom_text(aes(label = lens_name, x = 0), size = 2, hjust = 1, nudge_x = -10)

## グラフの見た目を調整する
p <- p +
  scale_color_manual(values = c("AF" = "darkgreen", "MF" = "darkorange")) +
  scale_x_continuous(breaks = seq(0, 450, 50)) +
  scale_y_reverse() +
  coord_cartesian(xlim = c(-300, 450)) +
  theme_classic() +
  theme(legend.title = element_blank(),
        plot.title = element_text(face = "bold"),
        axis.text.y = element_blank(), axis.line.y = element_blank(), axis.ticks.y = element_blank(),
        panel.grid.major.y = element_blank(), panel.background = element_rect(fill = "gray95"))

## グラフのタイトルや軸ラベルなどを指定する
p <- p +
  labs(x = "Focal length (mm)", y = "") +
  ggtitle("K mount")

## 右下にボックスとテキストを追加する(リアコンバーター用)
p <- p +
  geom_rect(aes(xmin = 180, xmax = 450, ymin = max(order) - 5.5, ymax = max(order) - 6.5),
            fill = "gray85", color = "gray85") +
  geom_text(aes(x = (180 + 450)/2, y = max(order) - 6,
            label = "HD PENTAX-DA AF REAR CONVERTER 1.4x AW"), color = "red",
            size = 2, vjust = 0.5, hjust = 0.5)

## プロットを表示する
p

 出力結果は冒頭に示した通りである。"geom", "scale", "coord" から始まる関数群の数値部分や"label"に記載されたテキストを変更することで、様々なレンズシステムに対応できる。コードの詳細な解説やカスタマイズ方法は、ChatGPTなどを利用して確認して欲しい。

まとめ

 この記事ではChatGPTとRを使用して、手持ちのレンズの焦点距離を図にまとめる方法を示した。結果として新たなレンズが欲しくなったので大失敗である。皆様も試してみてほしい。そして一緒に深いレンズ沼に堕ちよう。