数据分析【免费下载链接】dplyrdplyr: A grammar of data manipulation项目地址https://gitcode.com/gh_mirrors/dp/dplyr点击查看免费下载本篇指南围绕 dplyr 中sample_n()/sample_frac()两个已被slice_sample()取代的采样动词展开完整解析其参数语义、加权抽样的底层实现、分组场景下的逐组行为并逐条还原其 8 个典型错误场景的消息链路。读完后你将能够解释Cant compute indices.这类错误是如何从slice()的错误处理机制中生成的并能将旧代码平滑迁移到slice_sample()。1. 定位两个被标记为 superseded 的采样动词sample_n()与sample_frac()用于从数据框中随机抽取固定行数sample_n()或固定比例sample_frac()的行。二者的 roxygen 文档头部带有lifecycle::badge(superseded)标记见 R/sample.R官方立场是sample_n()andsample_frac()have been superseded in favour ofslice_sample(). While they will not be deprecated in the near future, retirement means that we will only perform critical bug fixes, so we recommend moving to the newer alternative.文档同时给出了取代的具体动机R/sample.R与其用两个函数分别表达“按行数采样”和“按比例采样”不如在一个函数里用两个互斥参数n/prop表达旧函数与slice()的关联不明显第一个参数名tbl与其他单表动词使用的.data不一致size参数使用了 tidy evaluation行为意外且未被文档说明已废弃的.env参数得以彻底移除...的所在位置不理想。NEWS.md也印证了这一状态sample_n()andsample_frac()have been superseded byslice_sample()见 NEWS.md。每次调用这两个函数时源码会主动发出 lifecycle 信号lifecycle::signal_stage(superseded, sample_n())见 R/sample.R 与 R/sample.R。但作为 CRAN 历史代码中大量存在的 API理解它们的行为与错误语义仍然重要——这正是本文主体即快照测试文件 tests/testthat/_snaps/sample.md 所固化的内容。2. 函数签名与参数两个函数的完整签名R/sample.R、R/sample.Rsample_n - function( tbl, size, replace FALSE, weight NULL, .env NULL, ... ) sample_frac - function( tbl, size 1, replace FALSE, weight NULL, .env NULL, ... )参数说明tbldata frame 输入。非 data frame 时落入默认方法并报错见第 4.3 节。size对sample_n()是要抽取的行数对sample_frac()是要抽取的比例默认1。若tbl已分组size对每个分组生效。支持n()等数据掩码函数如sample_n(df, n() - 2)。replace是否放回抽样默认FALSE。为TRUE时允许size超过数据/分组规模。weight抽样权重必须求值为与输入等长的非负数值向量权重会被自动标准化为和为 1。注意它被直接传入 base Rsample.int()的prob参数。.env已废弃DEPRECATED不再有实际效果。传入时会打印提醒sample_n() argument .env is deprecated and no longer has any effect.见 R/sample.R。...被忽略ignored。size与weight在数据框方法里通过enquo()捕获R/sample.R因此可以在表达式中引用数据列与n()而不是普通的求值——这也是文档中提到的“sizeargument uses tidy evaluation”的历史设计。3. 执行链路从 S3 分发到 sample.int()3.1 S3 分发与类型检查sample_n()是泛型UseMethod(sample_n)对 data frame 分派到sample_n.data.frame其他一切输入如空列表落入sample_n.default。默认方法只做一件事——中止并报类型错误R/sample.Rsample_n.default - function(tbl, size, replace FALSE, weight NULL, .env parent.frame(), ...) { msg - glue(tbl must be a data frame, not {obj_type_friendly(tbl)}.) abort(msg) }sample_frac.defaultR/sample.R同理。这正是第 4.3 节快照中tbl must be a data frame, not an empty list.的直接来源。3.2 data.frame 方法slice() local() 数据掩码sample_n.data.frame的核心实现只有几行R/sample.Rsample_n.data.frame - function(tbl, size, replace FALSE, weight NULL, .env NULL, ...) { if (!is_null(.env)) { inform(sample_n() argument .env is deprecated and no longer has any effect.) } size - enquo(size) weight - enquo(weight) dplyr_local_error_call() slice( tbl, local({ size - check_size(!!size, n(), replace replace) sample.int(n(), size, replace replace, prob !!weight) }) ) }要点采样被实现为slice()的特例索引表达式放在local()中由slice()的 data mask 逐组求值。因此采样天然具备分组语义——对 grouped data frame表达式在每个分组内独立执行n()返回当前分组的行数。check_size()先做规模校验无放回且size n()时中止真正的随机性来自 base Rsample.int(n(), size, replace, prob !!weight)权重向量被展开为prob。base R 对概率向量的合法性校验如非零权重数量不足产生的错误会沿调用链上抛成为第 4 节快照里Caused by error in sample.int(): ! too few positive probabilities的源头。sample_frac.data.frameR/sample.R结构完全一致只是规模换算方式不同size - round(n() * check_frac(!!size, replace replace)) sample.int(n(), size, replace replace, prob !!weight)即先把比例通过check_frac()校验再乘以当前组行数并四舍五入取整。3.3 check_size() 与 check_frac() 的校验规则两个辅助函数定义了“无放回时规模上限”的报错逻辑R/sample.Rcheck_size - function(size, n, replace FALSE) { if (size n || replace) { return(invisible(size)) } bullets - c( glue(size must be less than or equal to {n} (size of data).), i set replace TRUE to use sampling with replacement. ) abort(bullets, call NULL) } check_frac - function(size, replace FALSE) { if (size 1 || replace) { return(invisible(size)) } bullets - c( size of sampled fraction must be less or equal to one., i set replace TRUE to use sampling with replacement. ) abort(bullets, call NULL) }注意两条消息中都附带了i提示setreplace TRUEto use sampling with replacement.——这与第 4 节快照输出完全对应。replace TRUE时两个校验直接放行因为放回抽样不受池子大小的限制。4. 快照测试8 个错误场景逐条解析测试入口是 tests/testthat/test-sample.R 中名为sample_*() gives meaningful error messages的expect_snapshot()块其固化输出即 tests/testthat/_snaps/sample.md。以下按测试文件中的注释分组完整还原快照内容。4.1 base R 错误消息分组 权重构造的数据是x rep(1:2, 100)、y rep(c(0, 1), 100)、g rep(1:2, each 100)即两个分组各 100 行每组内y恰好一半为 0、一半为 1df2 - tibble(x rep(1:2, 100), y rep(c(0, 1), 100), g rep(1:2, each 100)) grp - group_by(df2, g) (expect_error(sample_n(grp, nrow(df2) / 2, weight y)))输出error/rlang_error Error in sample_n(): ! Cant compute indices. i In group 1: g 1. Caused by error in sample.int(): ! too few positive probabilities机制size 100对每个分组生效组内 100 行中只有 50 行权重非零。无放回抽样要求“被抽行数 ≤ 非零权重行数”100 50于是 base Rsample.int()报too few positive probabilities。该错误在slice()的索引求值阶段被捕获、重新包装见第 5 节并附加了出错分组的定位信息In group 1:g 1。同类地(expect_error(sample_frac(grp, 1, weight y)))输出error/rlang_error Error in sample_frac(): ! Cant compute indices. i In group 1: g 1. Caused by error in sample.int(): ! too few positive probabilitiessample_frac(grp, 1)在每组内换算为round(100 * 1) 100行同样撞上非零权重不足的问题。4.2 size 超过分组规模无放回(expect_error(sample_n(group_by(mtcars, cyl), 10)))输出error/rlang_error Error in sample_n(): ! Cant compute indices. i In group 2: cyl 6. Caused by error: ! size must be less than or equal to 7 (size of data). i set replace TRUE to use sampling with replacement.mtcars按cyl分组后cyl 6的分组只有 7 行cyl 4有 14 行、cyl 8有 11 行。check_size()在第一个不满足size n的分组这里是第 2 组cyl 6处中止消息中{n}被插值为 7。这条错误由 dplyr 自身抛出Caused by error:下没有具体函数名而非 base R。4.3 非 data frame 输入(expect_error(sample_n(list()))) (expect_error(sample_frac(list())))两者输出完全对称error/rlang_error Error in sample_n(): ! tbl must be a data frame, not an empty list.error/rlang_error Error in sample_frac(): ! tbl must be a data frame, not an empty list.如第 3.1 节所述list()无法分派到.data.frame方法走.default方法直接abort()。注意错误顶部标注的是Error insample_n()——这是dplyr_local_error_call()把报错调用定位到泛型入口的结果而不是定位到内部默认方法。4.4 未分组场景下的三类错误# respects weight df - data.frame(x 1:2, y c(0, 1)) (expect_error(sample_n(df, 2, weight y)))输出error/rlang_error Error in sample_n(): ! Cant compute indices. Caused by error in sample.int(): ! too few positive probabilitiesdf只有 2 行且未分组size 2但y c(0, 1)只有一个非零权重故sample.int()报错。注意未分组场景下没有In group ...一行——分组定位信息只在有活跃分组上下文时出现实现见 R/conditions.R 的cnd_bullet_cur_group_label()无分组时返回空。(expect_error(sample_frac(df, 2)))输出error/rlang_error Error in sample_frac(): ! Cant compute indices. Caused by error: ! size of sampled fraction must be less or equal to one. i set replace TRUE to use sampling with replacement.比例2 1且replace FALSE被check_frac()拦下。(expect_error(sample_frac(group_by(df, y), 2)))输出error/rlang_error Error in sample_frac(): ! Cant compute indices. i In group 1: y 0. Caused by error: ! size of sampled fraction must be less or equal to one. i set replace TRUE to use sampling with replacement.同一check_frac()错误发生在分组上下文中因此多了In group 1:y 0 的定位行。对比上一个未分组用例可以清晰看出分组标签是错误链的可选组成部分。(expect_error(sample_frac(df, 1, weight y)))输出error/rlang_error Error in sample_frac(): ! Cant compute indices. Caused by error in sample.int(): ! too few positive probabilitiessize 1比例合法check_frac通过换算为round(2 * 1) 2行但 2 行里只有 1 个非零权重仍由sample.int()拒绝。4.5 快照揭示的错误消息结构把 8 条输出放在一起可以归纳出sample_*()错误链的三段式结构顶层调用行Error insample_n()/Error in sample_frac() —— 始终指向用户直接调用的泛型入口slice() 包装层! Cant compute indices.索引计算失败的统一描述有分组上下文时追加i In group N:key value.根因层Caused by三类来源——Caused by error insample.int(): ! too few positive probabilitiesbase R 权重校验Caused by error: !sizemust be less than or equal to 7 (size of data).dplyr 的check_size()Caused by error: !sizeof sampled fraction must be less or equal to one.dplyr 的check_frac()以及不走包装、直接abort()的tbl must be a data frame, not an empty list.类型检查发生在进入slice()之前。每一类都附带可操作的修复提示i setreplace TRUE ... 或分组定位这正是该快照测试守护的“meaningful error messages”承诺。5. 错误链的源码出处slice() 的索引求值与分组标签第 4 节中Cant compute indices.与In group ...并非sample_*()自己生成的而是来自其底层的slice()错误处理。调用链为sample_n()→slice()→slice_rows()→slice_eval()/slice_combine()R/slice.R。slice_eval()用withCallingHandlers()包裹索引表达式的求值R/slice.RwithCallingHandlers( mask$eval_all(quo(impl(!!!dots))), error function(cnd) { if (inherits(cnd, vctrs_error_subscript)) { action - process } else { action - compute } if (index is_slice_call(error_call)) { local_error_context(dots, index, mask mask) header - cnd_bullet_header(action) } else { header - glue(Cant {action} indices.) } bullets - c(header, i cnd_bullet_cur_group_label()) abort(bullets, call error_call, parent cnd) } )非下标错误如sample.int()的概率错误归入compute生成头语Cant compute indices.abort(bullets, call error_call, parent cnd)把原始条件设为parent——这就是快照里Caused by error insample.int(): ...这种“父错误链”的由来cnd_bullet_cur_group_label()R/conditions.R从当前分组掩码读出分组标签仅当存在分组时返回In {label}.否则为空解释了 4.4 节中分组/未分组输出的差异。另一处兜底在slice_combine()R/slice.R合并各分组索引时若num_as_location()等定位转换出错同样以Cant compute indices.为头语、mask$set_current_group(group)还原分组上下文后中止。而“分组逐组求值”的行为本身也有测试保障tests/testthat/test-sample.R 验证mtcars | group_by(cyl) | sample_n(2)输出仍是grouped_df、每组恰好 2 行tests/testthat/test-sample.Rissue #3413验证size中可以使用n()如sample_n(gdf, n() - 2L)在 3 组场景下返回总行数减 4tests/testthat/test-sample.Rissue #1438则保证filter()出空分组后再sample_n()不会在无行的组上求值表达式。6. 迁移到 slice_sample()参数映射与行为差异sample_n()/sample_frac()的 roxygen 文档自带官方迁移对照R/sample.Rdf - tibble(x 1:5, w c(0.1, 0.1, 0.1, 2, 2)) # sample_n() - slice_sample() # Was: sample_n(df, 3) sample_n(df, 10, replace TRUE) sample_n(df, 3, weight w) # Now: slice_sample(df, n 3) slice_sample(df, n 10, replace TRUE) slice_sample(df, n 3, weight_by w) # sample_frac() - slice_sample() # Was: sample_frac(df, 0.25) sample_frac(df, 2, replace TRUE) # Now: slice_sample(df, prop 0.25) slice_sample(df, prop 2, replace TRUE)sample_n()/sample_frac()slice_sample()说明第一参数tbl.data命名与其他单表动词一致size行数n互斥参数二选一size比例prop与n互斥weightweight_by同样传入sample.int()的prob自动标准化replacereplace语义一致实现上slice_sample.data.frameR/slice.R复用同一套slice()机制仅规模计算换成get_slice_size(n, prop, allow_outsize replace)采样委托给sample_int()R/slice.Rsample_int - function(n, size, replace FALSE, wt NULL) { if (size 0L) { integer(0) } else { sample.int(n, size, prob wt, replace replace) } }一个关键行为差异值得注意sample_n()在n超过分组规模时报错而slice_sample()会静默截断到组内可用行数与slice_head()等其它 slice 辅助函数保持一致get_slice_size()在无放回时用clamp()把规模压到[0, n]见 R/slice.R文档注释见 R/sample.R 与 R/slice.R。即try(sample_n(df, 10)) # 报错 slice_sample(df, n 10) # 返回全部 5 行不报错因此迁移时如果依赖“超采样会报错”的语义需要自行加校验。另注意slice_sample()的weight_by与sample_*()的weight一样只是抽样概率权重不能用于从样本重建总体统计量文档 Details 部分有说明见 R/slice.R。7. 测试方法论为什么用 expect_snapshot() 固化错误消息上述错误消息的精确文案由 tests/testthat/test-sample.R 的expect_snapshot()守护快照存于 tests/testthat/_snaps/sample.md。这种写法适合错误消息回归测试的原因在于测试体只写“这段代码应当报错”expect_error(...)报错文案本身作为快照输出被逐字固化包括!/i项目符号、分组定位行与Caused by链一旦上游改动例如check_size()措辞调整、slice()包装层重构、base R 升级导致sample.int()消息变化导致输出漂移test_sample.R会失败并提示更新快照从而强制开发者审查错误消息的每次变更测试中用(expect_error(...))加括号的写法是expect_snapshot()惯用技巧——把每个expect_error()包裹成独立表达式使快照为每次报错单独生成一个Code/Output段落而不是混在同一个输出块里。该快照文件与R/sample.R中的check_size()/check_frac()报错文案、R/slice.R的错误包装逻辑、R/conditions.R的分组标签函数共同构成了一条完整的“实现—文档—测试”证据链修改任何一环另一环都会以测试失败的形式暴露不一致。8. 实践要点小结新代码优先用slice_sample()参数为n/prop互斥、weight_by、replace对超组规模请求采取截断而非报错支持负值n/prop表示从组大小中减去。维护旧代码时sample_n()/sample_frac()仍可用且仅接受关键 bug 修复出现supersededlifecycle 信号属正常现象可按第 6 节映射表批量改写。调试too few positive probabilities检查权重向量在每个分组内非零值的数量是否足以支撑无放回抽样规模要么提高非零权重覆盖要么设置replace TRUE。调试size must be less than or equal to Nsize在分组数据中按组生效报错的N是出错组的行数i In group ...行可直接定位是哪个键值组合触发了限制。理解错误链顶层Error insample_n() →Cant compute indices.slice 包装层可含分组定位→Caused by根因三层信息分别由dplyr_local_error_call()、slice_eval()/slice_combine()的withCallingHandlers()与parent cnd链式机制生成源码位置见 R/slice.R 与 R/slice.R。关键文件索引文件内容R/sample.Rsample_n()/sample_frac()泛型、默认方法、data frame 方法、check_size()/check_frac()R/slice.Rslice()错误处理slice_eval/slice_combine、slice_sample()及其实现R/conditions.R分组错误标签cnd_bullet_cur_group_label()、cnd_bullet_header()tests/testthat/test-sample.R采样行为与错误消息快照测试tests/testthat/_snaps/sample.md本文剖析的 8 条错误消息快照NEWS.mdslice_sample()取代sample_n()/sample_frac()的变更记录赞分享数据分析【免费下载链接】dplyrdplyr: A grammar of data manipulation项目地址https://gitcode.com/gh_mirrors/dp/dplyr点击查看免费下载相关推荐数据采样终极指南PythonDataScienceHandbook中的随机抽样与分层抽样技巧数据采样终极指南PythonDataScienceHandbook中的随机抽样与分层抽样技巧 数据采样是数据分析和机器学习中的关键步骤它直接影响模型的准确性教程数据科学数据分析数据可视化机器学习DeepSeek-V2模型下载指南HuggingFace仓库使用教程DeepSeek V2模型下载指南HuggingFace仓库使用教程 你还在为大模型下载流程复杂而烦恼本文将带你快速掌握DeepSeek V2模型的下载与本文档教程数据分析掌握ClickHouse数据采样10倍速提升大数据分析效率的终极指南掌握ClickHouse数据采样10倍速提升大数据分析效率的终极指南 ClickHouse® 作为免费的大数据分析型数据库管理系统其数据采样功能是处理海量数数据库OLAP列式数据库大数据实时分析数据分析上一篇Unison Transcript 信息字符串info string解析机制与错误诊断从 info-string-parse-error 出发的源码级解读下一篇下载的视频打不开res-downloader 视频解密操作与排错手册创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考