Snakemake:基于字典用expand生成组与子组文件并保留通配符
问题描述
给定如下Python字典:
data = { "group1": ["a", "b", "c"], "group2": ["x", "y", "z"] }
需要在Snakemake的rule all中使用expand函数,生成每个组(key)与其对应子组(value)的组合输出文件,比如group1/a.txt、group1/b.txt、group2/x.txt等,规则框架如下:
rule all: input: expand("{group}/{sub_group}.txt", group = ???, sub_group = ???)
同时需要配合以下rule some_rule实现,要求保留group和sub_group通配符并传递到params中:
rule some_rule: input: "single_input_file.txt" output: "{group}/{sub_group}.txt" params: group=group, # 如何提取这些占位符? sub_group=sub_group script: "some_script.R"
此前尝试用列表推导式硬编码rule all的输入文件,导致占位符无法被识别为通配符,进而无法传递到params;且因为rule some_rule只有静态输入文件,无法使用输入函数,需要用expand实现组与对应子组的匹配组合。
解决方案
1. 用expand实现组与子组的匹配组合
要避免生成组和子组的全交叉组合,需要让每个组只和自己的子组配对,有两种简洁实现方式:
方法一:基于配对元组列表的zip模式
先将字典转换为(组名, 子组名)的元组列表,再通过expand的zip参数实现一一配对:
# 先在Snakefile开头定义配对列表 group_subgroup_pairs = [(g, sg) for g, sgs in data.items() for sg in sgs] rule all: input: expand( "{group}/{sub_group}.txt", zip, group=[p[0] for p in group_subgroup_pairs], sub_group=[p[1] for p in group_subgroup_pairs] )
更简洁的写法可以用zip(*...)拆分元组列表:
group_subgroup_pairs = [(g, sg) for g, sgs in data.items() for sg in sgs] rule all: input: expand( "{group}/{sub_group}.txt", zip, group=zip(*group_subgroup_pairs)[0], sub_group=zip(*group_subgroup_pairs)[1] )
方法二:分组调用expand后拼接
对每个组单独调用expand生成对应子组的文件,再合并成总输入列表:
rule all: input: sum( [expand("{group}/{sub_group}.txt", group=g, sub_group=sgs) for g, sgs in data.items()], [] )
2. 正确提取通配符到params
在rule some_rule中,通配符值需要通过wildcards对象获取,修改后的规则如下:
rule some_rule: input: "single_input_file.txt" output: "{group}/{sub_group}.txt" params: group=wildcards.group, sub_group=wildcards.sub_group script: "some_script.R"
Snakemake会自动识别输出文件名中的通配符,并将对应的值传递到params中,供后续脚本使用。
内容的提问来源于stack exchange,提问作者Klumpi
相关产品推荐
相关产品推荐

