将具有不同元素数量的分隔字符串的列拆分为行

问题描述 投票:0回答:1

我正在使用一种名为 OrthoFinder 的生物信息学工具,它根据序列相似性将来自不同基因组/物种的基因放入所谓的 Orthogroups 中。

其中一个输出文件会告诉您哪些基因属于哪个 Orthogroup。此处,第一列具有 Orthogroup ID。接下来的三列代表三个基因组。在基因组列中,每行包含适合每个 Orthogroup 的基因 ID。如果每个基因组的 Orthogroup 中有多个基因,则该算法会将基因放入以逗号分隔的列表中。

正交群 基因组1 基因组2 基因组3
OG0000001 基因1,基因2,基因3 基因1
OG0000002 基因5,基因6 基因4
OG0000003 基因7 基因7,基因8

我想将包含基因 ID 的列中的数据分开,以便每个基因都有自己的行。我找到了有关如何使用

strsplit()
tidyr::seperate_longer_delim()
进行操作的信息。

我遇到的问题是每列都有不同数量的基因。在上表中,您可以在第二行 OG0000002 中看到,基因组 1 为 NA。因此,如果我使用基于基因组 1 的

strplit()
,我会丢失 OG0000002,以及基因组 2 和基因组 3 中的基因 ID。

当我尝试时:

separate_longer_delim(c(genome1, genome2, genome3), delim = ",")

我收到这样的错误:

separate_longer_delim()
中的错误: !在第 2 行中,无法将大小 2 的输入回收到大小 5。

以下是 Hadley Wickham 对此错误的看法

我需要一种方法来分隔每列中的元素,但如果每行中有不同数量的基因,则不会删除行。换句话说,每个基因在每个基因组中都应该有自己的行。

tidyr
1个回答
2
投票

根据您的示例数据,以下解决方案将有效,并且如果所有列中的数据一致,应该扩展到您的完整数据集。

使用

tidyverse

library(dplyr)
library(tidyr)

# Your sample data
df <- data.frame(Orthogroup = c("OG0000001", "OG0000002", "OG0000003"),
                 genome1 = c("gene1, gene2, gene3", NA, "gene1"),
                 genome2 = c(NA, "gene5, gene6", "gene4"),
                 genome3 = c("gene7", "gene7, gene8", NA))

df1 <- df |>
  pivot_longer(cols = starts_with("genome"), 
               names_to = "genome", 
               values_to = "genes") |>
  separate_longer_delim(genes, delim = ", ") |>
  mutate(row_id = row_number(), .by = c(Orthogroup, genome)) |>
  complete(Orthogroup, genome, row_id) |>
  pivot_wider(names_from = genome, 
              values_from = genes) |>
  select(-row_id)

df1
# # A tibble: 9 × 4
#   Orthogroup genome1 genome2 genome3
#   <chr>      <chr>   <chr>   <chr>  
# 1 OG0000001  gene1   NA      gene7  
# 2 OG0000001  gene2   NA      NA     
# 3 OG0000001  gene3   NA      NA     
# 4 OG0000002  NA      gene5   gene7  
# 5 OG0000002  NA      gene6   gene8  
# 6 OG0000002  NA      NA      NA     
# 7 OG0000003  gene1   gene4   NA     
# 8 OG0000003  NA      NA      NA     
# 9 OG0000003  NA      NA      NA

或者,您可以使用

cSplit()
包中的
splitstackshape
函数:

library(splitstackshape)

df1 <- data.frame(cSplit(df,
                         names(df[2:ncol(df)]), # All columns except the first one 
                         ",", # Delimiter
                         "long", # Rowise/long format
                         type.convert = "as.character")) # Value type
© www.soinside.com 2019 - 2024. All rights reserved.