python Snakemake扩展字典,保留通配符

pu82cl6c  于 2023-04-04  发布在  Python
关注(0)|答案(4)|浏览(114)

我有一本这样的字典:

data = {
    "group1": ["a", "b", "c"], 
    "group2": ["x", "y", "z"]
}

我想使用expand来分别获得键和它们的值之间的所有组合在“rule all”中,s.t.预期的输出文件是例如“group1/a.txt”,“group1/b.txt”,...“group2/x.txt,“group2/y.txt”...

rule all: 
    input: 
        expand("{group}/{sub_group}.txt", group = ???, sub_group = ???)

我需要为规则“some_rule”使用这个:

rule some_rule: 
    input: "single_input_file.txt"
    output: "{group}/{sub_group}.txt"
    params: 
        group=group, # how do I extract these placeholders?
        sub_group=sub_group
    script: 
        "some_script.R"

我需要groupsub_group通配符的原因是因为我需要将它们传递给规则“some_rule”的params
我试图用列表解析来硬编码“rule all”中需要的所有输出文件,但是占位符没有在通配符中定义,我无法将它们传递给参数。
所以我想我需要使用expand定义“rule all”输入文件,但在这里我不知道如何获得正确的文件,因为**我需要在“group1”及其值和“group2”及其值之间单独执行组合。
我也不能对规则“some_rule”使用输入函数,因为它只有一个单一的静态输入文件。
在StackOverflow上的其他类似问题中,要么没有组合问题,要么他们使用普通的python为“rule_all”创建输入文件,这使我失去了通配符。

ruarlubt

ruarlubt1#

根据您的评论回答。

import pandas as pd

data = {
    "group1": ["a", "b", "c"],
    "group2": ["x", "y", "z"]
}

df = pd.DataFrame([(k, v) for k, vs in data.items() for v in vs],
                  columns=['Group', 'Value'])

rule all:
    input:
        expand("{group}/{sub_group}.txt", zip, group=df['Group'], sub_group=df['Value'])

rule some_rule:
    output: "{group}/{sub_group}.txt"
    params:
        group='{group}',
        sub_group='{sub_group}'
    shell:
        """
        echo {params.group} {params.sub_group} > {output}
        """
mwngjboj

mwngjboj2#

可以使用嵌套列表解析

data = {
    "group1": ["a", "b", "c"], 
    "group2": ["x", "y", "z"]
}

files = sum(
    [
        [f"{key}/{value}.txt" for value in values] for key,values in data.items()],
    []
)

print(files)

我想你是打算然后运行一个程序对每个文件?如果是这样:

for file in files:
     # run script on `file`
yiytaume

yiytaume3#

您可以使用以下命令:

rule some_rule: 
    input: "single_input_file.txt"
    output: "{group}/{sub_group}.txt"
    script: 
        "some_script.R"

并访问R脚本中的通配符{group}{subgroups}的值,例如snakemake@wildcards[['group']](未测试,但我认为应该可以)。
或者,我认为您可以:

params:
    group='{group}'
    sub_group='{sub_group}',
tct7dpnv

tct7dpnv4#

我找到了一个解决我的问题的方法,使用一个自定义组合子函数

def pairwise_product(*args):
result = []
for group, sub_group in zip(*args):
    sub_group = ([sub_group[0]], sub_group[1])
    for sub_sub_group in itertools.product(*sub_group):
        result.append((group, sub_sub_group))
return result

查看snakemake的expand函数的源代码,我意识到可以使用自己的combinator函数。
pairwise_product期望输入两个元组列表,其中每个元组包含通配符名称和通配符值,例如

wildcard1 = [("group", "group1"), ("group", "group2")]
wildcard2 = [("sub_group", ["a", "b", "c"]), ("sub_group", ["x", "y", "z"])]
pairwise_product(wildcard1, wildcard2)

这个函数调用的输出将是:

[(('group', 'group1'), ('sub_group', 'a')),
 (('group', 'group1'), ('sub_group', 'b')),
 (('group', 'group1'), ('sub_group', 'c')),
 (('group', 'group2'), ('sub_group', 'x')),
 (('group', 'group2'), ('sub_group', 'y')),
 (('group', 'group2'), ('sub_group', 'z'))]
  • *expand函数**的输出为:
expand("{group}/{sub_group}.txt", pairwise_product, group=data.keys(), sub_group=data.values())

['group1/a.txt',
 'group1/b.txt',
 'group1/c.txt',
 'group2/x.txt',
 'group2/y.txt',
 'group2/z.txt']

使用这个解决方案,我还可以获得我想要的通配符,即列表中的各个元素-分别为每个字典键提供值。
请注意,此函数仅针对data字典中所示格式的两个通配符设计,未针对其他格式进行测试。

相关问题