You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
434 lines
13 KiB
Plaintext
434 lines
13 KiB
Plaintext
9 months ago
|
*! 3.0.7 9aug2007 TJS & NJC fixed Stata 10 bug by adding missing -version-
|
||
|
* 3.0.6 14may2006 TJS & NJC fixed Stata 9 bug with -by()-
|
||
|
// 3.0.5 22aug2005 Stata 8 - fixed legend(off)
|
||
|
// 3.0.4 27jan2005 TJS & NJC rewrite for Stata 8 + more for graphs
|
||
|
// 3.0.3 6oct2004 TJS & NJC rewrite for Stata 8
|
||
|
// 3.0.2 6oct2004 TJS & NJC rewrite for Stata 8
|
||
|
// 3.0.1 4oct2004 TJS & NJC rewrite for Stata 8 + fixes + noref
|
||
|
// 3.0.0 27jul2004 TJS & NJC rewrite for Stata 8
|
||
|
// 3.0.0 19jul2004 TJS & NJC rewrite for Stata 8
|
||
|
// 2.2.9 14jan2003 TJS & NJC handling of [ ] within connect()
|
||
|
// 2.2.8 2jan2003 TJS & NJC handling of [ ] within symbol()
|
||
|
// 2.2.7 30jan2002 TJS & NJC rho_se corrected (SJ2-2: st0015)
|
||
|
// 2.2.6 10dec2001 TJS & NJC bug fixes (labels, diag line)
|
||
|
// 2.2.5 23apr2001 TJS & NJC sortpreserve
|
||
|
// 2.2.4 24jan2001 TJS & NJC l1title for loa
|
||
|
// 2.2.3 8sep2000 TJS & NJC bug fixes & mods (STB-58: sg84.3)
|
||
|
// 2.2.0 16dec1999 TJS & NJC version 6 changes (STB-54: sg84.2)
|
||
|
// 2.1.6 18jun1998 TJS & NJC STB-45 sg84.1
|
||
|
// 2.0.2 6mar1998 TJS & NJC STB-43 sg84
|
||
|
//
|
||
|
// syntax: concord vary varx [fw] [if] [in] [,
|
||
|
// BY(varname) Summary LEvel(real `c(level)')
|
||
|
// CCC(str) LOA(str) QNORMD(str) ]
|
||
|
|
||
|
program concord, rclass sortpreserve
|
||
|
// Syntax help
|
||
|
if "`1'" == "" {
|
||
|
di "{p}{txt}Syntax is: {inp:concord} " ///
|
||
|
"{it:vary varx} [{it:weight}] " ///
|
||
|
"[{inp:if} {it:exp}] [{inp:in} {it:range}] " ///
|
||
|
"[, {inp:by(}{it:byvar}{inp:)} " ///
|
||
|
"{inp:summary level(}{it:#}{inp:)} " ///
|
||
|
"{inp:ccc}[{inp:(noref} {it:ccc_options}{inp:)}] " ///
|
||
|
"{inp:loa}[{inp:(noref regline} {it:loa_options}{inp:)}] " ///
|
||
|
"{inp:qnormd}[{inp:(}{it:qnormd_options}{inp:)}] {p_end}"
|
||
|
exit 0
|
||
|
}
|
||
|
|
||
|
// Setup
|
||
|
version 8
|
||
|
syntax varlist(numeric min=2 max=2) ///
|
||
|
[fw] ///
|
||
|
[if] [in] ///
|
||
|
[ , BY(varname) ///
|
||
|
Summary ///
|
||
|
LEvel(real `c(level)') ///
|
||
|
ccc(str asis) ///
|
||
|
CCC2 ///
|
||
|
loa(str asis) ///
|
||
|
LOA2 ///
|
||
|
qnormd(str asis) ///
|
||
|
QNORMD2 * ]
|
||
|
|
||
|
marksample touse
|
||
|
qui count if `touse'
|
||
|
if r(N) == 0 error 2000
|
||
|
|
||
|
tokenize `varlist'
|
||
|
|
||
|
// Set temporary names
|
||
|
tempvar d d2 db dll dul m byg kk bylabel
|
||
|
tempname dsd zv k xb yb sx2 sy2 r rp sxy p u sep z zp
|
||
|
tempname t set ll ul llt ult rdm Fdm zt ztp sd1 sd2 sl
|
||
|
|
||
|
// Set up wgt
|
||
|
if "`weight'" != "" local wgt "[`weight'`exp']"
|
||
|
|
||
|
// Generate CI z-value and label from Level()
|
||
|
if `level' < 1 local level = `level' * 100
|
||
|
scalar `zv' = -1 * invnorm((1 - `level' / 100) / 2)
|
||
|
local rl = `level'
|
||
|
local level : di %7.0g `level'
|
||
|
local level = ltrim("`level'")
|
||
|
|
||
|
// Generate BY groups
|
||
|
qui {
|
||
|
bysort `touse' `by' : gen byte `byg' = _n == 1 if `touse'
|
||
|
if "`by'" != "" gen `kk' = _n if `byg' == 1
|
||
|
replace `byg' = sum(`byg')
|
||
|
local byn = `byg'[_N]
|
||
|
|
||
|
// Generate `by' labels -- if required
|
||
|
if "`by'" != "" {
|
||
|
capture decode `by', gen(`bylabel')
|
||
|
if _rc != 0 {
|
||
|
local type : type `by'
|
||
|
gen `type' `bylabel' = `by'
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Print title
|
||
|
di
|
||
|
di as txt "Concordance correlation coefficient (Lin, 1989, 2000):"
|
||
|
|
||
|
// Do calculations
|
||
|
forval j = 1/`byn' { /* start of loop for each `by' group */
|
||
|
di
|
||
|
if "`by'" != "" {
|
||
|
sort `kk'
|
||
|
di as txt "{hline}"
|
||
|
di as txt "-> `by' = " `bylabel'[`j'] _n
|
||
|
local byl : di "`by' = " `bylabel'[`j']
|
||
|
}
|
||
|
|
||
|
// LOA (Bland & Altman) calculations
|
||
|
qui {
|
||
|
gen `d' = `1' - `2'
|
||
|
gen `d2' = `d'^2
|
||
|
su `d' if `byg' == `j' `wgt'
|
||
|
gen `db' = r(mean)
|
||
|
scalar `dsd' = r(sd)
|
||
|
gen `dll' = `db' - `zv' * `dsd'
|
||
|
gen `dul' = `db' + `zv' * `dsd'
|
||
|
gen `m' = (`1' + `2') / 2
|
||
|
}
|
||
|
|
||
|
// Concordance calculations
|
||
|
qui su `1' if `byg' == `j' `wgt'
|
||
|
scalar `k' = r(N)
|
||
|
scalar `yb' = r(mean)
|
||
|
scalar `sy2' = r(Var) * (`k' - 1) / `k'
|
||
|
scalar `sd1' = r(sd)
|
||
|
|
||
|
qui su `2' if `byg' == `j' `wgt'
|
||
|
scalar `xb' = r(mean)
|
||
|
scalar `sx2' = r(Var) * (`k' - 1) / `k'
|
||
|
scalar `sd2' = r(sd)
|
||
|
|
||
|
qui corr `1' `2' if `byg' == `j' `wgt'
|
||
|
scalar `r' = r(rho)
|
||
|
scalar `sl' = sign(`r') * `sd1' / `sd2'
|
||
|
|
||
|
scalar `rp' = min(tprob(r(N) - 2, r(rho) * sqrt(r(N) - 2) ///
|
||
|
/ sqrt(1 - r(rho)^2)) ,1)
|
||
|
scalar `sxy' = `r' * sqrt(`sx2' * `sy2')
|
||
|
scalar `p' = 2 * `sxy' / (`sx2' + `sy2' + (`yb' - `xb')^2)
|
||
|
scalar `u' = (`yb' - `xb') / (`sx2' * `sy2')^.25
|
||
|
|
||
|
// --- variance, test, and CI for asymptotic normal approximation
|
||
|
// scalar `sep' = sqrt(((1 - ((`r')^2)) * (`p')^2 * (1 -
|
||
|
// ((`p')^2)) / (`r')^2 + (4 * (`p')^3 * (1 - `p') * (`u')^2
|
||
|
// / `r') - 2 * (`p')^4 * (`u')^4 / (`r')^2 ) / (`k' - 2))
|
||
|
// Corrected se: per Lin (March 2000) Biometrics 56:325-5.
|
||
|
#delimit ;
|
||
|
scalar `sep' = sqrt(((1 - ((`r')^2)) * (`p')^2 * (1 -
|
||
|
((`p')^2)) / (`r')^2 + (2 * (`p')^3 * (1 - `p') * (`u')^2
|
||
|
/ `r') - .5 * (`p')^4 * (`u')^4 / (`r')^2 ) / (`k' - 2));
|
||
|
#delimit cr
|
||
|
scalar `z' = `p' / `sep'
|
||
|
scalar `zp' = 2 * (1 - normprob(abs(`z')))
|
||
|
scalar `ll' = `p' - `zv' * `sep'
|
||
|
scalar `ul' = `p' + `zv' * `sep'
|
||
|
|
||
|
// --- statistic, variance, test, and CI for inverse hyperbolic
|
||
|
// tangent transform to improve asymptotic normality
|
||
|
scalar `t' = ln((1 + `p') / (1 - `p')) / 2
|
||
|
scalar `set' = `sep' / (1 - ((`p')^2))
|
||
|
scalar `zt' = `t' / `set'
|
||
|
scalar `ztp' = 2 * (1 - normprob(abs(`zt')))
|
||
|
scalar `llt' = `t' - `zv' * `set'
|
||
|
scalar `ult' = `t' + `zv' * `set'
|
||
|
scalar `llt' = (exp(2 * `llt') - 1) / (exp(2 * `llt') + 1)
|
||
|
scalar `ult' = (exp(2 * `ult') - 1) / (exp(2 * `ult') + 1)
|
||
|
|
||
|
// Print output
|
||
|
di as txt " rho_c SE(rho_c) Obs [" _c
|
||
|
if index("`level'",".") {
|
||
|
di as txt %6.1f `level' "% CI ] P CI type"
|
||
|
}
|
||
|
else di as txt " `level'% CI ] P CI type"
|
||
|
|
||
|
di as txt "{hline 63}"
|
||
|
di as res %6.3f `p' %10.3f `sep' %8.0f `k' %10.3f `ll' _c
|
||
|
di as res %7.3f `ul' %9.3f `zp' as txt " asymptotic"
|
||
|
di as res _dup(24) " " %10.3f `llt' %7.3f `ult' %9.3f `ztp' _c
|
||
|
di as txt " z-transform"
|
||
|
|
||
|
di _n as txt "Pearson's r =" as res %7.3f `r' _c
|
||
|
di as txt " Pr(r = 0) =" as res %6.3f `rp' _c
|
||
|
di as txt " C_b = rho_c/r =" as res %7.3f `p' / `r'
|
||
|
di as txt "Reduced major axis: Slope = " as res %9.3f `sl' _c
|
||
|
di as txt " Intercept = " as res %9.3f `yb'-`xb'*`sl'
|
||
|
di _n as txt "Difference = `1' - `2'"
|
||
|
di _n as txt " Difference" _c
|
||
|
if index("`level'", ".") {
|
||
|
di _col(33) as txt %6.1f `level' "% Limits Of Agreement"
|
||
|
}
|
||
|
else di _col(33) as txt " `level'% Limits Of Agreement"
|
||
|
di as txt " Average Std Dev. (Bland & Altman, 1986)"
|
||
|
di as txt "{hline 63}"
|
||
|
di as res %10.3f `db' %12.3f `dsd' _c
|
||
|
di as res " " %11.3f `dll' %11.3f `dul'
|
||
|
|
||
|
qui corr `d' `m' if `byg' == `j' `wgt'
|
||
|
scalar `rdm' = r(rho)
|
||
|
di _n as txt "Correlation between difference and mean =" _c
|
||
|
local fmt = cond(r(rho) < 0, "%7.3f", "%6.3f")
|
||
|
di as res `fmt' r(rho)
|
||
|
|
||
|
su `d2' if `byg' == `j' `wgt', meanonly
|
||
|
local sumd2 = r(sum)
|
||
|
qui reg `d' `m' if `byg' == `j' `wgt'
|
||
|
scalar `Fdm' = ((`sumd2' - e(rss)) / 2) / (e(rss) / e(df_r))
|
||
|
di _n as txt "Bradley-Blackwood F = " ///
|
||
|
as res %4.3f `Fdm' ///
|
||
|
as txt " (P = " %6.5f ///
|
||
|
as res 1 - F(2, e(df_r), `Fdm') ///
|
||
|
as txt ")"
|
||
|
|
||
|
if "`summary'" != "" su `1' `2' if `byg' == `j' `wgt'
|
||
|
|
||
|
// setup local options for passing to graph routines
|
||
|
if "`byl'" != "" local byls byl("`byl'")
|
||
|
if "`level'" != "" local levs level(`level')
|
||
|
|
||
|
// set more if needed
|
||
|
if (`"`loa'`loa2'"' != "" & `"`qnormd'`qnormd2'"' != "") | ///
|
||
|
(`"`loa'`loa2'"' != "" & `"`ccc'`ccc2'"' != "") | ///
|
||
|
(`"`ccc'`ccc2'"' != "" & `"`qnormd'`qnormd2'"' != "") {
|
||
|
|
||
|
local moreflag "more"
|
||
|
}
|
||
|
|
||
|
// loa graph
|
||
|
if `"`loa'`loa2'"' != "" {
|
||
|
gphloa `2' `1' `dll' `db' `dul' `d' `m' `byg' ///
|
||
|
`wgt', j(`j') byn(`byn') `byls' `levs' `loa' `options'
|
||
|
|
||
|
`moreflag'
|
||
|
}
|
||
|
|
||
|
// qnormd graph
|
||
|
if `"`qnormd'`qnormd2'"' != "" {
|
||
|
gphqnormd `2' `1' `d' `byg' ///
|
||
|
`wgt', j(`j') byn(`byn') `byls' `levs' `qnormd' `options'
|
||
|
|
||
|
`moreflag'
|
||
|
}
|
||
|
|
||
|
// ccc graph
|
||
|
if `"`ccc'`ccc2'"' != "" {
|
||
|
local sll = `sl'
|
||
|
local xbl = `xb'
|
||
|
local ybl = `yb'
|
||
|
gphccc `1' `2' `byg' `wgt', j(`j') ///
|
||
|
xb(`xbl') yb(`ybl') sl(`sll') byn(`byn') `byls' `ccc' `options'
|
||
|
}
|
||
|
|
||
|
if `byn' > 1 {
|
||
|
capture drop `d'
|
||
|
capture drop `d2'
|
||
|
capture drop `db'
|
||
|
capture drop `dll'
|
||
|
capture drop `dul'
|
||
|
capture drop `m'
|
||
|
}
|
||
|
|
||
|
} /* end of loop for each `by' group */
|
||
|
|
||
|
// save globals
|
||
|
if `byn' == 1 {
|
||
|
return scalar N = `k'
|
||
|
return scalar rho_c = `p'
|
||
|
return scalar se_rho_c = `sep'
|
||
|
return scalar asym_ll = `ll'
|
||
|
return scalar asym_ul = `ul'
|
||
|
return scalar z_tr_ll = `llt'
|
||
|
return scalar z_tr_ul = `ult'
|
||
|
return scalar C_b = `p' / `r'
|
||
|
return scalar diff = `db'
|
||
|
return scalar sd_diff = `dsd'
|
||
|
return scalar LOA_ll = `dll'
|
||
|
return scalar LOA_ul = `dul'
|
||
|
return scalar rdm = `rdm'
|
||
|
return scalar Fdm = `Fdm'
|
||
|
|
||
|
// double save globals
|
||
|
// now undocumented as of 3.0.0
|
||
|
global S_1 = `k'
|
||
|
global S_2 = `p'
|
||
|
global S_3 = `sep'
|
||
|
global S_4 = `ll'
|
||
|
global S_5 = `ul'
|
||
|
global S_6 = `llt'
|
||
|
global S_7 = `ult'
|
||
|
global S_8 = `p' / `r'
|
||
|
global S_9 = `db'
|
||
|
global S_10 = `dsd'
|
||
|
global S_11 = `dll'
|
||
|
global S_12 = `dul'
|
||
|
}
|
||
|
end
|
||
|
|
||
|
program gphloa
|
||
|
// loa graph
|
||
|
version 8
|
||
|
syntax varlist(numeric min=2) [fw] ///
|
||
|
[ , J(int 1) BYN(int 1) BYL(str) REGline LEvel(real `c(level)') ///
|
||
|
plot(str asis) noREF * ]
|
||
|
|
||
|
tokenize `varlist'
|
||
|
args two one dll db dul d m byg
|
||
|
if "`weight'" != "" local wgt "[`weight'`exp']"
|
||
|
|
||
|
if `"`byl'"' != "" local t2title `"t2title(`byl')"'
|
||
|
|
||
|
local name2 : variable label `2'
|
||
|
local name1 : variable label `1'
|
||
|
local lnth = length(`"`name2'"') + length(`"`name1'"')
|
||
|
if `"`name2'"' == `""' | `lnth' > 50 local name2 "`2'"
|
||
|
if `"`name1'"' == `""' | `lnth' > 50 local name1 "`1'"
|
||
|
|
||
|
qui if "`regline'" != "" {
|
||
|
tempvar fit
|
||
|
regress `d' `m' if `byg' == `j' `wgt'
|
||
|
predict `fit'
|
||
|
}
|
||
|
|
||
|
if "`ref'" == "" {
|
||
|
local ord 2 3
|
||
|
if "`regline'" != "" local ord 2 3 4
|
||
|
local zero yli(0, lstyle(refline)) yscale(range(0)) ylabel(0, add) ///
|
||
|
legend(on order(`ord') label(2 observed average agreement) ///
|
||
|
label(3 `"`level'% limits of agreement"') label(4 regression line)) ///
|
||
|
caption("y=0 is line of perfect average agreement")
|
||
|
}
|
||
|
|
||
|
graph twoway line `dll' `db' `dul' `fit' `m' if `byg' == `j', ///
|
||
|
clcolor(red purple red green) sort ///
|
||
|
|| scatter `d' `m' if `byg' == `j' ///
|
||
|
, ms(oh) `t2title' ///
|
||
|
yti(`"Difference of `name2' and `name1'"') ///
|
||
|
xti(`"Mean of `name2' and `name1'"') ///
|
||
|
caption("`level'% Limits Of Agreement") legend(off) `zero' ///
|
||
|
`options' ///
|
||
|
|| `plot'
|
||
|
|
||
|
if `byn' > 1 more
|
||
|
end
|
||
|
|
||
|
program gphqnormd, sort
|
||
|
// normal prob plot
|
||
|
// note: logic pilfered from qnorm
|
||
|
version 8
|
||
|
syntax varlist(numeric min=2) [fw] ///
|
||
|
[ , J(int 1) BYN(int 1) BYL(str) LEvel(real `c(level)') ///
|
||
|
plot(str asis) * ]
|
||
|
|
||
|
args two one d byg
|
||
|
if "`weight'" != "" local wgt "[`weight'`exp']"
|
||
|
else local exp 1
|
||
|
|
||
|
local name2 : variable label `2'
|
||
|
local name1 : variable label `1'
|
||
|
local lnth = length(`"`name2'"') + length(`"`name1'"')
|
||
|
if `"`name2'"' == `""' | `lnth' > 50 local name2 "`2'"
|
||
|
if `"`name1'"' == `""' | `lnth' > 50 local name1 "`1'"
|
||
|
|
||
|
tempvar Z Psubi touse2
|
||
|
mark `touse2' if `byg' == `j'
|
||
|
qui {
|
||
|
gsort -`touse2' `d'
|
||
|
gen `Psubi' = sum(`touse2' * `exp')
|
||
|
replace `Psubi' = cond(`touse2' == 0, ., `Psubi'/(`Psubi'[_N] + 1))
|
||
|
su `d' if `touse2' == 1 `wgt'
|
||
|
gen float `Z' = invnorm(`Psubi') * r(sd) + r(mean)
|
||
|
label var `Z' "Inverse Normal"
|
||
|
local xttl : var label `Z'
|
||
|
local yttl `"Difference of `name2' and `name1'"'
|
||
|
}
|
||
|
|
||
|
if `"`byl'"' != "" local t2title `"t2title(`byl')"'
|
||
|
|
||
|
graph twoway ///
|
||
|
(scatter `d' `Z', ///
|
||
|
sort ///
|
||
|
ytitle(`"`yttl'"') ///
|
||
|
xtitle(`"`xttl'"') ///
|
||
|
`t2title' ///
|
||
|
`options' ///
|
||
|
) ///
|
||
|
(function y=x, ///
|
||
|
range(`Z') ///
|
||
|
n(2) ///
|
||
|
clstyle(refline) ///
|
||
|
yvarlabel("Reference") ///
|
||
|
yvarformat(`fmt') ///
|
||
|
) ///
|
||
|
, legend(off) ///
|
||
|
|| `plot'
|
||
|
|
||
|
if `byn' > 1 more
|
||
|
end
|
||
|
|
||
|
program gphccc
|
||
|
version 8
|
||
|
//-----------------------------------------------------
|
||
|
// ccc graph
|
||
|
// ----------------------------------------------------
|
||
|
syntax varlist(numeric min=2) [fw] [ , J(int 1) XB(real 0) noREF ///
|
||
|
YB(real 0) SL(real 0) BYN(int 1) BYL(str) plot(str asis) LEGEND(str) * ]
|
||
|
|
||
|
tokenize `varlist'
|
||
|
tempvar byg rmaxis
|
||
|
local byg `3'
|
||
|
if "`weight'" != "" local wgt "[`weight'`exp']"
|
||
|
|
||
|
local yttl : variable label `1'
|
||
|
if `"`yttl'"' == "" local yttl "`1'"
|
||
|
local xttl : variable label `2'
|
||
|
if `"`xttl'"' == "" local xttl "`2'"
|
||
|
|
||
|
if "`ref'" == "" local lopc || function y = x, ra(`2') clstyle(refline) ///
|
||
|
legend(on order(2 "reduced major axis" 3 "line of perfect concordance"))
|
||
|
|
||
|
if "`legend'" != "" {
|
||
|
local legnd "legend(`legend')"
|
||
|
}
|
||
|
|
||
|
// Graph concordance plot
|
||
|
qui gen `rmaxis' = `sl' * (`2' - `xb') + `yb'
|
||
|
|
||
|
graph twoway scatter `1' `rmaxis' `2' ///
|
||
|
if `byg' == `j' `wgt', ///
|
||
|
sort connect(none line) ms(oh none) ///
|
||
|
yti(`"`yttl'"') xti(`"`xttl'"') legend(off) `lopc' ///
|
||
|
`options' ///
|
||
|
|| `plot'
|
||
|
|
||
|
if `byn' > 1 more
|
||
|
end
|
||
|
|