Hello,

Though I agree with what Ravi and Gabriel have said, I believe the OP 
might have a point.

Inline.



-------- Mensagem reencaminhada --------
Assunto:        [Rd] Bug report: mean(..., trim) silently applies integer 
truncation when k = trim * n is non-integer
Data:   Thu, 30 Jul 2026 14:09:05 -0500
De:     JUAN CARLOS GAVIRIA CHAVERRA via R-devel <[email protected]>
Responder-Para:         JUAN CARLOS GAVIRIA CHAVERRA 
<[email protected]>
Para:   [email protected]



Subject: Bug report: mean(..., trim) silently applies integer truncation
when k = trim * n is non-integer

Dear R Core Team,

I am writing to report a structural limitation in the mean(..., trim)
function in base R that has gone undetected for over three decades and
affects the overwhelming majority of practical uses of trimmed mean
computation.

--- NARRATIVE JUSTIFICATION ---

For more than three decades, researchers in econometrics, finance, public
health, environmental sciences and many other fields have trusted that
mean(..., trim = 0.05) applies exactly 5% trimming to their data. This
implicit trust is precisely what makes the integer truncation problem so
consequential: it affects any combination of n and trim that produces a
non-integer k = trim * n, which represents the overwhelming majority of
practical uses.

The problem has two manifestations. When k < 1 (Type A), R reduces k to
zero and returns the arithmetic mean, completely ignoring the requested
trimming without any warning. When k > 1 but non-integer (Type B), R trims
fewer observations than requested, with losses reaching 33% of the nominal
value, also without any warning.

The scope extends beyond direct users: packages such as WRS2 (hundreds of
thousands of downloads) use mean(x, tr) internally, propagating the
distortion silently to confidence intervals and hypothesis tests.

We are not requesting a change in the existing algorithm. We are requesting
transparency: a warning when the effective trimming differs from the
requested trimming, preserving complete backward compatibility.


There are base functions whose documentation mentions coercion to 
integer by truncation.
 From ?dim section Arguments

 > value
 > for the default method, either NULL or a numeric vector, which is 
coerced to integer (by truncation).


And from ?mean, section Value

 > If trim is non-zero, a symmetrically trimmed mean is computed with a 
fraction of trim observations deleted from each end before the mean is 
computed.


A warning is too much, it would seem there was something wrong or 
worrying going on, when there isn't. But the documentation could include 
that the trimmed fraction is coerced to integer and how it is done.
Maybe

 > If trim is non-zero, a symmetrically trimmed mean is computed with a 
fraction of trim observations deleted from each end before the mean is 
computed. The fraction is coerced to integer (by truncation).


Hope this helps,

Rui Barradas


The existence of sgmean as a separate package (CRAN v0.1.1) should not be
interpreted as a permanent solution. sgmean and mean(..., trim) produce
identical results whenever k = trim * n is an exact integer. The only
difference is that sgmean also handles non-integer k correctly. Directing
users to install a separate package to obtain the result that base R's own
mean() function should produce is not a solution — it is a transfer of
responsibility. The R Core Team has the unique opportunity to resolve this
at the root, ensuring that every R user benefits from correct trimmed mean
computation.

--- REPRODUCIBLE EXAMPLE ---

x <- c(850, 920, 980, 1050, 1120, 1180, 1250,
1320, 1400, 1480, 1550, 1700, 1850, 2100, 8500)

# TYPE A: k < 1
cat('k requested:', 0.05 * 15, '| k applied:', floor(0.05 * 15), '\n')
# k requested: 0.75 | k applied: 0
mean(x) # [1] 1816.667
mean(x, trim = 0.05) # [1] 1816.667 -- SAME: no trimming applied
# Expected (Statgraphics): 1499.074

# TYPE B: k > 1, non-integer
cat('k requested:', 0.10 * 15, '| k applied:', floor(0.10 * 15), '| Loss:
33.3%\n')
mean(x, trim = 0.10) # [1] 1376.923
# Expected (Statgraphics): 1365.833

--- CROSS-PLATFORM EVIDENCE ---

This bug exists identically in Python's scipy.stats.trim_mean, confirming
that integer truncation in trimmed mean computation is a systematic
limitation shared across the two most widely used scientific computing
environments in the world.

Software | Type A (k=0.75) | Type B (k=1.50)
R base mean(...,trim) | 1816.667 (wrong)| 1376.923 (wrong)
Python trim_mean | 1816.667 (wrong)| 1376.923 (wrong)
Statgraphics | 1499.074 (correct) | 1365.833 (correct)
sgmean CRAN v0.1.1 | 1499.074 (correct) | 1365.833 (correct)

--- PROPOSED SOLUTION ---

Minimum fix: add a warning in mean.default() when k = trim * n is
non-integer:

if (k != floor(k)) {
if (floor(k) == 0L) {
warning(paste0('trim * length(x) = ', k, ' < 1. ',
'No trimming applied (effective trim = 0%). ',
'Consider sgmean::sgmean() for proportional trimming.'))
} else {
warning(paste0('trim * length(x) = ', k, ' is not an integer. ',
'Effective trimming: ', round(floor(k)/length(x)*100,1), '% ',
'(requested: ', trim*100, '%, loss: ',
round((k-floor(k))/k*100,1), '%).'))
}
}

--- AVAILABLE SOLUTION ---

A corrected implementation is available on CRAN:
install.packages('sgmean')
DOI: https://doi.org/10.32614/CRAN.package.sgmean
GitHub: https://github.com/jcarlosgaviria/sgmean

--- R VERSION ---

R version 4.5.3 (2026-03-11 ucrt)
Platform: x86_64-w64-mingw32/x64

Best regards,

Juan C. Gaviria-Chaverra
ALIADO-Analytics and Research for Decision Making
Department of Industrial Engineering, Universidad de Antioquia
Medellin, Colombia
[email protected]
ORCID: 0009-0008-9403-416X
GitHub: https://github.com/jcarlosgaviria

-- 


"La información aquí contenida es para uso exclusivo de la persona o entidad de 
destino. Está estrictamente prohibida su utilización, copia, descarga, 
distribución, modificación y/o reproducción total o parcial, sin el permiso 
expreso de Universidad de Antioquia, pues su contenido puede ser de carácter 
confidencial y/o contener material privilegiado. Si usted recibió esta 
información por error, por favor contacte en forma inmediata a quien la envió y 
borre este material de su computador. Universidad de Antioquia no es 
responsable por la información contenida en esta comunicación, el directo 
responsable es quien la firma o el autor de la misma."

______________________________________________
[email protected] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel

        [[alternative HTML version deleted]]

______________________________________________
[email protected] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel

Reply via email to