R中基于系谱数据计算每个个体直系后代的平均出生年份
实现思路
- 需求核心是统计每个个体的直接子女数量、子女出生年份平均值,无需递归遍历深层的孙代、曾孙代等后裔,和
pedigree包countOff统计全层级后裔的逻辑完全不同,计算量更小。 - 具体执行逻辑:
- 修正原代码的笔误:原构造数据时写的
dataframe是R语法错误,正确函数为data.frame - 把每个孩子记录中的母亲ID、父亲ID统一转为“个体-子女”的配对长表,剔除父母ID缺失的无效记录
- 按父母ID分组,分别计算组内的子女数、子女出生年份的平均值
- 将统计结果按ID匹配回原数据框,无子女的个体后代数记为0,平均出生年份记为NA
- 修正原代码的笔误:原构造数据时写的
可直接运行的代码
# 正确构造原始数据集 ID <- 1:30 MomID <- c(NA, NA, NA, NA, NA, NA, NA, NA, NA, 1,2,1,2,6,8,6,10,11,13,16,19,16,13,16,20,19,16,19,20,23) DadID <- c(NA, NA, NA, NA, NA, NA, NA, NA, NA,3,4,5,5,7,4,9,7,7,14,18,7,15,18,18,17,21,14,18,21,17) Birthyear <- c(1975, 1975, 1976, 1977, 1977, 1977, 1977, 1978, 1978, 1980, 1981, 1982, 1982, 1984, 1984, 1985, 1985, 1985, 1988, 1989, 1990, 1990, 1991, 1992, 1993, 1993, 1993, 1995, 1995, 1996) df <- data.frame(ID, MomID, DadID, Birthyear) # 构造统一的父母-子女配对长表 parent_child_pairs <- rbind( data.frame(parent_id = df$MomID, child_birth_year = df$Birthyear), data.frame(parent_id = df$DadID, child_birth_year = df$Birthyear) ) |> na.omit() # 剔除无有效父母ID的记录 # 分组统计每个个体的直系后代数、后代平均出生年份 offspring_stats <- aggregate( child_birth_year ~ parent_id, data = parent_child_pairs, FUN = function(x) { c( direct_offspring_n = length(x), avg_offspring_birthyear = round(mean(x), 2) ) } ) # 把聚合生成的矩阵列拆分为普通数值列 offspring_stats <- data.frame( parent_id = offspring_stats$parent_id, offspring_stats$child_birth_year ) # 匹配回原数据框 df <- merge( df, offspring_stats, by.x = "ID", by.y = "parent_id", all.x = TRUE ) # 无后代的个体后代数补为0 df$direct_offspring_n[is.na(df$direct_offspring_n)] <- 0
结果核对说明
举个可直接验证的实例:
- 个体ID=1,对应的子女是ID=10(母=1,出生年1980)、ID=12(母=1,出生年1982),统计结果为
direct_offspring_n=2,avg_offspring_birthyear=1981 - 对比
countOff的结果:该函数会把ID=10的子女ID=17也统计为个体1的后裔,总计3个后代,和我们的统计逻辑形成明确区分,完全匹配仅统计直系子女的需求。 - 该方法的计算效率远高于递归遍历家谱的方式,哪怕扩展到上万条个体的数据集也不会出现运行卡顿。
内容的提问来源于stack exchange,提问作者pedigreeanalyst
相关产品推荐
相关产品推荐

