我有一个如下所示的数据框:
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"))
如您所见,我想合并包含以“>”符号开头的字符串的两行之间的每一行。 坦白说,我不知道从哪里开始。 请指教。
为此我们可以使用
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
假设这本来是一个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
您可以使用字符串操作函数在每个组的开头和结尾插入分隔符,然后将所有内容折叠成一个字符串(包括插入的分隔符),然后使用分隔符将组分开。
使用基础-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 != "")