ps_trunc() bounds extreme propensity scores to fixed limits, replacing
out-of-range values with the boundary value (a form of winsorizing). The
result is a vector or matrix of the same length and dimensions as ps, with
no observations removed. This contrasts with ps_trim(), which sets extreme
values to NA (effectively removing those observations from analysis).
Usage
ps_trunc(
ps,
method = c("ps", "pctl", "cr"),
lower = NULL,
upper = NULL,
.exposure = NULL,
.focal_level = NULL,
.reference_level = NULL,
...,
.treated = NULL,
.untreated = NULL
)Arguments
- ps
A numeric vector of propensity scores between 0 and 1 (binary exposures), or a matrix/data.frame where each column contains propensity scores for one level of a categorical exposure.
- method
One of
"ps","pctl", or"cr":"ps"(default): Truncate directly on propensity score values. Values outside[lower, upper]are set to the nearest bound. For categorical exposures, applies symmetric truncation usingloweras the threshold (delta) and renormalizes rows to sum to 1."pctl": Truncate at quantiles of the propensity score distribution. Thelowerandupperarguments specify quantile probabilities. For categorical exposures, quantiles are computed across all columns."cr": Truncate to the common range of propensity scores across exposure groups (binary exposures only). Bounds are[min(ps[focal]), max(ps[reference])]. Requires.exposure.
- lower, upper
Bounds for truncation. Interpretation depends on
method:method = "ps": Propensity score values (defaults: 0.1 and 0.9). For categorical exposures,loweris the truncation threshold delta (default: 0.01);upperis ignored.method = "pctl": Quantile probabilities (defaults: 0.05 and 0.95; categorical defaults: 0.01 and 0.99).method = "cr": Ignored; bounds are determined by the data.
- .exposure
An exposure vector. Required for method
"cr"(binary exposure vector) and for categorical exposures (factor or character vector) with any method.- .focal_level
The value of
.exposurerepresenting the focal (treated) group. For binary exposures, defaults to the higher value. Required forwt_att()andwt_atu()with categorical exposures.- .reference_level
The value of
.exposurerepresenting the reference (control) group. Automatically detected if not supplied.- ...
Additional arguments passed to methods.
- .treated
- .untreated
Value
A ps_trunc object (a numeric vector for binary exposures, or a
matrix for categorical exposures). Use ps_trunc_meta() to inspect
metadata including method, lower_bound, upper_bound, and
truncated_idx (positions of modified values).
Details
Unlike ps_trim(), truncation preserves all observations. No NA values
are introduced; out-of-range scores are replaced with the boundary value.
For binary exposures, each propensity score \(e_i\) is bounded:
If \(e_i < l\), set \(e_i = l\) (the lower bound).
If \(e_i > u\), set \(e_i = u\) (the upper bound).
For categorical exposures, values below the threshold are set to the threshold and each row is renormalized to sum to 1.
Arithmetic behavior: Arithmetic operations on ps_trunc objects return
plain numeric vectors. Once propensity scores are transformed (e.g., into
weights), the result is no longer a propensity score.
Combining behavior: Combining ps_trunc objects with c() requires
matching truncation parameters. Mismatched parameters produce a warning and
return a plain numeric vector.
References
Crump, R. K., Hotz, V. J., Imbens, G. W., & Mitnik, O. A. (2009). Dealing with limited overlap in estimation of average treatment effects. Biometrika, 96(1), 187–199.
Walker, A. M., Patrick, A. R., Lauer, M. S., et al. (2013). A tool for assessing the feasibility of comparative effectiveness research. Comparative Effectiveness Research, 3, 11–20.
See also
ps_trim() for removing (rather than bounding) extreme values,
ps_refit() for refitting the propensity model after trimming,
is_ps_truncated(), is_unit_truncated(), ps_trunc_meta()
Examples
set.seed(2)
n <- 200
x <- rnorm(n)
z <- rbinom(n, 1, plogis(1.2 * x))
fit <- glm(z ~ x, family = binomial)
ps <- predict(fit, type = "response")
# Truncate to [0.1, 0.9]
ps_t <- ps_trunc(ps, method = "ps", lower = 0.1, upper = 0.9)
ps_t
#> <ps_trunc{[0.1,0.9], method=ps}[200]>
#> 1 2 3 4 5 6 7 8
#> 0.2913095 0.5707511 0.8590561 0.2418820 0.4993060 0.5567591 0.7011122 0.4561604
#> 9 10 11 12 13 14 15 16
#> 0.9000000 0.4834312 0.6312438 0.7594616 0.4153613 0.2603881 0.8827176 0.1000000
#> 17 18 19 20 21 22 23 24
#> 0.7384237 0.5307543 0.7655683 0.6349278 0.9000000 0.2283122 0.8592915 0.9000000
#> 25 26 27 28 29 30 31 32
#> 0.5224033 0.1000000 0.6461643 0.3628349 0.7199125 0.5983593 0.7081103 0.6059826
#> 33 34 35 36 37 38 39 40
#> 0.7776782 0.4442186 0.3189618 0.3630602 0.1432262 0.2900408 0.3722937 0.4543264
#> 41 42 43 44 45 46 47 48
#> 0.4177638 0.1148898 0.3038315 0.8956760 0.6813225 0.9000000 0.4385124 0.4964323
#> 49 50 51 52 53 54 55 56
#> 0.4711469 0.2285337 0.3046166 0.9000000 0.3714863 0.8128663 0.2587396 0.1141443
#> 57 58 59 60 61 62 63 64
#> 0.4338453 0.7502468 0.7892860 0.8697086 0.1351329 0.9000000 0.3365403 0.5636424
#> 65 66 67 68 69 70 71 72
#> 0.6533256 0.3088378 0.1105762 0.3927369 0.5438044 0.2916295 0.2858818 0.6089556
#> 73 74 75 76 77 78 79 80
#> 0.4826524 0.6355772 0.5065031 0.2890305 0.8174117 0.7154239 0.7732114 0.1906359
#> 81 82 83 84 85 86 87 88
#> 0.7622717 0.1472971 0.3788316 0.1970403 0.1000000 0.8871259 0.3486998 0.4440783
#> 89 90 91 92 93 94 95 96
#> 0.4168763 0.6233901 0.8606965 0.8708768 0.2314475 0.1994226 0.1740398 0.2183041
#> 97 98 99 100 101 102 103 104
#> 0.9000000 0.5231365 0.3036226 0.3616811 0.7773582 0.5907629 0.4361655 0.3253709
#> 105 106 107 108 109 110 111 112
#> 0.2991480 0.9000000 0.7510710 0.9000000 0.4078242 0.4264336 0.2629645 0.4532487
#> 113 114 115 116 117 118 119 120
#> 0.6448288 0.8262184 0.6674247 0.6408723 0.8053646 0.7907095 0.5498332 0.3173982
#> 121 122 123 124 125 126 127 128
#> 0.8071017 0.5584826 0.8744315 0.4053976 0.2594361 0.6609892 0.3447196 0.6851535
#> 129 130 131 132 133 134 135 136
#> 0.1434914 0.1410494 0.6969682 0.6090883 0.7368408 0.1087328 0.8022199 0.8001309
#> 137 138 139 140 141 142 143 144
#> 0.7692948 0.7186431 0.9000000 0.1834141 0.3662171 0.6292392 0.3118604 0.5441734
#> 145 146 147 148 149 150 151 152
#> 0.7097460 0.3486308 0.6894218 0.6639810 0.3119192 0.2693231 0.7582975 0.4751339
#> 153 154 155 156 157 158 159 160
#> 0.7043397 0.3032090 0.8131267 0.2020948 0.7139969 0.6429234 0.5927018 0.6918371
#> 161 162 163 164 165 166 167 168
#> 0.6263848 0.3524856 0.4486289 0.6165339 0.2074392 0.2942181 0.9000000 0.1003085
#> 169 170 171 172 173 174 175 176
#> 0.2210197 0.7611782 0.7800143 0.7302196 0.5364399 0.6072561 0.2895753 0.3489979
#> 177 178 179 180 181 182 183 184
#> 0.4500408 0.2829251 0.7262051 0.1573127 0.2623292 0.2166743 0.6247878 0.2416706
#> 185 186 187 188 189 190 191 192
#> 0.6625838 0.7959533 0.5278943 0.6555095 0.3485232 0.6526880 0.2148033 0.5002503
#> 193 194 195 196 197 198 199 200
#> 0.2017086 0.4490035 0.7798096 0.6994296 0.4022315 0.3161761 0.3003833 0.3261363
# Truncate at the 1st and 99th percentiles
ps_trunc(ps, method = "pctl", lower = 0.01, upper = 0.99)
#> <ps_trunc{[0.0900660672917143,0.912020808232711], method=pctl}[200]>
#> 1 2 3 4 5 6 7
#> 0.29130945 0.57075108 0.85905610 0.24188201 0.49930600 0.55675915 0.70111217
#> 8 9 10 11 12 13 14
#> 0.45616038 0.90360175 0.48343119 0.63124383 0.75946160 0.41536130 0.26038808
#> 15 16 17 18 19 20 21
#> 0.88271762 0.09006607 0.73842370 0.53075430 0.76556830 0.63492785 0.91202081
#> 22 23 24 25 26 27 28
#> 0.22831221 0.85929151 0.90074563 0.52240328 0.09006607 0.64616425 0.36283492
#> 29 30 31 32 33 34 35
#> 0.71991248 0.59835929 0.70811028 0.60598256 0.77767823 0.44421858 0.31896179
#> 36 37 38 39 40 41 42
#> 0.36306016 0.14322616 0.29004079 0.37229372 0.45432638 0.41776382 0.11488981
#> 43 44 45 46 47 48 49
#> 0.30383148 0.89567605 0.68132246 0.90420941 0.43851237 0.49643227 0.47114693
#> 50 51 52 53 54 55 56
#> 0.22853370 0.30461661 0.91106441 0.37148631 0.81286633 0.25873963 0.11414425
#> 57 58 59 60 61 62 63
#> 0.43384531 0.75024682 0.78928598 0.86970860 0.13513287 0.90793306 0.33654034
#> 64 65 66 67 68 69 70
#> 0.56364237 0.65332558 0.30883775 0.11057616 0.39273691 0.54380444 0.29162947
#> 71 72 73 74 75 76 77
#> 0.28588182 0.60895559 0.48265241 0.63557725 0.50650310 0.28903045 0.81741170
#> 78 79 80 81 82 83 84
#> 0.71542388 0.77321135 0.19063586 0.76227170 0.14729713 0.37883165 0.19704028
#> 85 86 87 88 89 90 91
#> 0.09015377 0.88712592 0.34869977 0.44407832 0.41687627 0.62339015 0.86069650
#> 92 93 94 95 96 97 98
#> 0.87087680 0.23144748 0.19942258 0.17403983 0.21830407 0.90120123 0.52313647
#> 99 100 101 102 103 104 105
#> 0.30362260 0.36168114 0.77735817 0.59076288 0.43616553 0.32537093 0.29914802
#> 106 107 108 109 110 111 112
#> 0.90944557 0.75107099 0.90586644 0.40782418 0.42643359 0.26296452 0.45324867
#> 113 114 115 116 117 118 119
#> 0.64482877 0.82621843 0.66742471 0.64087231 0.80536462 0.79070955 0.54983317
#> 120 121 122 123 124 125 126
#> 0.31739822 0.80710169 0.55848264 0.87443145 0.40539762 0.25943605 0.66098916
#> 127 128 129 130 131 132 133
#> 0.34471960 0.68515350 0.14349137 0.14104940 0.69696824 0.60908833 0.73684079
#> 134 135 136 137 138 139 140
#> 0.10873282 0.80221987 0.80013088 0.76929476 0.71864309 0.91202081 0.18341413
#> 141 142 143 144 145 146 147
#> 0.36621714 0.62923918 0.31186040 0.54417339 0.70974601 0.34863085 0.68942181
#> 148 149 150 151 152 153 154
#> 0.66398099 0.31191915 0.26932313 0.75829753 0.47513393 0.70433975 0.30320896
#> 155 156 157 158 159 160 161
#> 0.81312672 0.20209485 0.71399686 0.64292343 0.59270175 0.69183710 0.62638476
#> 162 163 164 165 166 167 168
#> 0.35248559 0.44862887 0.61653394 0.20743922 0.29421813 0.91200893 0.10030845
#> 169 170 171 172 173 174 175
#> 0.22101971 0.76117824 0.78001428 0.73021961 0.53643993 0.60725607 0.28957526
#> 176 177 178 179 180 181 182
#> 0.34899794 0.45004081 0.28292513 0.72620510 0.15731275 0.26232917 0.21667429
#> 183 184 185 186 187 188 189
#> 0.62478778 0.24167062 0.66258378 0.79595325 0.52789428 0.65550948 0.34852324
#> 190 191 192 193 194 195 196
#> 0.65268801 0.21480329 0.50025030 0.20170859 0.44900347 0.77980959 0.69942959
#> 197 198 199 200
#> 0.40223149 0.31617609 0.30038326 0.32613630
# Use truncated scores to calculate weights
wt_ate(ps_t, .exposure = z)
#> ℹ Treating `.exposure` as binary
#> ℹ Setting focal level to 1
#> <psw{estimand = ate; truncated}[200]>
#> [1] 1.411053 2.329651 1.164068 1.319056 2.002780 2.256110 1.426305 1.838777
#> [9] 1.111111 2.068547 2.711819 1.316722 1.710458 1.352060 1.132865 1.111111
#> [17] 1.354236 1.884111 1.306219 2.739185 1.111111 1.295861 1.163749 1.111111
#> [25] 2.093817 1.111111 1.547594 1.569452 1.389058 1.671237 1.412209 2.537959
#> [33] 4.497985 1.799268 1.468346 2.754364 1.167169 3.447791 2.686051 1.832597
#> [41] 2.393697 1.129803 3.291298 1.116475 1.467734 1.111111 2.280437 2.014373
#> [49] 1.890884 1.296233 1.438056 1.111111 1.591055 1.230215 3.864889 1.128852
#> [57] 1.766302 4.003953 4.745769 1.149810 7.400124 1.111111 1.507251 1.774175
#> [65] 1.530630 3.237946 1.124323 2.546234 1.838896 1.411691 1.400328 1.642156
#> [73] 1.932936 1.573373 1.974322 3.459843 1.223374 1.397773 1.293307 1.235538
#> [81] 1.311868 1.172741 2.639695 1.245392 1.111111 1.127236 2.867797 1.798815
#> [89] 2.398793 2.655268 1.161850 1.148268 1.301147 5.014477 1.210712 1.279270
#> [97] 1.111111 2.097036 1.436003 1.566615 1.286408 1.692727 1.773570 1.482296
#> [105] 1.426835 1.111111 1.331432 1.111111 2.452037 2.345031 1.356787 1.828985
#> [113] 1.550799 1.210334 1.498296 1.560373 5.137812 1.264687 1.818733 3.150616
#> [121] 5.184079 1.790566 1.143600 2.466714 1.350322 1.512884 1.526064 3.176151
#> [129] 1.167531 7.089715 1.434786 2.558123 3.799981 1.121998 1.246541 1.249796
#> [137] 1.299892 1.391511 1.111111 5.452143 1.577827 2.697157 1.453194 2.193817
#> [145] 1.408955 1.535228 1.450491 2.976022 1.453318 3.713012 4.137318 1.905248
#> [153] 1.419769 1.435150 5.351220 1.253282 1.400566 1.555395 1.687189 3.245037
#> [161] 2.676550 1.544367 2.229014 1.621971 4.820689 1.416868 1.111111 1.111492
#> [169] 4.524483 1.313753 4.545750 1.369451 2.157218 2.546188 1.407609 2.865346
#> [177] 2.222021 1.394555 1.377021 1.186680 1.355618 1.276608 2.665158 1.318688
#> [185] 1.509243 1.256355 1.894319 1.525531 2.869249 2.879256 1.273566 2.001002
#> [193] 1.252675 1.814893 1.282364 3.327007 1.672888 1.462365 1.429354 1.483980
# Inspect which observations were truncated
is_unit_truncated(ps_t)
#> [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE
#> [13] FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE TRUE FALSE FALSE TRUE
#> [25] FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
#> [37] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE
#> [49] FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
#> [61] FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
#> [73] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
#> [85] TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
#> [97] TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE TRUE
#> [109] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
#> [121] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
#> [133] FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE
#> [145] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
#> [157] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE
#> [169] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
#> [181] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
#> [193] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
