なぜJupyterからPositronへ移行したのか
データ分析をしていると、いつの間にか「Jupyter Notebook (.ipynb) 地獄」に陥っていませんか?
Git差分が読めない
Outputが含まれるため、GitのDiffが巨大になり、どこを変更したかわからない。
環境再現性の欠如
「あの人のPCでは動くけど、私のPCでは動かない」。
言語の壁
RとPythonを行き来するとき、ディレクトリ構成やパス指定がバラバラになりがち。
これまで私もJupyter Labを愛用していましたが、チーム開発や長期的なメンテナンス性を考え、Gitで管理しやすく、pythonとRどちらの解析も可能な環境への移行を決意しました。
そこで辿り着いたのが、Positron をベースにし、R (renv) × Python (uv) でガチガチに管理された「オレオレ最強分析環境」です。
本記事では、この環境を一発で構築するシェルスクリプトとともに、そのワークフローを紹介します。
今回の技術スタック
今回の環境構築の肝となるツールたちです。
-
IDE: Positron
- RStudioの開発元であるPosit社が開発した、VS CodeベースのIDE。
- RとPythonの両方をファーストクラスでサポート。
- 変数エクスプローラー(Data Explorer)が優秀で、Jupyterのような対話的実行が可能かつ、スクリプト(.py/.R)ベースなのでGit管理が容易。
-
Python環境管理: uv
- Rust製の爆速パッケージマネージャー。
pipやpoetryよりも圧倒的に速い。 - 仮想環境作成(
venv)からパッケージインストールまでこれ一本。
- Rust製の爆速パッケージマネージャー。
-
R環境管理: renv
- Rのプロジェクトごとのパッケージ管理のデファクトスタンダード。
-
renv.lockでバージョンを固定し、再現性を担保。
事前準備
事前にこれらの環境を整えておく必要があります。
- Positronのインストール
- pythonのインストール
- Rのインストール
- uvのインストール
- gitのインストール、初期設定(username、emailの登録)
課題:プロジェクトの「初手」が面倒くさい
いざ「きれいに管理しよう」と思っても、毎回ディレクトリ掘って、requirements.txt 作って、.gitignore 書いて…というのは面倒です。
そこで、これらをすべて一撃で行うシェルスクリプトを作成しました。
このスクリプトを実行すると、以下のディレクトリ構成(Cookiecutter Data Scienceライクな構成)と設定ファイルが自動生成されます。
ProjectName/
├── analysis/ # 分析ノートブック
├── data/ # データ (Git管理外に設定済)
├── output/ # 出力結果
├── scripts/ # 関数・ETLスクリプト
│ └── common/ # ユーティリティなど
│ ├── utils.py # pythonユーティリティー
│ └── utils.R # Rユーティリティー
├── templates/ # 解析ファイルのテンプレート
│ ├── template.py # pythonテンプレート
│ └── template.qmd # qmdテンプレート
├── requirements.txt # Pythonライブラリ定義
├── ~~.Rproj # R Projectファイル
├── setup_r_packages.R # Rセットアップ用
├── _quarto.yml # quartoのデフォルト設定ファイル
├── references.bib # 参考文献のbib
├── custom_citation.csl # qmdに記載する引用のフォーマット
├── .gitignore # データ除外など設定済
├── history.qmd # Git変更履歴レポート
└── README.md # プロジェクト説明書
自動構築スクリプト (setup_project.sh)
以下のスクリプトを setup_project.sh として保存し、実行権限を与えてください(chmod +x setup_project.sh)。
setup_project.sh
#!/bin/bash
# エラーが発生したらその時点でスクリプトを停止する
set -e
# 引数チェック
if [ -z "$1" ]; then
echo "Error: プロジェクト名を引数に指定してください。"
echo "Usage: ./setup_project.sh <ProjectName>"
exit 1
fi
PROJECT_NAME=$1
echo "🚀 プロジェクト '$PROJECT_NAME' のセットアップを開始します..."
# ---------------------------------------------------
# 1. ディレクトリ作成
# ---------------------------------------------------
echo "Creating directories..."
# Data directories
mkdir -p "$PROJECT_NAME/data/00_raw"
mkdir -p "$PROJECT_NAME/data/01_interim"
mkdir -p "$PROJECT_NAME/data/02_processed"
mkdir -p "$PROJECT_NAME/data/database"
# Script directories
mkdir -p "$PROJECT_NAME/scripts/common"
mkdir -p "$PROJECT_NAME/scripts/01_fetch"
mkdir -p "$PROJECT_NAME/scripts/02_preprocess"
mkdir -p "$PROJECT_NAME/scripts/03_features"
# Analysis directories
mkdir -p "$PROJECT_NAME/analysis/01_descriptive"
mkdir -p "$PROJECT_NAME/analysis/02_hypothesis"
mkdir -p "$PROJECT_NAME/analysis/03_modeling"
# Report directories
mkdir -p "$PROJECT_NAME/reports/_extensions"
# Output directory
mkdir -p "$PROJECT_NAME/output"
# Template directory
mkdir -p "$PROJECT_NAME/templates"
# ---------------------------------------------------
# 2. ファイル作成
# ---------------------------------------------------
echo "Creating files..."
# Python: requirements.txt
cat <<EOF >"$PROJECT_NAME"/requirements.txt
pandas
numpy
seaborn
pyprojroot
jupyter
tabulate
openpyxl
pyarrow
EOF
# R: renv.lock (空ファイル)
touch "$PROJECT_NAME"/renv.lock
# Pythonパッケージ化用の __init__.py
touch "$PROJECT_NAME"/scripts/__init__.py
touch "$PROJECT_NAME"/scripts/common/__init__.py
touch "$PROJECT_NAME"/scripts/common/utils.py
# R: 共通ユーティリティ (utils.R) の作成
cat <<EOF >"$PROJECT_NAME"/scripts/common/utils.R
# ==========================================
# Common R Utilities
# ==========================================
suppressWarnings({
if (!require("pacman")) {
install.packages("pacman")
}
pacman::p_load(
gtsummary,
ggplot2,
dplyr,
tidyr,
janitor,
stringr,
labelled,
flextable,
readxl,
IRdisplay,
patchwork,
gt,
here,
cardx,
car,
pROC,
broom,
broom.helpers
)
})
# プロジェクトルートの取得
root_path <- here()
# パスの定義
# here("フォルダ", "サブフォルダ") と書くと、自動的に繋げて絶対パスにしてくれます
dataDir <- here("data")
rawDataDir <- here("data", "00_raw")
interimDataDir <- here("data", "01_interim")
processedDataDir <- here("data", "02_processed")
# 確認用メッセージ(読み込み時に表示されます)
message("Loaded: scripts/common/utils.R")
message("Project Root: ", root_path)
EOF
# R: パッケージ一括インストール用スクリプトの作成
cat <<EOF >"$PROJECT_NAME"/setup_r_packages.R
# ==========================================
# R Package Setup Script
# ==========================================
options(repos = c(CRAN = "https://cloud.r-project.org"))
if (!require("renv")) install.packages("renv")
if (!file.exists("renv.lock")) {
renv::init(bare = TRUE)
}
if (!require("pacman")) install.packages("pacman")
# utils.R と同じパッケージリストをここでも定義して初期インストールします
pacman::p_load(
gtsummary,
ggplot2,
dplyr,
tidyr,
janitor,
stringr,
labelled,
flextable,
readxl,
IRdisplay,
patchwork,
gt,
here,
cardx,
car,
pROC,
broom,
broom.helpers
)
message("Saving package state to renv.lock...")
renv::snapshot()
message("✅ R packages setup complete!")
EOF
# ---------------------------------------------------
# 変更履歴テンプレートの作成
# ---------------------------------------------------
cat <<'EOF' >"$PROJECT_NAME/history.qmd"
---
title: "分析レポート"
format: html
---
## 変更履歴
```{python}
#| echo: false
#| output: asis
import subprocess
import pandas as pd
from io import StringIO
import glob
import os
# ---------------------------------------------------------
# 設定
# ---------------------------------------------------------
target_extensions = ['.py', '.R', '.qmd']
search_root = './'
# ---------------------------------------------------------
# 関数定義
# ---------------------------------------------------------
def get_git_log(file_path):
"""指定されたファイルのGit履歴をDataFrameで返す"""
try:
cmd = [
"git", "log",
"--date=format:%Y/%m/%d",
"--pretty=format:%h\t%an\t%ad\t%s",
file_path
]
result = subprocess.run(cmd, capture_output=True, text=True, encoding='utf-8')
if result.returncode != 0 or not result.stdout.strip():
return None
df = pd.read_csv(
StringIO(result.stdout),
sep="\t",
header=None,
names=["ID", "作成者", "作成日", "コメント"]
)
return df
except Exception:
return None
# ---------------------------------------------------------
# メイン処理
# ---------------------------------------------------------
target_files = []
for ext in target_extensions:
pattern = os.path.join(search_root, f"**/*{ext}")
found = glob.glob(pattern, recursive=True)
target_files.extend(found)
target_files.sort()
if not target_files:
print("対象ファイルが見つかりませんでした。")
for file_path in target_files:
# 変更履歴のないファイルはスキップ
df_log = get_git_log(file_path)
if df_log is not None:
# 相対パスをきれいに表示
disp_path = os.path.relpath(file_path, search_root)
print(f"\n### {disp_path}\n")
print(df_log.to_markdown(index=False))
print("\n")
```
EOF
# ---------------------------------------------------
# .gitignore の作成
# ---------------------------------------------------
cat <<EOF >"$PROJECT_NAME"/.gitignore
.Rproj.user
.Rhistory
.RData
.python-version
__pycache__/
venv/
.venv/
renv/library/
renv/staging/
# Data files (Git管理外)
data/
*_files/
*_cache/
output/
*.csv
*.xlsx
*.duckdb
*.sqlite
# Keep folder structure
!data/**/.gitkeep
!output/.gitkeep
EOF
# 空フォルダ維持用の .gitkeep 作成
touch "$PROJECT_NAME"/data/00_raw/.gitkeep
touch "$PROJECT_NAME"/data/01_interim/.gitkeep
touch "$PROJECT_NAME"/data/02_processed/.gitkeep
touch "$PROJECT_NAME"/data/database/.gitkeep
touch "$PROJECT_NAME"/output/.gitkeep
# ---------------------------------------------------
# R Projectファイル (.Rproj) の作成
# ---------------------------------------------------
cat <<EOF >"$PROJECT_NAME/$PROJECT_NAME.Rproj"
Version: 1.0
RestoreWorkspace: Default
SaveWorkspace: Default
AlwaysSaveHistory: Default
EnableCodeIndexing: Yes
UseSpacesForTab: Yes
NumSpacesForTab: 2
Encoding: UTF-8
RnwWeave: Sweave
LaTeX: pdfLaTeX
EOF
# ---------------------------------------------------
# _quarto.yml の作成
# ---------------------------------------------------
cat <<EOF >"$PROJECT_NAME/_quarto.yml"
project:
output-dir: output
toc: true
number-sections: true
bibliography: references.bib
csl: custom_citation.csl
EOF
# ---------------------------------------------------
# references.bib の作成
# ---------------------------------------------------
cat <<EOF >"$PROJECT_NAME/references.bib"
EOF
# ---------------------------------------------------
# custom_citation.csl の作成
# ---------------------------------------------------
cat <<EOF >"$PROJECT_NAME/custom_citation.csl"
<?xml version="1.0" encoding="utf-8"?>
<style xmlns="http://purl.org/net/xbiblio/csl" class="in-text" version="1.0" demote-non-dropping-particle="sort-only" default-locale="en-US">
<info>
<title>Compact Slide Style (Author, Journal, Vol:Page)</title>
<id>compact-slide-style</id>
<updated>2025-12-06T00:00:00+00:00</updated>
<author>
<name>Gemini</name>
</author>
</info>
<citation et-al-min="2" et-al-use-first="1">
<layout delimiter="; ">
<group delimiter=", ">
<names variable="author">
<name form="long" initialize-with="." name-as-sort-order="all" delimiter=", "/>
<et-al font-style="italic"/>
</names>
<text variable="container-title" form="short"/> <group delimiter=":">
<group>
<text variable="volume"/>
<text variable="issue" prefix="(" suffix=")"/>
</group>
<text variable="page"/>
</group>
</group>
</layout>
</citation>
<bibliography hanging-indent="true" et-al-min="7" et-al-use-first="6">
<layout>
<group delimiter=". ">
<names variable="author"/>
<text variable="title"/>
<text variable="container-title" font-style="italic"/>
<date variable="issued"><date-part name="year"/></date>
</group>
</layout>
</bibliography>
</style>
EOF
# ---------------------------------------------------
# template.py の作成
# ---------------------------------------------------
cat <<EOF >"$PROJECT_NAME/templates/template.py"
# %%
import pandas as pd
import pyprojroot
import numpy as np
import sys
from scripts.common.utils import *
root_path = str(pyprojroot.here())
base_dir = str(root_path)
sys.path.append(str(root_path))
EOF
# ---------------------------------------------------
# template.qmd の作成
# ---------------------------------------------------
cat <<'EOF' >"$PROJECT_NAME/templates/template.qmd"
---
title: "タイトル"
format:
html:
code-fold: true
execute:
cache: true
---
```{r}
#| echo: false
library(here)
source(here("scripts/common/utils.R"))
```
EOF
# ---------------------------------------------------
# README.md の作成
# ---------------------------------------------------
cat <<'EOF' >"$PROJECT_NAME/README.md"
# Project: Analysis Base
RとPythonを併用したデータ解析プロジェクトです。
環境非依存(Cross-Platform)な設計に基づき構築されており、再現性を重視しています。
## 📋 前提条件 (Prerequisites)
このプロジェクトを実行するには、以下のツールがインストールされている必要があります。
- **R** (>= 4.2.0)
- **Python** (>= 3.10)
- **Quarto** (最新版推奨)
- **uv** (Pythonパッケージ管理)
- **Git**
## 🚀 セットアップ (Getting Started)
プロジェクトをクローン後、以下の手順で環境を構築してください。
### 1. Python環境 (uv)
`uv` を使用して高速に環境構築を行います。
```bash
# uvによるプロジェクト初期化(pyproject.toml生成)と仮想環境作成
uv init
uv venv
# 仮想環境の有効化
uv sync
# パッケージインストール
uv pip install -r requirements.txt
```
### 2. R環境 (renv)
`renv` を使用してパッケージバージョンを復元します。
```bash
Rscript setup_r_packages.R
```
## 📂 フォルダ構成 (Directory Structure)
データとコードは明確に分離して管理します。
```
.
├── analysis/ # 探索的分析ノートブック (番号順に実施)
│ ├── 01_descriptive # 記述統計・データ確認
│ ├── 02_hypothesis # 仮説検定・詳細分析
│ └── 03_modeling # モデリング・予測
├── data/ # データファイル (Git管理外)
│ ├── 00_raw # 元データ (決して変更しないこと)
│ ├── 01_interim # 中間データ (クレンジング途中など)
│ ├── 02_processed # 分析用データ (最終形)
│ └── database # SQLite/DuckDBファイル等
├── output/ # 生成されたレポート・図表
├── reports/ # 提出用レポート原稿 (qmd)
├── scripts/ # 関数・ETLスクリプト
│ ├── common/ # 共通ユーティリティ (utils.R / utils.py)
│ ├── 01_fetch/ # データ取得
│ ├── 02_preprocess/ # 前処理
│ └── 03_features/ # 特徴量生成
└── templates/ # 分析テンプレート
```
## 🛠️ 開発ルール (Guidelines)
### 1. パス管理 (Path Management)
絶対パスは使用禁止です。必ずプロジェクトルートを基準にパスを解決するライブラリを使用してください。
**Rの場合 (`here` パッケージ):**
```r
source(here::here("scripts/common/utils.R"))
# rawDataDir, processedDataDir 等の変数が利用可能になります
df <- read_csv(file.path(rawDataDir, "input.csv"))
```
**Pythonの場合 (`pyprojroot`):**
```python
import pyprojroot
root = pyprojroot.here()
data_path = root / "data" / "00_raw" / "input.csv"
```
### 2. 再現性 (Reproducibility)
- **乱数シード**: 分析結果を固定するため、必ず `set.seed()` や `random_state` を指定してください。
- **Rawデータ**: `data/00_raw` 内のファイルは上書き・変更しないでください。
### 3. レポート生成 (Reporting)
Quartoを使用してレポートを作成します。
```bash
# 全てのレポートをレンダリング
quarto render
```
### 4. 変更履歴 (History)
Gitのコミットログから自動的に変更履歴を生成する仕組みがあります。
`history.qmd` をレンダリングすると、主要ファイルの更新履歴が確認できます。
---
*Created by setup_project.sh*
EOF
echo "✅ プロジェクト '$PROJECT_NAME' の作成が完了しました。"
echo " cd $PROJECT_NAME で移動して作業を開始してください。"
保存したら、保存場所で以下のようにコマンドを打ってください。
sh ./setup_project.sh 〇〇
〇〇はプロジェクト名を入力してください。
セットアップ手順
以下の手順でセットアップができます。
※README.mdにも記載しています。
python仮想環境構築(uvを用いて)
uv を使用して高速に環境構築を行います。
# uvによるプロジェクト初期化(pyproject.toml生成)と仮想環境作成
uv init
uv venv
# 仮想環境の有効化
uv sync
# パッケージインストール
uv pip install -r requirements.txt
requirements.txtには、データ解析で必要となりそうなライブラリをあらかじめ記載しています。
pandas
numpy
seaborn
pyprojroot
jupyter
tabulate
openpyxl
pyarrow
R仮想環境構築(renvを用いて)
renv を使用してパッケージバージョンを復元します。
Rscript setup_r_packages.R
setup_r_packages.Rには、データ解析で必要となりそうなライブラリをあらかじめ記載しています。
# ==========================================
# R Package Setup Script
# ==========================================
options(repos = c(CRAN = "https://cloud.r-project.org"))
if (!require("renv")) install.packages("renv")
if (!file.exists("renv.lock")) {
renv::init(bare = TRUE)
}
if (!require("pacman")) install.packages("pacman")
# utils.R と同じパッケージリストをここでも定義して初期インストールします
pacman::p_load(
gtsummary,
ggplot2,
dplyr,
tidyr,
janitor,
stringr,
labelled,
flextable,
readxl,
IRdisplay,
patchwork,
gt,
here,
cardx,
car,
pROC,
broom,
broom.helpers
)
message("Saving package state to renv.lock...")
renv::snapshot()
message("✅ R packages setup complete!")
これで、このプロジェクトの中で、pythonとRが使えるようになりました。
Gitの初期設定
解析ファイルはgitで管理していきますので、あらかじめgit initしておきます。
git init
この環境の「推し」ポイント
RとPythonで「パスの書き方」を統一
このスクリプトは、R (hereパッケージ) と Python (pyprojrootパッケージ) を使って、プロジェクトルートからの相対パスでファイルを読み込むユーティリティを自動生成します。
Rの場合 :
# ==========================================
# Common R Utilities
# ==========================================
suppressWarnings({
if (!require("pacman")) {
install.packages("pacman")
}
pacman::p_load(
gtsummary,
ggplot2,
dplyr,
tidyr,
janitor,
stringr,
labelled,
flextable,
readxl,
IRdisplay,
patchwork,
gt,
here,
cardx,
car,
pROC,
broom,
broom.helpers
)
})
# プロジェクトルートの取得
root_path <- here()
# パスの定義
# here("フォルダ", "サブフォルダ") と書くと、自動的に繋げて絶対パスにしてくれます
dataDir <- here("data")
rawDataDir <- here("data", "00_raw")
interimDataDir <- here("data", "01_interim")
processedDataDir <- here("data", "02_processed")
# 確認用メッセージ(読み込み時に表示されます)
message("Loaded: scripts/common/utils.R")
message("Project Root: ", root_path)
実際のコードでは、
source(here::here("scripts/common/utils.R"))
# rawDataDir変数が自動定義される
df <- read_csv(file.path(rawDataDir, "data.csv"))
このようにして、プロジェクトルートのディレクトリを参照して、utils.Rが読み込まれることになります。
Pythonの場合
import pyprojroot
root_path = str(pyprojroot.here())
sys.path.append(root_path)
from scripts.common.utils import *
このようにして、プロジェクトルートのディレクトリを参照して、utils.pythonが読み込まれることになります。
隠れたこだわり:「変更履歴」の完全自動化
分析レポートを提出する際、「前回のレポートからどこが変わったの?」と聞かれて答えに窮したことはありませんか? あるいは、自分でも「あの前処理のロジック、いつ書き換えたっけ…」と記憶が曖昧になることがあります。
そこで、「Quartoをレンダリングするだけで、Gitログから綺麗な変更履歴表を自動生成する」 仕組み (history.qmd) をテンプレートに組み込みました。
仕組み:Quartoの中でGitを叩く
history.qmd の内部では、Pythonの subprocess モジュールを使用して git log コマンドを実行し、その結果を Pandas DataFrame に変換して Markdown の表として出力しています。
この仕組みのポイントは以下の3点です:
対象ファイルを限定
画像やキャッシュファイルの変更は無視し、分析の本質であるコード (.py, .R) とレポート (.qmd) の変更だけを抽出します。
相対パス表示
プロジェクトルートからの相対パスで表示するため、どのスクリプトが変更されたか一目瞭然です。
レポート一体型
HTMLレポートの一部としてレンダリングされるため、分析結果と一緒に「その結果を生み出したコードの履歴」も納品できます。
実装のイメージ
生成される history.qmd の中身は、おおよそ以下のような処理をしています(自動生成スクリプトに含まれています)。
import subprocess
import pandas as pd
from io import StringIO
import glob
import os
# ---------------------------------------------------------
# 設定
# ---------------------------------------------------------
target_extensions = ['.py', '.R', '.qmd']
search_root = './' # レポートの場所から見たプロジェクトルート
# ---------------------------------------------------------
# 関数定義
# ---------------------------------------------------------
def get_git_log(file_path):
"""指定されたファイルのGit履歴をDataFrameで返す"""
try:
cmd = [
"git", "log",
"--date=format:%Y/%m/%d",
"--pretty=format:%h\t%an\t%ad\t%s",
file_path
]
# Windows対応: utf-8でダメなら cp932 に変更してください
result = subprocess.run(cmd, capture_output=True, text=True, encoding='utf-8')
if result.returncode != 0 or not result.stdout.strip():
return None
df = pd.read_csv(
StringIO(result.stdout),
sep="\t",
header=None,
names=["ID", "作成者", "作成日", "コメント"]
)
return df
except Exception:
return None
# ---------------------------------------------------------
# メイン処理
# ---------------------------------------------------------
target_files = []
for ext in target_extensions:
pattern = os.path.join(search_root, f"**/*{ext}")
found = glob.glob(pattern, recursive=True)
target_files.extend(found)
target_files.sort()
if not target_files:
print("対象ファイルが見つかりませんでした。")
for file_path in target_files:
# 変更履歴のないファイルはスキップ
df_log = get_git_log(file_path)
if df_log is not None:
# 相対パスをきれいに表示
disp_path = os.path.relpath(file_path, search_root)
print(f"\n### {disp_path}\n")
print(df_log.to_markdown(index=False))
print("\n")
これにより、Quartoのレンダリングで、最新の分析結果と共に、以下のような変更履歴ページが自動的に出来上がります。
1.1 history.qmd
ID 作成者 作成日 コメント
a5d7880 〇〇 2025/12/07 first commit
1.2 main.py
ID 作成者 作成日 コメント
a5d7880 〇〇 2025/12/07 first commit
1.3 scripts/init.py
ID 作成者 作成日 コメント
a5d7880 〇〇 2025/12/07 first commit
1.4 scripts/common/init.py
ID 作成者 作成日 コメント
a5d7880 〇〇 2025/12/07 first commit
1.5 scripts/common/utils.R
ID 作成者 作成日 コメント
a5d7880 〇〇 2025/12/07 first commit
1.6 scripts/common/utils.py
ID 作成者 作成日 コメント
a5d7880 〇〇 2025/12/07 first commit
1.7 setup_r_packages.R
ID 作成者 作成日 コメント
a5d7880 〇〇 2025/12/07 first commit
1.8 templates/template.py
ID 作成者 作成日 コメント
a5d7880 〇〇 2025/12/07 first commit
1.9 templates/template.qmd
ID 作成者 作成日 コメント
a5d7880 〇〇 2025/12/07 first commit
こまめにGitでログを保存すれば、いつ、誰がどんな解析をやったのか一目瞭然です!
研究者への「隠し機能」:参考文献管理 (.bib / .csl) の自動セットアップ
データ分析のゴールは、コードを書くことではなく、論文やレポートとしてアウトプットすることです。 アカデミアや研究開発の現場では、引用が避けて通れません。
通常、Quartoで引用管理をするには references.bib を用意し、投稿先に合わせた .csl (Citation Style Language) ファイルを探してくる必要がありますが、このスクリプトはそこも自動化しています。
独自の「Compact Slide Style」を標準装備
スクリプトを実行すると、自動的に以下の2ファイルが生成されます。
references.bib
空のBibTeXファイル。ここにGoogle ScholarやZoteroからコピーしたBibTeXを貼るだけで準備完了です。
custom_citation.csl
ここがこだわりです。
標準的なAPAやChicagoスタイルは、スライドや簡易レポートの脚注にするには長すぎることがあります。 そこで、「(Author, Journal, Vol:Page)」 という形式に極限まで短縮した、独自のCompact Slide Styleを定義したCSLファイルを自動生成するようにしました。
使い方
_quarto.yml にも自動的に設定が書き込まれているため、セットアップ直後からすぐに引用が可能です。
references.bib に文献情報を追記する。
本文中で @Key2025 のように書く。
これだけで、レポートの末尾(またはスライドの脚注)に、スッキリとした書誌情報が自動生成されます。 「分析」から「執筆」への移行コストをゼロにするための、地味ですが強力な機能です。
まとめ
本記事では、より堅牢で、より管理のしやすいデータ分析環境の構築方法を提案しました。もっと効率のいいやり方があれば是非コメントいただきたいです。