公開データを収集するときに出典・基準日・単位を記録する
title と URL だけを集めるのではなく、reference date、publication date、access date、units、terms of use を1行に記録します。コード不要で使える CSV template と checklist を含みます。
小規模な研究用参考文献リストを CSV で管理し、比較用に DOI text を正規化して、重複 DOI と欠落 DOI を確認する review file を作成します。workflow は元の CSV を保持し、DOI が存在するというだけで有効だとは判断しません。
この翻訳はAIで作成しました。コード、単位、数値は原文と併せて確認してください。各言語のネイティブ話者による校閲は、まだ完了していません。 English
対象読者スプレッドシートや CSV で参考文献リストを管理し、重複 DOI と DOI 欠落を簡単に確認したい研究者向けのガイドです。
この workflow は2つの実務的な問題を確認します。reference に DOI value がない場合と、simple text normalization 後に2 rows が同じ DOI を持つ場合です。DOI registry には接続しないため、DOI が実在すること、正しく解決されること、引用した article に属することまでは証明しません。
script は https://doi.org/ や doi: などの一般的な textual prefixes を除去し、whitespace を trim して、残った DOI text を比較用に lowercase に変換します。original DOI text は normalized value と並べて output に保持します。
以下の reference list は合成データであり、この記事のために作成したものです。DOI-like strings は demonstration data であり、実在または解決可能な publications として提示するものではありません。file を references.csv として保存してください。
ref_id,title,year,doi
R001,Synthetic bracket study,2024,10.0000/demo.alpha
R002,Synthetic vibration study,2025,10.0000/demo.beta
R003,Synthetic bracket study copy,2024,https://doi.org/10.0000/demo.alpha
R004,Synthetic fatigue note,2023,
R005,Synthetic surrogate study,2026,doi:10.0000/DEMO.GAMMA
R006,Synthetic optimization study,2026,10.0000/demo.delta
reference rows は6件あります。5件には DOI text があり、R004 には DOI がありません。R001 と R003 は異なる textual forms を使用していますが、同じ value に normalize されます。R005 は capitalization と doi: prefix も比較用に normalize できることを示します。
| ref_id | Original DOI | Normalized DOI | 想定 issue |
|---|---|---|---|
| R001 | 10.0000/demo.alpha | 10.0000/demo.alpha | DUPLICATE_DOI |
| R002 | 10.0000/demo.beta | 10.0000/demo.beta | None |
| R003 | https://doi.org/10.0000/demo.alpha | 10.0000/demo.alpha | DUPLICATE_DOI |
| R004 | MISSING_DOI | ||
| R005 | doi:10.0000/DEMO.GAMMA | 10.0000/demo.gamma | None |
| R006 | 10.0000/demo.delta | 10.0000/demo.delta | None |
想定件数は references 6件、DOI text を持つ rows 5件、missing DOI の row 1件、2 rows を含む duplicate DOI group 1件です。normalization 後、空白でない DOI entries 5件には distinct DOI values が4つあります。
次の script を reference_list_check.py として保存してください。reference list 全体の normalized copy と、review が必要な rows だけを含む別の issues.csv を書き出します。元の references.csv は読み取り専用です。
import csv
from pathlib import Path
SOURCE = Path("references.csv")
OUTPUT_DIR = Path("outputs") / "reference_list_result"
NORMALIZED = OUTPUT_DIR / "normalized_references.csv"
ISSUES = OUTPUT_DIR / "issues.csv"
REQUIRED = {"ref_id", "title", "year", "doi"}
def normalize_doi(value: str) -> str:
text = value.strip()
lowered = text.lower()
prefixes = (
"https://doi.org/",
"http://doi.org/",
"doi:",
)
for prefix in prefixes:
if lowered.startswith(prefix):
text = text[len(prefix):].strip()
break
return text.lower()
def main() -> None:
if not SOURCE.is_file():
raise FileNotFoundError(f"Source CSV not found: {SOURCE}")
if OUTPUT_DIR.exists():
raise FileExistsError(f"Output folder already exists: {OUTPUT_DIR}")
rows = []
with SOURCE.open("r", encoding="utf-8-sig", newline="") as stream:
reader = csv.DictReader(stream)
if reader.fieldnames is None or not REQUIRED.issubset(reader.fieldnames):
raise ValueError("CSV is missing a required column.")
seen_ids = set()
for row in reader:
ref_id = row["ref_id"].strip()
if not ref_id:
raise ValueError("ref_id must not be blank.")
if ref_id in seen_ids:
raise ValueError(f"Duplicate ref_id: {ref_id}")
seen_ids.add(ref_id)
rows.append({
"ref_id": ref_id,
"title": row["title"],
"year": row["year"],
"doi": row["doi"],
"normalized_doi": normalize_doi(row["doi"]),
})
by_doi = {}
for row in rows:
doi = row["normalized_doi"]
if doi:
by_doi.setdefault(doi, []).append(row["ref_id"])
duplicate_dois = {
doi: ids for doi, ids in by_doi.items() if len(ids) > 1
}
issue_rows = []
for row in rows:
doi = row["normalized_doi"]
if not doi:
issue_rows.append({
"ref_id": row["ref_id"],
"issue": "MISSING_DOI",
"normalized_doi": "",
"related_ref_ids": "",
})
elif doi in duplicate_dois:
issue_rows.append({
"ref_id": row["ref_id"],
"issue": "DUPLICATE_DOI",
"normalized_doi": doi,
"related_ref_ids": ";".join(duplicate_dois[doi]),
})
OUTPUT_DIR.parent.mkdir(parents=True, exist_ok=True)
OUTPUT_DIR.mkdir()
normalized_fields = ["ref_id", "title", "year", "doi", "normalized_doi"]
with NORMALIZED.open("x", encoding="utf-8", newline="") as stream:
writer = csv.DictWriter(stream, fieldnames=normalized_fields)
writer.writeheader()
writer.writerows(rows)
issue_fields = ["ref_id", "issue", "normalized_doi", "related_ref_ids"]
with ISSUES.open("x", encoding="utf-8", newline="") as stream:
writer = csv.DictWriter(stream, fieldnames=issue_fields)
writer.writeheader()
writer.writerows(issue_rows)
missing_count = sum(row["issue"] == "MISSING_DOI" for row in issue_rows)
print(f"References checked: {len(rows)}.")
print(f"Missing DOI rows: {missing_count}.")
print(f"Duplicate DOI groups: {len(duplicate_dois)}.")
print(f"Issue rows: {len(issue_rows)}.")
print(f"Output folder: {OUTPUT_DIR.as_posix()}")
if __name__ == "__main__":
main()
issues.csv には3つの data rows が含まれるはずです。重複した normalized DOI の R001 と R003、そして missing DOI の R004 です。
ref_id,issue,normalized_doi,related_ref_ids
R001,DUPLICATE_DOI,10.0000/demo.alpha,R001;R003
R003,DUPLICATE_DOI,10.0000/demo.alpha,R001;R003
R004,MISSING_DOI,,
以下の想定 console output は、合成 list と script から手作業で導出したものです。実際に取得した execution log ではありません。
References checked: 6.
Missing DOI rows: 1.
Duplicate DOI groups: 1.
Issue rows: 3.
Output folder: outputs/reference_list_result| 問題 | 確認すること |
|---|---|
| 同じ paper が異なる DOI formatting で2回入力されている | 比較前に一般的な DOI URL と doi: prefixes を normalize します。 |
| Blank DOI が duplicate として扱われる | missing DOI detection と duplicate DOI grouping を分けてください。 |
| 異なる papers の titles が似ている | title similarity だけを records が duplicates である証拠として使用しないでください。 |
| DOI に見える string が存在する | 存在するだけでは validity の証明になりません。重要な references は trusted metadata source で確認してください。 |
| 既存 result が上書きされる | 以前の review evidence を保持するため、新しい output folder を使用します。 |
DOI metadata が存在する場合、DOI matching は有用ですが、missing DOI だからといって reference が invalid または incomplete という意味ではありません。一部の publications や document types には DOI がない場合があり、older records では別の identifiers や manual bibliographic checks が必要になることがあります。
この script が行うのは text normalization だけです。DOI links の resolve、Crossref や別の registration agency への query、titles や authors の検証、retractions の検出、異なる DOI values が work の関連 versions を示すかどうかの判断は行いません。
実際の research database では authors, title, year, journal, volume, pages, DOI, another local reference ID などの fields を保持してください。automatic duplicate detection は bibliographic records を削除する指示ではなく、review aid として扱います。
2026-09-20 · 手作業で確認した例 · 対象: Python 3.12 · 標準ライブラリ: csv, pathlib · 未実行
説明と例は独自に作成しました。関連する動作や概念は、以下の公式資料で確認できます。