【问题标题】:How to fill gaps in series of strings?如何填补一系列字符串中的空白?
【发布时间】:2019-02-26 20:34:01
【问题描述】:

我面临一个问题,即一个包检索长度不同的分类信息(关于物种)。因此,该函数将输出存储在一个列表中,该列表的元素包含 2 行和各种列数的表格(1 行用于分类等级,1 行用于信息本身):

taxo.spA <- data.frame(name=c("Animalia", "Arthropoda", "Chelicerata", 
                                 "Arachnida", "Acari"), 
                       rank=c("Kingdom", "Phylum", "Subphylum", "Class", 
                              "Subclass"))

taxo.spB <- data.frame(name=c("Animalia", "Chordata", "Vertebrata", 
                               "Gnathostomata", "Actinopterygii", "Perciformes", 
                               "Trachinoidei", "Ammodytidae", "Ammodytes", 
                               "Ammodytes tobianus"),
                       rank=c("Kingdom", "Phylum", "Subphylum", "Superclass", 
                              "Class", "Order", "Suborder", "Family", "Genus", 
                              "Species"))

我想最终得到一个以列为列、以行为名称的表。 主要问题是分类法通常在等级方面有所不同,有些分类群没有解决到物种级别(比如这个 Acari),或者如果解决了,等级可能会不同(没有超类)所以你不能 cbind 或rbind 那些表(=不同的列数或行数)。

但是,分类等级遵循等级制度,因此我一直在尝试重建这一系列等级(从王国到物种或亚种)。 我想知道最好的方法是什么?是否有一个包/函数可以在两个字符串之间找到匹配项以及插入缺失内容的位置?


例如:

ranks1 <- c("Kingdom", "Phylum", "Subphylum", "Class")
ranks2 <- c("Kingdom", "Phylum", "Subphylum", "Superclass", "Class", "Order")

该函数将确定 Kingdom:Subphylum 和 Class 是共同的。而且 Subphylum 和 Class 围绕着 Superclass,因此 Superclass 可以插入 Subphylum 和 Class 之间。最后,Order 丢失了,应该在 Class 之后的右侧:

“王国”、“门”、“亚门”、“超类”、“类”、“秩序”

最终,我正在编写的函数将构建一个包含 n 列(=最长的分类)和 S 行(分类单元的数量)的 data.frame,并用我在每个分类单元上拥有的分类信息以正确的方式填充它列,其余为 NA。

desired.output <- data.frame(rbind(c("Animalia", "Arthropoda", "Chelicerata", 
                                     NA, "Arachnida", "Acari", NA), 
                                   c("Animalia", "Chordata", "Vertebrata", 
                                     "Gnathostomata", "Actinopterygii", NA, 
                                     "Perciformes")))

names(desired.output) <- c("Kingdom", "Phylum", "Subphylum", "Superclass", 
                           "Class", "Subclass", "Order")

我试图从我拥有的最完整的信息之一开始,并填补与其他分类群相比的空白。我玩过 setdiff(), intersect(), %in%;并试图找到共同点,什么只属于两个字符串之一并重建它,但我不确定这是最好的方法吗?

有什么想法吗?有什么建议吗?

注意我会将数据集保留为数据框(尽管现在更多的是矩阵),因为稍后我会将其与其他数据集合并。


编辑/回答如下

首先,感谢您的帮助。我从答案中启发了自己,并设法让它发挥作用。

主要问题是列表中包含的表 (1) 的行数不同,(2) 行可能包含不同的信息(分类中可能会跳过某些等级),因此很难合并所有内容在一张桌子内。

但是,分类具有这种树状层次结构,我可以使用它来查找这些等级如何分支在一起。 我是如何解决这个问题的:

我使用具有最多解析信息的有机体作为我的参考(= 最高等级数),然后获取每个等级列表(等级向量)并找到与这个最解析向量的差异。 然后我通过查看层次结构中的高于和低于它们的等级以及它们在我的参考中匹配的位置来搜索这些缺失等级的位置。

四种情况是可能的(注意最高等级在左边,最低在右边):

  • 不匹配:我无法将该排名放在分类中(目前)
  • 2 个匹配项:我可以将两个匹配项之间缺少的信息放在我的 参考
  • 左侧有 1 个匹配项:我可以在匹配项之后放置它
  • 右侧有 1 个匹配项:我可以将其放在匹配项之前

我遍历缺失的排名并按顺序增加排名,直到数据集中所有可能的排名都包含在向量中:我使用函数 append() 在由常见排名位置定义的特定位置之后依次添加缺失的排名在参考和其他分类法之间。

最后,我将此向量用作最终表格的列名,并用分类信息填充表格(见下文)。 也许不是最好的,但应该在各个分类法中保持一致。

非常感谢! (P.S. 当它终于做它应该做的事时感觉很好)

【问题讨论】:

  • 为了更正我的帖子,我得到的列表实际上包含 tibbles 而不是 data.frames(我对这类表不太熟悉)。

标签: r


【解决方案1】:

您可以先定义一个函数,将您的taxo*s 转换为不完整的结束格式。

