R语言phangorn包批量计算系统发育树节点后代数赋值错误问题
问题原因
phangorn::Descendants()接收节点向量作为输入时,返回值是列表结构:列表长度等于输入节点的总数,每个列表元素对应一个输入节点的所有后代ID向量。
你直接在函数外层嵌套length()时,计算的是最外层返回列表的总长度(也就是你输入的节点个数,测试中输入3个节点因此固定返回3),并没有对每个节点对应的后代向量单独计数,因此所有行都会被赋值为同一个数。
最优实现方案
不需要用逐行apply循环,直接用R内置的lengths()函数(注意函数名带末尾的s)即可,该函数专门用于批量计算列表中每个元素的长度,属于向量化运算,节点量大时运行效率远高于逐行迭代:
# 加载phangorn包(如果未加载) library(phangorn) tests <- data.frame(nodes=c(12551, 12514, 12519)) # 一次性传入所有节点,批量计算每个节点的后代总数 tests$children <- lengths(Descendants(tree, tests$nodes, type = 'all'))
该写法直接利用了Descendants()本身支持向量输入的特性,只需要调用一次函数即可完成所有节点的后代提取,注意事项如下:
- 不要写for循环逐节点单独调用
Descendants(),当节点数达到上千级别时,重复的函数调用会让运行速度明显变慢,向量化写法是最优选择。 - 注意区分
length()和lengths():前者计算单个对象的总长度,后者批量计算列表/向量每个子元素的长度。
备选逐行写法
如果节点量很小,也可以用sapply逐节点计算,结果和上述方案一致:
tests$children <- sapply(tests$nodes, function(node_id) { length(Descendants(tree, node_id, type = 'all')) })
运行结果
执行上述代码后,得到的数据框完全符合预期:
nodes children 1 12551 2 2 12514 8 3 12519 2
内容的提问来源于stack exchange,提问作者aholtz
相关产品推荐
相关产品推荐

