Agent-almanac validate-statistical-output
git clone https://github.com/pjt222/agent-almanac
T=$(mktemp -d) && git clone --depth=1 https://github.com/pjt222/agent-almanac "$T" && mkdir -p ~/.claude/skills && cp -r "$T/i18n/ja/skills/validate-statistical-output" ~/.claude/skills/pjt222-agent-almanac-validate-statistical-output-0b8ad7 && rm -rf "$T"
i18n/ja/skills/validate-statistical-output/SKILL.md統計出力のバリデーション
独立した計算と系統的な比較を通じて統計分析結果を検証します。
使用タイミング
- 規制提出向けの主要・副次エンドポイント分析のバリデーション時
- ダブルプログラミングの実施時(RとSAS、または独立したR実装)
- 分析コードが正しい結果を生成することの検証時
- コードや環境の変更後の再バリデーション時
入力
- 必須: 主要分析コードと結果
- 必須: 参照結果(独立した計算、公表値、または既知のテストデータ)
- 必須: 数値比較の許容誤差基準
- 任意: 規制提出のコンテキスト
手順
ステップ1: 比較フレームワークの定義
# Define tolerance levels for different statistics tolerances <- list( counts = 0, # Exact match for integers proportions = 1e-4, # 0.01% for proportions means = 1e-6, # Numeric precision for means p_values = 1e-4, # 4 decimal places for p-values confidence_limits = 1e-3 # 3 decimal places for CIs )
期待結果: 各統計カテゴリーの許容誤差レベルが定義され、整数カウントには厳しい許容誤差(完全一致)、浮動小数点統計(p値、信頼区間)には緩い許容誤差が設定されていること。
失敗時: 許容誤差レベルが争われた場合は、各閾値の根拠を文書化し、進める前に統計責任者の承認を得ます。規制提出についてはICH E9ガイドラインを参照します。
ステップ2: 比較関数の作成
#' Compare two result sets with tolerance-based matching #' #' @param primary Results from the primary analysis #' @param reference Results from the independent calculation #' @param tolerances Named list of tolerance values #' @return Data frame with comparison results compare_results <- function(primary, reference, tolerances) { stopifnot(names(primary) == names(reference)) comparison <- data.frame( statistic = names(primary), primary_value = unlist(primary), reference_value = unlist(reference), stringsAsFactors = FALSE ) comparison$absolute_diff <- abs(comparison$primary_value - comparison$reference_value) comparison$tolerance <- sapply(comparison$statistic, function(s) { # Match to tolerance category or use default tol <- tolerances[[s]] if (is.null(tol)) tolerances$means # default tolerance else tol }) comparison$pass <- comparison$absolute_diff <= comparison$tolerance comparison }
期待結果:
compare_results() が統計名、主要値、参照値、絶対差、許容誤差、合否ステータスの列を含むデータフレームを返すこと。
失敗時: 名前の不一致で関数がエラーになった場合は、両方の結果リストが同じ統計名を使用していることを確認します。許容誤差マッピングが失敗した場合は、認識されない統計名のデフォルト許容誤差を追加します。
ステップ3: ダブルプログラミングの実装
異なるコードで同じ結果に到達する独立した実装を作成します:
# PRIMARY ANALYSIS (in R/primary_analysis.R) primary_analysis <- function(data) { model <- lm(endpoint ~ treatment + baseline + sex, data = data) coefs <- summary(model)$coefficients list( treatment_estimate = coefs["treatmentActive", "Estimate"], treatment_se = coefs["treatmentActive", "Std. Error"], treatment_p = coefs["treatmentActive", "Pr(>|t|)"], n_subjects = nobs(model), r_squared = summary(model)$r.squared ) } # INDEPENDENT VERIFICATION (in validation/independent_analysis.R) # Written by a different analyst or using different methodology independent_analysis <- function(data) { # Using matrix algebra instead of lm() X <- model.matrix(~ treatment + baseline + sex, data = data) y <- data$endpoint beta <- solve(t(X) %*% X) %*% t(X) %*% y residuals <- y - X %*% beta sigma2 <- sum(residuals^2) / (nrow(X) - ncol(X)) var_beta <- sigma2 * solve(t(X) %*% X) se <- sqrt(diag(var_beta)) t_stat <- beta["treatmentActive"] / se["treatmentActive"] p_value <- 2 * pt(-abs(t_stat), df = nrow(X) - ncol(X)) list( treatment_estimate = as.numeric(beta["treatmentActive"]), treatment_se = se["treatmentActive"], treatment_p = as.numeric(p_value), n_subjects = nrow(data), r_squared = 1 - sum(residuals^2) / sum((y - mean(y))^2) ) }
期待結果: 異なるコードパス(例:
lm() と行列代数)を使用して同じ統計結果に到達する2つの独立した実装が存在すること。実装が異なるアナリストによって作成されているか、根本的に異なる方法を使用していること。
失敗時: 独立した実装が異なる結果を生成した場合は、まず両方が同じ入力データを使用していることを確認します(
digest::digest(data) を比較)。次に、NA処理、コントラストコーディング、または自由度計算の違いを確認します。
ステップ4: 比較の実行
# Execute both analyses primary_results <- primary_analysis(study_data) independent_results <- independent_analysis(study_data) # Compare comparison <- compare_results(primary_results, independent_results, tolerances) # Report cat("Validation Comparison Report\n") cat("============================\n") cat(sprintf("Date: %s\n", Sys.time())) cat(sprintf("Overall: %s\n\n", ifelse(all(comparison$pass), "ALL PASS", "DISCREPANCIES FOUND"))) print(comparison)
期待結果: 比較報告書がすべての統計を許容誤差内で示すこと。
Overall 行に「ALL PASS」と表示されること。
失敗時: 不一致が見つかった場合、主要分析が間違っていると即座に仮定しないこと。両方の実装を調査します:中間計算を確認し、同一の入力データを検証し、欠損値とエッジケースの処理を比較します。
ステップ5: 外部参照(SAS)との比較
RとSASの出力を比較する場合:
# Load SAS results (exported as CSV or from .sas7bdat) sas_results <- list( treatment_estimate = 1.2345, # From SAS PROC GLM output treatment_se = 0.3456, treatment_p = 0.0004, n_subjects = 200, r_squared = 0.4567 ) comparison <- compare_results(primary_results, sas_results, tolerances) # Known sources of difference between R and SAS: # - Default contrasts (R: treatment, SAS: GLM parameterization) # - Rounding of intermediate calculations # - Handling of missing values (na.rm vs listwise deletion)
期待結果: RとSASの比較結果が許容誤差内に収まり、既知の系統的な差異(コントラストコーディング、丸め)が文書化され、説明されていること。
失敗時: RとSASが許容誤差を超えた異なる結果を生成する場合は、差異の3つの最も一般的な原因を確認します:デフォルトのコントラストコーディング(Rは処理コントラスト、SASはGLMパラメータ化を使用)、欠損値の処理、中間計算の丸め。各差異をその根本原因とともに文書化します。
ステップ6: 結果の文書化
バリデーション報告書を作成します:
# validation/output_comparison_report.R sink("validation/output_comparison_report.txt") cat("OUTPUT VALIDATION REPORT\n") cat("========================\n") cat(sprintf("Project: %s\n", project_name)) cat(sprintf("Date: %s\n", format(Sys.time()))) cat(sprintf("Primary Analyst: %s\n", primary_analyst)) cat(sprintf("Independent Analyst: %s\n", independent_analyst)) cat(sprintf("R Version: %s\n\n", R.version.string)) cat("COMPARISON RESULTS\n") cat("------------------\n") print(comparison, row.names = FALSE) cat(sprintf("\nOVERALL VERDICT: %s\n", ifelse(all(comparison$pass), "VALIDATED", "DISCREPANCIES - INVESTIGATION REQUIRED"))) cat("\nSESSION INFO\n") print(sessionInfo()) sink()
期待結果:
validation/output_comparison_report.txt にプロジェクトのメタデータ、比較結果、総合評価、セッション情報を含む完全なバリデーション報告書ファイルが存在すること。
失敗時:
sink() が失敗するか空ファイルを生成する場合は、出力ディレクトリが存在するか確認し(dir.create("validation", showWarnings = FALSE))、前の sink() 呼び出しがまだアクティブでないか確認します(sink.number() を使用)。
ステップ7: 不一致の処理
結果が一致しない場合:
- 両方の実装が同じ入力データを使用していることを確認する(ハッシュ比較)
- NA処理の違いを確認する
- 中間計算をステップごとに比較する
- 根本原因を文書化する
- 差異が許容可能か(許容誤差内で根拠が記録されている)、またはコード修正が必要かを判断する
期待結果: すべての不一致が調査され、根本原因が特定され、各不一致が許容可能(許容誤差内で理由が記録されている)またはコード修正が必要として分類されていること。
失敗時: 不一致を説明できない場合は、統計責任者にエスカレートします。説明のつかない差異は一方の実装に本物のエラーが存在する可能性があるため、無視しないでください。
バリデーション
- 独立した分析が許容誤差内の結果を生成する
- すべての比較統計が文書化されている
- 不一致(ある場合)が調査され、解決されている
- 入力データの整合性が検証されている(ハッシュ一致)
- 許容誤差基準が事前に指定され、正当化されている
- バリデーション報告書が完成し、署名されている
よくある落とし穴
- 同じアナリストが両方の実装を作成: ダブルプログラミングは真のバリデーションのために独立したアナリストが必要
- 実装間でのコードの共有: 独立バージョンは主要バージョンからコピーしてはならない
- 不適切な許容誤差: 緩すぎると本物のエラーを隠す;厳しすぎると浮動小数点のノイズをフラグする
- 系統的差異の無視: 許容誤差内の小さな一貫したバイアスでも本物のエラーを示している場合がある
- バリデーションのバリデートなし: 既知の入力でコンパリゾンコード自体が正しく動作することを確認すること
関連スキル
- バリデート済み作業のプロジェクト構造setup-gxp-r-project
- プロトコルと報告書テンプレートwrite-validation-documentation
- バリデーションプロセス自体の追跡implement-audit-trail
- 継続的バリデーションのための自動テストスイートwrite-testthat-tests