Repository navigation
Attribute-level distance-matched kappa and R2 (ADR 0006) - #13
Conversation
create_attribute_summary.R computes, per rank and physiology, Cohen's kappa (linearly weighted for ordered states) or R2 with held-out tips weighted to the NSTI distribution of the tips to be imputed, plus per-state precision. 01_numeric_val.R now writes its fold predictions for it. Refs #12. Co-authored-by: Claude Code <noreply@anthropic.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
| pos <- attrs_tsv$ordinal_position[ | ||
| match(paste(group, states), paste(attrs_tsv$attribute_group, attrs_tsv$attribute)) | ||
| ] | ||
| ordinal <- length(states) > 2 && all(!is.na(pos)) |
There was a problem hiding this comment.
states is built from the states observed in held-out truth/predictions for this rank, so whether the attribute is "ordinal" depends on how many states happen to appear. The output shows this: biosafety level is weighted kappa at rank all but plain kappa at species/strain (only levels 1 and 2 are seen). Those scores aren't comparable across ranks, and the rank-all weighted value uses a different scale from the others. Likewise, if an intermediate level is missing, the linear weights get distorted (e.g. levels 1 and 3 become adjacent).
Fix: take the state set and order from attributes.tsv for the whole attribute group (all states with an ordinal_position), not from the observed states. Use a single metric per attribute across ranks, and use length(states) > 2 on that full set (with 2 states, weighted and unweighted kappa are the same anyway).
| diag(k) | ||
| } | ||
| expected <- outer(rowSums(cm), colSums(cm)) | ||
| (sum(agree * cm) - sum(agree * expected)) / (1 - sum(agree * expected)) |
There was a problem hiding this comment.
If a fold has 1 - sum(agree * expected) == 0 (all held-out truth and predictions fall in one state, plausible for rare-state attributes and small folds), this returns NaN. mean, sd and lower_bound then propagate NaN to the whole attribute row, and the write.table step would write NaN or NA silently. Handle that case explicitly, either by dropping the fold with a warning or by returning NA and asserting !anyNA(folds$score) in summarise_scores.
| n_folds = nrow(folds), | ||
| score_mean = mean(folds$score), | ||
| score_sd = sd(folds$score), | ||
| score_lcb = lower_bound(folds$score), |
There was a problem hiding this comment.
score_lcb is reported even where the weighting is degenerate. For example, spore shape (all) has ess_fraction 0.036 and max_weight 38.9, and hemolysis has ESS about 0.2 with weights up to 6.9. In those rows a few tips dominate each fold's weighted score, so the t-interval over folds understates the uncertainty. Either set the score to NA, or add an explicit low_ess flag, below a documented ESS threshold. The README says this table decides imputation, so downstream consumers shouldn't have to re-derive the check.
|
Main issues, most important first:
This is a script repo with no package exports, so there were no Bioconductor documentation issues to raise. |
…ppa; tests Address review on #13: the state set and positions of an ordered attribute come from attributes.tsv, so the metric is the same at every rank; a fold whose chance agreement is 1 gives NA with a warning instead of NaN; the scoring functions move to attribute_scores.R with test_attribute_scores.R. Co-authored-by: Claude Code <noreply@anthropic.com>
…ppa at every rank) Co-authored-by: Claude Code <noreply@anthropic.com>
Closes #12. Stacked on #11 (v1.0.7), whose fold files it reads; retarget to main once #11 merges.
create_attribute_summary.Rwritesvalidation_attributes.tsv(one row per rank and physiology: kappa, linearly weighted for ordered attributes, or R2; held-out tips weighted to the NSTI distribution of the tips to be imputed; lower bound of a two-sided 95% t-interval over folds; effective sample size) andvalidation_states.tsv(per-state precision).01_numeric_val.Rnow writes its fold predictions (untracked CSV) for it.all, gram stain, spore formation and aerophilicity pass kappa 0.7; G+C content, coding genes, genome size and growth temperature pass R2 0.5. Same decisions as the evidence in bugphyzzExports ADR 0006.The ordered scales come from bugphyzz
attributes.tsv(ordinal_position, waldronlab/bugphyzz#292); this run used that file from the bugphyzz branch.Drafted with Claude Code; decisions and edits are mine.