我有一个包含数千行和以下列的数据集:ID、parentID、rank 和 ScientificName。
我希望创建一个新列,用于告知给定物种所属的family(rank中的级别)。如果有人可以提供帮助,将不胜感激。
示例数据:
ID = c('f1','f2','g1','g2','g3','g4','s1','s2','s3','s4','s5','s6') # all unique
parentID = c(NA,NA,'f1','f1','f2','f2','g1','g1','g2','g3','g3','g4')
rank = c('family','family','genus','genus','genus','genus','species','species','species','species','species','species')
scientificName = c('FamA','FamB','GenA','GenB','GenC','GenD','SpA','SpB','SpC','SpD','SpE','SpF')
dat = data.frame( ID, parentID, rank, scientificName)
我想要的输出(在本例中)将是一个额外的列,通知家庭如下: 家庭 = c('famA','famB','famA','famA','famB','famB','famA','famA','famA','famB','famB','famB ')
我考虑过创建家族及其 ID 的向量,然后通过家族名称更改 ParentID 列中的代码,然后尝试对属进行类似的操作,最终将家族信息与每个物种“链接”起来,但它有点混乱最后(也就是说,它没有成功)。我认为我需要的可以通过“dplyr”包来完成,但我被困住了......再次,我将不胜感激任何帮助。
这是一个很好的递归问题。这是一个矢量化的基本 R 解决方案。
find_family <- function(ID, parentID, scientificName) {
find_family_id <- function(ID, parentID) {
ID_new <- ifelse(!is.na(parentID), parentID, ID)
parentID_new <- parentID[match(ID_new, ID)]
if (all(is.na(parentID_new))) return(ID_new)
find_family_id(ID_new, parentID_new)
}
family_ids <- find_family_id(ID, parentID)
scientificName[match(family_ids, ID)]
}
dat$family <- with(dat, find_family(ID, parentID, scientificName))
dat
# ID parentID rank scientificName family
# 1 f1 <NA> family FamA FamA
# 2 f2 <NA> family FamB FamB
# 3 g1 f1 genus GenA FamA
# 4 g2 f1 genus GenB FamA
# 5 g3 f2 genus GenC FamB
# 6 g4 f2 genus GenD FamB
# 7 s1 g1 species SpA FamA
# 8 s2 g1 species SpB FamA
# 9 s3 g2 species SpC FamA
# 10 s4 g3 species SpD FamB
# 11 s5 g3 species SpE FamB
# 12 s6 g4 species SpF FamB
您可以编写一个小型递归函数来查找 ID,直到达到家庭排名,然后使用一些迭代来应用此函数(此处
purrr::map_chr
以确保字符向量):
library(dplyr)
library(purrr)
get_family <- function(x) {
i <- match(x, ID)
with(dat, if (rank[i]=="family") scientificName[i] else get_family(parentID[i]))
}
dat |>
mutate(family = map_chr(ID, get_family))
输出
ID parentID rank scientificName family
1 f1 <NA> family FamA FamA
2 f2 <NA> family FamB FamB
3 g1 f1 genus GenA FamA
4 g2 f1 genus GenB FamA
5 g3 f2 genus GenC FamB
6 g4 f2 genus GenD FamB
7 s1 g1 species SpA FamA
8 s2 g1 species SpB FamA
9 s3 g2 species SpC FamA
10 s4 g3 species SpD FamB
11 s5 g3 species SpE FamB
12 s6 g4 species SpF FamB