The trouble with 'ntile()'

原始链接: https://blog.djnavarro.net/posts/2026-09-20_the-trouble-with-ntile/

这场 Hacker News 讨论聚焦于对 `ntile()` 函数的批评。最初的抱怨称,由于该函数在处理平局(ties)时的逻辑以及在 SQL 中对内存的高消耗,它是一个“被诅咒”的函数。批评者认为,`ntile()` 优先保证分组大小相等而非保持平局一致性的做法有违直觉。 然而,其他参与者则反驳称,大多数不满源于用户未阅读文档。他们澄清道,`ntile()` 的设计初衷就是忽略平局以确保均匀分布。此外,他们指出该函数的行为是可预测的,用户完全可以通过在数据集中添加额外的变量或列来轻松处理平局问题。目前的共识倾向于认为,该函数带来的“麻烦”很大程度上是开发者操作不当的结果,而非工具本身的固有缺陷。
相关文章

原文

You keep using that function. I do not think it does what you think it does

As longtime readers of this blog will no doubt be aware, I am a tidyverse girl. As deeply as I adore the R programming language, there are some wild things that are baked into the behaviour of base R, and a lot of what tidyverse does so very, very well is smooth over those rough edges. Whether it is data visualisation with ggplot2, data wrangling with dplyr, or navigating the hell that is string manipulation with stringr rather than grappling with the stunningly inconsistent base R regex tools, it has been a blessing. I don’t usually bother to write posts pointing out the obvious, though, so I’ve been more likely to write about a few of the less celebrated packages like fs and cli that sit underneath tidyverse and make everyone’s life a little less painful.

In short, I am a fan.

And so it is with a certain level of trepidation and regret that I find myself writing a post about something that a tidyverse package doesn’t do well. After all, who am I to criticise? I have written some truly terrible code over the years and had some very unwise choices end up in packages that people actually use. But of course that’s the point… even the very best tools have problems, even the best programmers make mistakes, etc. It’s foolish to pretend otherwise.

With that in mind, this is a post about dplyr::ntile(). It is a warning that you should not use it for any purpose where statistical accuracy is important. If you try to guess what it does based on the function name – and are one of the fortunate souls never to have worked with SQL – you will get burned when you discover what it actually does. It is emphatically not a tool for binning data into quantile-based groups, and it will absolutely misbehave when you use it for data analysis. Please be careful.

NTILE function in SQL. Just like its SQL counterpart, ntile() forces identical values to be assigned into different groups if that would produce a more “even” split of the data. In SQL though, this behaviour leads to even stranger outcomes: because databases don’t really have any inherent concept of row order the tie-breaking behaviour in NTILE is simply declared to be “nondeterministic”. All you’re really told about its behaviour is this:

If the number of rows in a partition isn’t divisible by integer_expression, this causes groups of two sizes that differ by one member. Larger groups come before smaller groups in the order specified by the OVER clause. For example, if the total number of rows is 53 and the number of groups is five, the first three groups have 11 rows and the two remaining groups have 10 rows each. If on the other hand the total number of rows is divisible by the number of groups, the rows are evenly distributed among the groups. For example, if the total number of rows is 50, and there are five groups, each bucket contains 10 rows.

NTILE prescribes the size of the groups, but not their membership or the rule that maps values to categories. Despite the painfully inappropriate similarity of name, NTILE is not in any meaningful sense a tool for quantile binning. Indeed, if the ORDER BY clause in an NTILE expression produces ties at the breaks… well, who even knows what it will do? It’s “nondeterministic”, which most certainly is not the same thing as “random” in this context. Breaking ties at random would be a lot less unhinged, since the statistical properties of random allocation are well understood. But breaking ties using a rule that is unknown but probably systematically related to variables that matter for your analysis? That is horrifically bad. There are perhaps some contexts in which the “quick and dirty carve up” that NTILE and ntile() provide is useful, but serious data analysis is not one of them.

And without question, neither one is suitable for regulatory work in the pharmaceuticals industry.

Appendix

Reuse

Citation

BibTeX citation:

@online{navarro2026,
  author = {Navarro, Danielle},
  title = {The Trouble with “Ntile()”},
  date = {2026-09-20},
  url = {https://blog.djnavarro.net/posts/2026-09-20_the-trouble-with-ntile/},
  langid = {en}
}

For attribution, please cite this work as:

Navarro, Danielle. 2026. “The Trouble with ‘Ntile()’.” September 20. https://blog.djnavarro.net/posts/2026-09-20_the-trouble-with-ntile/.
联系我们 contact @ memedata.com