如果前一行包含以特定符号开头的字符串,则合并行

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

我有一个如下所示的数据框:

df <- data.frame(V1=c(">A1", "aaaa", "bbb", "cccc",
            ">B2", "dddd", "eeeee","ff",
            ">C3", "ggggggg", "hhhhh", "iiiii", "jjjjj"))

这就是我想要得到的:

df1 <- data.frame(V1=c(">A1", "aaaabbbcccc",
            ">B2", "ddddeeeeeff",
            ">C3", "ggggggghhhhhiiiiijjjjj"))

如您所见,我想合并包含以“>”符号开头的字符串的两行之间的每一行。 坦白说,我不知道从哪里开始。 请指教。

r
3个回答
3
投票

为此我们可以使用

cumsum(grepl(.))

data.frame(
  V1 = unlist(
    by(df$V1, cumsum(grepl("^>", df$V1)),
       function(z) c(z[1], paste(z[-1], collapse = "")))
  )
)
#                        V1
# 11                    >A1
# 12            aaaabbbcccc
# 21                    >B2
# 22            ddddeeeeeff
# 31                    >C3
# 32 ggggggghhhhhiiiiijjjjj

简要说明:

  • grepl(.)
    为每个包含
    TRUE
    的单元格返回
    >
    ;然后

  • cumsum
    为该行和所有行分配相同的编号,直到下一次出现:

    grepl(">", df$V1)
    #  [1]  TRUE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE FALSE
    cumsum(grepl(">", df$V1))
    #  [1] 1 1 1 1 2 2 2 2 3 3 3 3 3
    
  • by(.)
    对每个组都做了一些事情;在这种情况下,它返回一个长度为 2 的向量,首先是
    >
    字符串,然后连接所有其他字符串。

其结构为您的

df1

df1
#                       V1
# 1                    >A1
# 2            aaaabbbcccc
# 3                    >B2
# 4            ddddeeeeeff
# 5                    >C3
# 6 ggggggghhhhhiiiiijjjjj

1
投票

假设这本来是一个fasta文件,那么使用专用包:

write(as.matrix(df), file = "tmp.fasta")

library("Biostrings")

readDNAStringSet("tmp.fasta")

# DNAStringSet object of length 3:
#     width seq                                                                 names               
# [1]    11 AAAABBBCCCC                                                         A1
# [2]     4 DDDD                                                                B2
# [3]    12 GGGGGGGHHHHH                                                        C3
# Warning message:
# In .Call2("fasta_index", filexp_list, nrec, skip, seek.first.rec,  :
#   reading FASTA file tmp.fasta: ignored 17 invalid one-letter sequence codes

相关文章:将 FASTA 读入数据帧并提取 FASTA 文件的子序列


1
投票

您可以使用字符串操作函数在每个组的开头和结尾插入分隔符,然后将所有内容折叠成一个字符串(包括插入的分隔符),然后使用分隔符将组分开。

使用基础-R

df1 <- data.frame(
    V1 = tail(strsplit(paste(sub("^(>.*)", "\n\\1\n", df$V1), collapse = ""), "\n")[[1]], -1),
    stringsAsFactors = FALSE
)

说明:

sub()
与“>”匹配值,并在前后插入换行符以分隔每个行组。
paste()
将所有内容组合成一根字符串。
strsplit()
将字符串分成换行符之间的单独值,并且
tail()
删除开头的无关空组。

相同的步骤,但使用

dplyr

拼写得更清楚
library(dplyr, warn.conflicts = FALSE)

df |>
    # Insert separators before and after groups
    mutate(V1 = ifelse(grepl("^>", V1), paste0("\n", V1, "\n"), V1)) |>
    # Combine all groups into a single string
    summarize(V1 = paste(V1, collapse = "")) |>
    # Split into groups using the separators
    summarize(V1 = strsplit(V1, "\n")[[1]]) |>
    # drop the empty group at the beginning
    filter(V1 != "")

更新:适用于较新版本的

dplyr
(汇总不能用于扩展行数)

df |>
    # Insert separators before and after groups
    mutate(V1 = ifelse(grepl("^>", V1), paste0("\n", V1, "\n"), V1)) |>
    # Combine all groups into a single string
    summarize(V1 = paste(V1, collapse = "")) |>
    # Split into groups using the separators
    reframe(V1 = strsplit(V1, "\n")[[1]]) |>
    # drop the empty group at the beginning
    filter(V1 != "")
© www.soinside.com 2019 - 2024. All rights reserved.