根据具有多个条件的文件名将字符串分配给对象
Assign string to object based on filename with multiple conditions
我根据提供的数据在我的 R 脚本中使用了一些开关,我想自动识别所述数据。我正在使用的文件在其名称中包含所需的信息,我正在寻找一种匹配和分配这些部分的好方法。
文件名:
# Folder1:
T090_V4_plate1_S90_L001_R1_001.fastq.gz
T090_V4_plate1_S90_L001_R2_001.fastq.gz
# Folder2:
T091_V4_plate2_S1_L001_R1_001.fastq.gz
T091_V4_plate2_S1_L001_R2_001.fastq.gz
# Folder3:
TNT_2017_13_V34_plate4_S13_L001_R1_001.fastq.gz
TNT_2017_13_V34_plate4_S13_L001_R2_001.fastq.gz
TNT_2017_14_V34_plate4_S14_L001_R1_001.fastq.gz
TNT_2017_14_V34_plate4_S14_L001_R2_001.fastq.gz
我想分配给对象的两个值是 V3
或 V34
到对象 primerset
和 plate[1-4]
到 plate
。我这样试过:
if (length(list.files(pattern = "plate1")) > 1) {
plate <<- "plate1"
} else if (length(list.files(pattern = "plate2")) > 1) {
plate <<- "plate2"
} else if (length(list.files(pattern = "plate3")) > 1) {
plate <<- "plate3"
} else if (length(list.files(pattern = "plate4")) > 1) {
plate <<- "plate4"}
if (length(list.files(pattern = "V4")) > 1) {
primerset <<- "V4"
} else if (length(list.files(pattern = "V34")) > 1) {
primerset <<- "V34"
}
# print message based on detected values from file names
if (primerset == "V34"){
cat("sequence length is 301 bp")
} else if (primerset == "V4"){
cat("sequence length is 250 bp")
}
效果很好,但看起来很复杂,容易出错。有更优雅的解决方案吗?我不想只为这个任务加载一个包。
此外,如果满足多个条件,我不知道如何添加中断,例如plate1
和 plate2
在同一文件夹中(我将数据集分开,但为了安全起见)。
解法:
根据下面的答案,这两个版本还测试是否只存在 primerset
或 plate
的一个实例:
filenames <- list.files()
if (length(unique(sub(".*_(plate\d)_.*", "\1", filenames))) == 1) {
plate <- unique(sub(".*_(plate\d)_.*", "\1", filenames))
}
matches = stringr::str_match(filenames, '_(V\d+)_(plate\d)')
if (length(unique(matches[, 2])) == 1) {
primerset = unique(matches[, 2])
}
这需要 regular expression。使用 {stringr} 包,你会写:
matches = stringr::str_match(x, '_(V\d+)_(plate\d)')
primerset = matches[, 2]
plate = matches[, 3]
即:匹配一个下划线,然后是'V'
和一个数字,然后是下划线,然后是'plate'
和一个数字。您可以扩展表达式以匹配泳道、交配和复制。
最重要的是,上面的内容是矢量化的,因此它可以正确处理文件名矢量。
请注意,无论哪种方式,您都应该而不是在此处使用<<-
(这执行全局而不是局部赋值并且很少适用)。
在 base R 中,我们可以使用 sub
来提取字符串的特定部分。
primerset <- sub(".*_(V4|V34)_.*", "\1", x)
#Or more generally
#primerset <- sub(".*_(V\d+)_.*", "\1", x)
plate <- sub(".*_(plate\d)_.*", "\1", x)
其中 x
是所有文件名的向量
x <- c("T090_V4_plate1_S90_L001_R1_001.fastq.gz",
"T090_V4_plate1_S90_L001_R2_001.fastq.gz",
"T091_V4_plate2_S1_L001_R1_001.fastq.gz",
"T091_V4_plate2_S1_L001_R2_001.fastq.gz",
"TNT_2017_13_V34_plate4_S13_L001_R1_001.fastq.gz",
"TNT_2017_13_V34_plate4_S13_L001_R2_001.fastq.gz",
"TNT_2017_14_V34_plate4_S14_L001_R1_001.fastq.gz",
"TNT_2017_14_V34_plate4_S14_L001_R2_001.fastq.gz")
我根据提供的数据在我的 R 脚本中使用了一些开关,我想自动识别所述数据。我正在使用的文件在其名称中包含所需的信息,我正在寻找一种匹配和分配这些部分的好方法。
文件名:
# Folder1:
T090_V4_plate1_S90_L001_R1_001.fastq.gz
T090_V4_plate1_S90_L001_R2_001.fastq.gz
# Folder2:
T091_V4_plate2_S1_L001_R1_001.fastq.gz
T091_V4_plate2_S1_L001_R2_001.fastq.gz
# Folder3:
TNT_2017_13_V34_plate4_S13_L001_R1_001.fastq.gz
TNT_2017_13_V34_plate4_S13_L001_R2_001.fastq.gz
TNT_2017_14_V34_plate4_S14_L001_R1_001.fastq.gz
TNT_2017_14_V34_plate4_S14_L001_R2_001.fastq.gz
我想分配给对象的两个值是 V3
或 V34
到对象 primerset
和 plate[1-4]
到 plate
。我这样试过:
if (length(list.files(pattern = "plate1")) > 1) {
plate <<- "plate1"
} else if (length(list.files(pattern = "plate2")) > 1) {
plate <<- "plate2"
} else if (length(list.files(pattern = "plate3")) > 1) {
plate <<- "plate3"
} else if (length(list.files(pattern = "plate4")) > 1) {
plate <<- "plate4"}
if (length(list.files(pattern = "V4")) > 1) {
primerset <<- "V4"
} else if (length(list.files(pattern = "V34")) > 1) {
primerset <<- "V34"
}
# print message based on detected values from file names
if (primerset == "V34"){
cat("sequence length is 301 bp")
} else if (primerset == "V4"){
cat("sequence length is 250 bp")
}
效果很好,但看起来很复杂,容易出错。有更优雅的解决方案吗?我不想只为这个任务加载一个包。
此外,如果满足多个条件,我不知道如何添加中断,例如plate1
和 plate2
在同一文件夹中(我将数据集分开,但为了安全起见)。
解法:
根据下面的答案,这两个版本还测试是否只存在 primerset
或 plate
的一个实例:
filenames <- list.files()
if (length(unique(sub(".*_(plate\d)_.*", "\1", filenames))) == 1) {
plate <- unique(sub(".*_(plate\d)_.*", "\1", filenames))
}
matches = stringr::str_match(filenames, '_(V\d+)_(plate\d)')
if (length(unique(matches[, 2])) == 1) {
primerset = unique(matches[, 2])
}
这需要 regular expression。使用 {stringr} 包,你会写:
matches = stringr::str_match(x, '_(V\d+)_(plate\d)')
primerset = matches[, 2]
plate = matches[, 3]
即:匹配一个下划线,然后是'V'
和一个数字,然后是下划线,然后是'plate'
和一个数字。您可以扩展表达式以匹配泳道、交配和复制。
最重要的是,上面的内容是矢量化的,因此它可以正确处理文件名矢量。
请注意,无论哪种方式,您都应该而不是在此处使用<<-
(这执行全局而不是局部赋值并且很少适用)。
在 base R 中,我们可以使用 sub
来提取字符串的特定部分。
primerset <- sub(".*_(V4|V34)_.*", "\1", x)
#Or more generally
#primerset <- sub(".*_(V\d+)_.*", "\1", x)
plate <- sub(".*_(plate\d)_.*", "\1", x)
其中 x
是所有文件名的向量
x <- c("T090_V4_plate1_S90_L001_R1_001.fastq.gz",
"T090_V4_plate1_S90_L001_R2_001.fastq.gz",
"T091_V4_plate2_S1_L001_R1_001.fastq.gz",
"T091_V4_plate2_S1_L001_R2_001.fastq.gz",
"TNT_2017_13_V34_plate4_S13_L001_R1_001.fastq.gz",
"TNT_2017_13_V34_plate4_S13_L001_R2_001.fastq.gz",
"TNT_2017_14_V34_plate4_S14_L001_R1_001.fastq.gz",
"TNT_2017_14_V34_plate4_S14_L001_R2_001.fastq.gz")