myTransform <- function(x) {
  tr <- t(x[2:1])
  colnames(tr) <- make.names(tr[1, ], unique=TRUE)  # `make.names()` to get unique column names
  return(as.data.frame(t(tr[-1, ])))
}

然后将所有taxo*s 放入列表l。例如。 mget() 如果它们被加载到工作区中。

l <- lapply(mget(ls(pattern="taxo")), myTransform)

(这与l &lt;- lapply(list(taxo.spA, taxo.spB), myTransform) 所做的基本相同,但假设您有一大堆taxo*s。)

id 列添加到列表中的数据框是有意义的。

l <- l <- lapply(1:length(l), function(x) cbind(id=names(l)[x], l[[x]]))

现在运行 merge() 包装成 Reduce() 像这样:

out <- Reduce(function(...) merge(..., all=TRUE), l)

给予

> out
        id  Kingdom     Phylum   Subphylum          Class Subclass
1 taxo.spA Animalia Arthropoda Chelicerata      Arachnida    Acari
2 taxo.spB Animalia   Chordata  Vertebrata Actinopterygii     <NA>
3 taxo.spC Animalia Arthropoda Chelicerata      Arachnida    Acari
     Superclass       Order     Suborder      Family     Genus
1          <NA>        <NA>         <NA>        <NA>      <NA>
2 Gnathostomata Perciformes Trachinoidei Ammodytidae Ammodytes
3          <NA>        <NA>         <NA>        <NA>      <NA>
             Species Subclass.1
1               <NA>       <NA>
2 Ammodytes tobianus       <NA>
3               <NA>  Something
1               <NA>       <NA>
2 Ammodytes tobianus       <NA>
3               <NA>  Something

附加数据(模拟重复列)

taxo.spC <- structure(list(name = structure(c(2L, 4L, 5L, 3L, 1L, 6L), .Label = c("Acari", 
"Animalia", "Arachnida", "Arthropoda", "Chelicerata", "Something"
), class = "factor"), rank = structure(c(2L, 3L, 5L, 1L, 4L, 
4L), .Label = c("Class", "Kingdom", "Phylum", "Subclass", "Subphylum"
), class = "factor")), row.names = c(NA, -6L), class = "data.frame")

【讨论】:

  • 您好,感谢您的回答。我收到一个错误,但我不知道为什么:“fix.by(by.y, y) 中的错误:'by' 必须指定一个唯一有效的列”我认为这是因为对于鱼,数据集包含超类 Gnathostomata和超类双鱼座(所以重复的列名)。我删除了它,但仍然是这个错误。
  • "fix.by(by.y, y) 中的错误:'by' 必须指定唯一有效的列"
  • 也许您可以扩展您的示例数据,以便我可以重现该错误。重复的列可能是导致错误的原因。
  • 有没有办法在这里共享 Rdata?会更容易,因为我不知道是什么表导致了这个错误。
  • 我将编辑我的答案。我设法让函数与 append 一起工作。
【解决方案2】:

这样的事情怎么样:

library(dplyr)
# add a column with the name of the taxonomy
taxo.spA$tax <- "taxo.spA"
taxo.spB$tax <- "taxo.spB"

# bind the rows together (an alternative to do.call(rbind, .) would be data.table::rbindlist())
# this would also work if you have more than two taxonomies 
result <- list(taxo.spA, taxo.spB) %>% 
  do.call(rbind, .) %>% 
  reshape2::dcast(tax ~ rank, value.var = "name") 

# choose the columns and the order you want
orderd_classes <- c("Kingdom", "Phylum", "Subphylum", "Superclass", "Class", "Subclass", "Order")
result[orderd_classes]

结果是:

# Kingdom     Phylum   Subphylum    Superclass          Class Subclass       Order
# Animalia Arthropoda Chelicerata          <NA>      Arachnida    Acari        <NA>
# Animalia   Chordata  Vertebrata Gnathostomata Actinopterygii     <NA> Perciformes

【讨论】:

  • 嗨,我不确定这里的意图。我得到一个列联表,其中一列中有分类群,其他列是等级。我将如何从那里去?我拥有的另一个更简单的解决方案是将分类等级顺序存储在一个向量中(我认为最多有 25-30 个等级)并使用它们来选择正确的列来填充表格。但我认为如果等级名称发生变化或者我使用不同的分类法,可能会有不同的解决方案。
  • 我觉得我错过了这里的问题,我不是你研究领域的专家,但我知道 R,所以你能帮我理解问题到底是什么吗?这种方法到底有什么不能做的?
  • 我想最终得到一个包含字符(分类单元名称)的表。每列将对应于一个分类等级(〜层次结构中的一个级别),每一行将包含特定生物或生物群的每个等级的信息。我从这个数据库中检索数据:marinespecies.org/aphia.php?p=taxdetails&id=2036 在括号中,您有排名(例如 Phylum)并与该特定 Phylum 的名称相关联(例如 Annelida)。我找到了我将在上面发布的解决方案。
猜你喜欢
  • 2020-07-06
  • 2015-08-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-25
  • 2019-02-05
  • 2012-10-19
相关资源
最近更新 更多