我有一个包含三列的数据集:
https://drive.google.com/file/d/1gtCssfAXHxRjGfX8uTAaimGPWCA2cnci/view?usp=sharing
以下是前几行:
ID transcript_id go_description
MA_10000213g0010 MA_10000213g0010
MA_10000405g0010 MA_10000405g0010 GO:0006468-protein phosphorylation;GO:0030246-carbohydrate binding;GO:0005524-ATP binding;GO:0004672-protein kinase activity
MA_1000049g0010 MA_1000049g0010
MA_10000516g0010 MA_10000516g0010 GO:0005515-protein binding
MA_10001015g0010 MA_10001015g0010
MA_10001337g0010 MA_10001337g0010
MA_10001425g0010 MA_10001425g0010
MA_10001478g0010 MA_10001478g0010
MA_10001558g0010 MA_10001558g0010
MA_10001g0010 MA_10001g0010
MA_10002030g0010 MA_10002030g0010 GO:0005737-cytoplasm;GO:0000184-nuclear-transcribed mRNA catabolic process, nonsense-mediated decay;GO:0004386-helicase activity;GO:0008270-zinc ion binding;GO:0003677-DNA binding;GO:0005524-ATP binding
MA_10002157g0010 MA_10002157g0010 GO:0006468-protein phosphorylation;GO:0005524-ATP binding;GO:0004672-protein kinase activity
MA_10002549g0010 MA_10002549g0010
MA_10002583g0010 MA_10002583g0010 GO:0008168-methyltransferase activity
MA_10002614g0010 MA_10002614g0010
MA_10002643g0010 MA_10002643g0010 GO:0055114-oxidation-reduction process
在第三列中,我想删除所有文本,只保留GO:xxxxxxx
每个术语应以逗号分隔的位置。例如:
GO:0006468, GO:0030246
前两列应保持不变。我怎样才能做到这一点?
答案1
假设您的数据是制表符分隔的,您可以这样做:
perl -F'\t' -lane '
$F[2] = join(",", $F[2]=~/GO:\d+/g);
print join "\t",@F
' gene_table_Go\ -\ gene_table_Go.tsv > fixed.tsv
make-a
的perl
作用类似于awk
nd 将每个输入行拆分到@F
由 给定的字符上的数组中-F
。在这里,我传递了一个选项卡(如果还没有,您可以随时将文件保存为制表符分隔的文件)。接下来,我将第三个字段 设定$F[2]
为将GO:
现有第三个字段中所有出现的 后跟数字连接起来的结果,换句话说,只保留 GO 术语而不保留其他任何内容。然后,我打印@F
由制表符连接的数组。
这是相同基本思想的更浓缩版本:
perl -F'\t' -lane '
$,="\t";
print @F[0..1], join(",",$F[2]=~/GO:\d+/g);
' gene_table_Go\ -\ gene_table_Go.tsv
两个示例产生相同的输出:
$ perl -F'\t' -lane '$,="\t"; print @F[0,1], join(",",$F[2]=~/GO:\d+/g);' gene_table_Go\ -\ gene_table_Go.tsv | head
ID transcript_id
MA_10000213g0010 MA_10000213g0010
MA_10000405g0010 MA_10000405g0010 GO:0006468,GO:0030246,GO:0005524,GO:0004672
MA_1000049g0010 MA_1000049g0010
MA_10000516g0010 MA_10000516g0010 GO:0005515
MA_10001015g0010 MA_10001015g0010
MA_10001337g0010 MA_10001337g0010
MA_10001425g0010 MA_10001425g0010
MA_10001478g0010 MA_10001478g0010
MA_10001558g0010 MA_10001558g0010
为了保持标题完整,因为它实际上与GO:\d+
模式不匹配,您可以这样做:
$ perl -F'\t' -lane '$,="\t"; print $. == 1 ? @F : @F[0,1], join(",",$F[2]=~/GO:\d+/g);' gene_table_Go\ -\ gene_table_Go.tsv | head
ID transcript_id go_description
MA_10000213g0010 MA_10000213g0010
MA_10000405g0010 MA_10000405g0010 GO:0006468,GO:0030246,GO:0005524,GO:0004672
MA_1000049g0010 MA_1000049g0010
MA_10000516g0010 MA_10000516g0010 GO:0005515
MA_10001015g0010 MA_10001015g0010
MA_10001337g0010 MA_10001337g0010
MA_10001425g0010 MA_10001425g0010
MA_10001478g0010 MA_10001478g0010
MA_10001558g0010 MA_10001558g0010
答案2
AWK:
$ awk '
BEGIN{FS=OFS="\t"}
{
while(match($3,/GO:[0-9]+/))
{
col= sprintf("%s",((col) ? col ",": "")substr($3,RSTART,RLENGTH));
$3= substr($3,RSTART+RLENGTH)
}
}
col{ $3=col; col=""}
1'
答案3
使用乐(以前称为 Perl_6)
假设\t
制表符作为列分隔符:
~$ raku -ne 'BEGIN put get; \
my @a = .split(:skip-empty, / \t /, 3); \
@a[2] = (@a[2] // "").comb(/ GO\: \d+ /).join(","); \
@a.join("\t").trim-trailing.put;' file
这是用 Raku(Perl 编程语言家族的成员)编写的答案。逐行进行:
BEGIN
标题行的语句(put
如果标题行\t
像正文行一样用制表符分隔,则可以省略)。正文行(行)可以拆分
\t
并保存到@a
数组中。请注意,可能(但有风险)分割\s**4
ie 四个连续的空白字符,甚至\h**4
(四个连续的空白字符)水平的空白字符),如果第三列不包含该模式。但同样,这是有风险的。第三列(即
@a[2]
)被替换为@a[2]
已comb
针对正则表达式 的一个或多个匹配项进行编辑(即正选)的列文本GO\: \d+
。认为comb
是相反的split
(这是破坏性的)。然后用逗号将选定的GO
-ID 连接起来。最后,这些
split
列在选项卡join
上重新组合在一起\t
,然后输出put
。
输入示例:
ID transcript_id go_description
MA_10000213g0010 MA_10000213g0010
MA_10000405g0010 MA_10000405g0010 GO:0006468-protein phosphorylation;GO:0030246-carbohydrate binding;GO:0005524-ATP binding;GO:0004672-protein kinase activity
MA_1000049g0010 MA_1000049g0010
MA_10000516g0010 MA_10000516g0010 GO:0005515-protein binding
MA_10001015g0010 MA_10001015g0010
MA_10001337g0010 MA_10001337g0010
MA_10001425g0010 MA_10001425g0010
MA_10001478g0010 MA_10001478g0010
MA_10001558g0010 MA_10001558g0010
MA_10001g0010 MA_10001g0010
MA_10002030g0010 MA_10002030g0010 GO:0005737-cytoplasm;GO:0000184-nuclear-transcribed mRNA catabolic process, nonsense-mediated decay;GO:0004386-helicase activity;GO:0008270-zinc ion binding;GO:0003677-DNA binding;GO:0005524-ATP binding
MA_10002157g0010 MA_10002157g0010 GO:0006468-protein phosphorylation;GO:0005524-ATP binding;GO:0004672-protein kinase activity
MA_10002549g0010 MA_10002549g0010
MA_10002583g0010 MA_10002583g0010 GO:0008168-methyltransferase activity
MA_10002614g0010 MA_10002614g0010
MA_10002643g0010 MA_10002643g0010 GO:0055114-oxidation-reduction process
示例输出:
ID transcript_id go_description
MA_10000213g0010 MA_10000213g0010
MA_10000405g0010 MA_10000405g0010 GO:0006468,GO:0030246,GO:0005524,GO:0004672
MA_1000049g0010 MA_1000049g0010
MA_10000516g0010 MA_10000516g0010 GO:0005515
MA_10001015g0010 MA_10001015g0010
MA_10001337g0010 MA_10001337g0010
MA_10001425g0010 MA_10001425g0010
MA_10001478g0010 MA_10001478g0010
MA_10001558g0010 MA_10001558g0010
MA_10001g0010 MA_10001g0010
MA_10002030g0010 MA_10002030g0010 GO:0005737,GO:0000184,GO:0004386,GO:0008270,GO:0003677,GO:0005524
MA_10002157g0010 MA_10002157g0010 GO:0006468,GO:0005524,GO:0004672
MA_10002549g0010 MA_10002549g0010
MA_10002583g0010 MA_10002583g0010 GO:0008168
MA_10002614g0010 MA_10002614g0010
MA_10002643g0010 MA_10002643g0010 GO:0055114
答案4
你可以考虑使用磨坊主,它内置了对 TSV 文件的支持 - 例如
$go_description
将字段拆分;
为数组GO:nnnnnn
应用正则表达式从数组的每个元素中提取子字符串- 将结果连接回一个
,
单独的字符串 - 将结果分配回
$go_description
所以
mlr --tsv put '
$go_description = joinv(
apply(splitax($go_description,";"),func(e) {return regextract(e,"GO:[[:digit:]]+")}),
","
)
' gene_table_Go.tsv