如何在R中从字符向量中删除常见的字符串部分?

3
假设有一个如下的字符向量:
file1_p1_analysed_samples.txt
file1_p1_raw_samples.txt
f2_file2_p1_analysed_samples.txt
f3_file3_p1_raw_samples.txt

期望的输出:

file1_p1_analysed
file1_p1_raw
file2_p1_analysed
file3_p1_raw

我希望能够比较元素并尽可能地从开头和结尾删除字符串的部分,但保持它们的独特性。

上面只是一个例子。要删除的部分对所有元素来说并不常见。我需要一种通用的解决方案,与上面示例中的字符串无关。

到目前为止,我已经能够除去所有元素都共有的部分,前提是分隔符和分割后的部分长度相同。以下是函数:

mf <- function(x,sep){
    xsplit = strsplit(x,split = sep)
    xdfm <- as.data.frame(do.call(rbind,xsplit))
    res <- list()
    for (i in 1:ncol(xdfm)){
        if (!all(xdfm[,i] == xdfm[1,i])){
            res[[length(res)+1]] <- as.character(xdfm[,i])
        }
    }
    res <- as.data.frame(do.call(rbind,res))
    res <- apply(res,2,function(x) paste(x,collapse="_"))
    return(res)
}

应用上述函数:
 a = c("a_samples.txt","b_samples.txt")
 mf(a,"_")
  V1  V2
 "a" "b"

2.

> b = c("apple.fruit.txt","orange.fruit.txt")
> mf(b,sep = "\\.")
      V1       V2
 "apple" "orange"

如果分割后的部分长度不同,这种方法就行不通了。

如果您想要删除的部分在所有元素中都相同,那么这很容易实现:gsub("_samples.txt", "", [your vector]) - ulfelder
不,它们不一样。 - Veera
@Veera,为什么你移除了 f2f3?它们不一样。 - pogibas
@PoGibas 是的。但是在删除它们之后,仍然得到了唯一的字符串。我希望只有当字符串不再唯一时才停止删除。 - Veera
1
@ulfelder:你需要转义点号。否则它只是另一个字符(可能确实是一个点,但也可能是其他任何字符)。 - Jan
2个回答

1
这句话的意思是“关于什么”。
files <- c("file1_p1_analysed_samples.txt", "file1_p1_raw_samples.txt", "f2_file2_p1_analysed_samples.txt", "f3_file3_p1_raw_samples.txt")
new_files <- gsub('_samples\\.txt', '', files)
new_files

"...这将产生/得到"
[1] "file1_p1_analysed"    "file1_p1_raw"         "f2_file2_p1_analysed" "f3_file3_p1_raw"     

这会从你的字符串中移除_samples.txt这一部分。

不,这不是我想要的。我需要一个自动确定向量中字符串的唯一和非唯一部分并仅删除非唯一部分的解决方案。 - Veera

1
为什么不呢?
strings <- c("file1_p1_analysed_samples.txt",
"file1_p1_raw_samples.txt",
"f2_file2_p1_analysed_samples.txt",
"f3_file3_p1_raw_samples.txt")

sapply(strings, function(x) {
  pattern <- ".*(file[0-9].*)_samples\\.txt"
  gsub(x, pattern = pattern, replacement = "\\1")
})

在替换中,与()之间匹配的内容可以称为后向引用组。您可以使用\\1来实现此目的。您甚至可以指定多个组!

看到您对Jan答案的评论。为什么不定义静态位并将它们粘贴在一起,然后始终用括号括起来?然后您可以始终在gsub的替换中调用\\i


哦,@Jan的答案更好。也许用这个模式替换他的模式: '.(file[0-9].)_samples\.txt',别忘了使用\\1进行反向引用。 - Erik Schutte

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接