Python словарей не копируются должным образом, вызывая повторы, как это сделать правильно? - PullRequest
0 голосов
/ 16 июня 2020

Я пишу функцию, которая должна сравнивать списки (важные гены для теста) и перечислять общие элементы (гены) для всех возможных комбинаций выбора списков.

Эти результаты предназначены для может использоваться для диаграммы Венна ...

Количество тестов и гибких генов.

Входной JSON файл выглядит примерно так:

| test              | genes                                                 |
|-----------------  |---------------------------------------------------    |
| p-7trt_1/0con_1   | [ENSMUSG00000000031, ENSMUSG00000000049, ENSMU...     |
| p-7trt_2/0con_1   | [ENSMUSG00000000031, ENSMUSG00000000037, ENSMU...     |
| p-7trt_1/0con_2   | [ENSMUSG00000000037, ENSMUSG00000000049, ENSMU...     |
| p-7trt_2/0con_2   | [ENSMUSG00000000028, ENSMUSG00000000031, ENSMU...     |
| p-7trt_1/0con_3   | [ENSMUSG00000000088, ENSMUSG00000000094, ENSMU...     |
| p-7trt_2/0con_3   | [ENSMUSG00000000028, ENSMUSG00000000031, ENSMU...     |

Итак, функция выглядит следующим образом:

import pandas as pd
def get_venn_compiled_data(dir_loc):
    """return json of compiled data for the venn thing
    """
    data_frame = pd.read_json(dir_loc + "/venn.json", orient="records")
    number_of_tests = data_frame.shape[0]
    venn_data = []
    venn_data_point = {"tests": [], "genes": []} # list of genes which are common across listed tests
    binary = lambda x: bin(x)[2:] # to directly get the binary number
    for dec_number in range(1, 2 ** number_of_tests):

        # resetting
        venn_data_point["tests"] = []
        venn_data_point["genes"] = []

        # using a binary number to get all the cases
        for index, state in enumerate(binary(dec_number)):
            if state == "0":
                continue

            # putting in all the genes from the first test
            if venn_data_point["tests"] == []:
                venn_data_point["genes"] = data_frame["data"][index].copy()

            # removing the ones which are not common in current genes state and this.tests
            else:
                for gene_index, gene in enumerate(venn_data_point["genes"]):
                    if gene not in data_frame["data"][index]:
                        venn_data_point["genes"].pop(gene_index)

            # putting the test in the tests list
            venn_data_point["tests"].append(data_frame["name"][index])

        venn_data.append(venn_data_point.copy())
    return venn_data

Я в основном злоупотребляю тем фактом, что двоичное число генерирует все возможные комбинации единиц и нулей, так что каждое место двоичного числа соответствует тесту, и для каждого двоичного числа число, если присутствует 0, то список, соответствующий этому тесту, не берется для сравнения.

Я изо всех сил старался объяснить, пожалуйста, спросите в комментариях, если я не понял.

После запуска функции я получаю результат, в котором есть случайные места, где повторяются наборы тестов.

Это тестовый входной файл.

* 1 022 * и

Это то, что получилось на выходе

Любая помощь приветствуется. Спасибо.

1 Ответ

0 голосов
/ 16 июня 2020

Я понял, какую ошибку делал

Я предполагал, что двоичная функция всегда волшебным образом будет генерировать строку с нужным мне количеством мест, чего не происходит.

После обновления двоичная функция для добавления этих нулей работает нормально.

import pandas as pd
def get_venn_compiled_data(dir_loc):
    """return json of compiled data for the venn thing
    """
    # internal variables
    data_frame = pd.read_json(dir_loc + "/venn.json", orient="records")
    number_of_tests = data_frame.shape[0]
    venn_data = []

    # defining internal function
    def binary(dec_no, length=number_of_tests):
        """Just to convert decimal number to binary of specified length
        """
        bin_number = bin(dec_no)[2:]

        if len(bin_number) < length:
            bin_number = "0" * (length - len(bin_number)) + bin_number

        return bin_number

    # list of genes which are common across listed tests
    venn_data_point = {
        "tests": [],
        "genes": [],
    }


    for dec_number in range(1, 2 ** number_of_tests):

        # resetting
        venn_data_point["tests"] = []
        venn_data_point["genes"] = []

        # using a binary number to get all the cases
        for index, state in enumerate(binary(dec_number)):
            if state == "0":
                continue

            # putting in all the genes from the first test
            if venn_data_point["tests"] == []:
                venn_data_point["genes"] = data_frame["data"][index].copy()

            # removing the ones which are not common in current genes state and this.tests
            else:
                for gene_index, gene in enumerate(venn_data_point["genes"]):
                    if gene not in data_frame["data"][index]:
                        venn_data_point["genes"].pop(gene_index)

            # putting the test in the tests list
            venn_data_point["tests"].append(data_frame["name"][index])

        venn_data.append(venn_data_point.copy())
    return venn_data

Если у кого-то еще есть более оптимизированный алгоритм для этого, помощь приветствуется.

...