R语言如何在tibble中创建不依赖前置列的独立新列表列
需求说明
需要对经纬度、Case值交叉后得到的嵌套tibble,为每一组经纬度对独立生成3个0-50区间内无放回的随机整数,要求:
- 每组经纬度对应的3个随机数本身无放回
- 不同经纬度对的随机数结果相互独立,不能所有行复用同一份抽样结果
- 不能将抽样逻辑写入
crossing()阶段,避免和Case值做不必要的交叉展开
最初写法的核心问题是:直接在mutate()中调用sample()时,R只会全局执行1次抽样,再将得到的长度为3的向量通过循环规则填充到所有行,最终导致所有经纬度对的随机数完全一致。
可行实现方案
方案1:使用rowwise逐行计算
通过rowwise()将数据框转换为按行分组的结构,后续mutate()中的表达式会逐行独立执行,每次调用sample()都会生成新的独立抽样结果:
library(tidyverse) LAT = c(0, 10, 20, 30, 40) LON = c(-180, -120, -60, 0, 60, 120) Case = c("All", "These", "Are", "Arbitrary") df <- crossing(LAT, LON, Case) %>% nest(TotalCases = Case) %>% rowwise() %>% # 逐行执行抽样,用list包裹存入列表列 mutate(ViewingAngles = list(sample(0:50, 3, replace = FALSE))) %>% ungroup() # 操作完成后取消行分组,避免影响后续数据处理
方案2:使用map函数迭代抽样
map系列函数完全可用,不需要找特殊的传入参数,直接以行序号作为迭代源即可:
df <- crossing(LAT, LON, Case) %>% nest(TotalCases = Case) %>% # seq_len(n())生成1到总行数的序列,每迭代一次触发一次独立抽样 mutate(ViewingAngles = map(seq_len(n()), ~ sample(0:50, 3, replace = FALSE)))
避坑提示
不要直接使用
mutate(ViewingAngles = list(sample(0:50,3,replace=F)))写法,这种写法下sample()仅会全局执行1次,最终所有行都会复用同一份抽样结果,这是R的向量自动循环规则导致的,并非sample()函数本身的问题。
内容的提问来源于stack exchange,提问作者Jared Brewer
相关产品推荐
相关产品推荐

