Индексация строк

Я пытаюсь получить вывод на основе этой процедуры, которую лучше всего объяснить на примере.

например в улыбке

С (N) (N) CC (N) C, [0, 1, 2, 0, 0, 1, 0]
это результат, который я пытаюсь получить.

Он подсчитывает ветвление (которое представлено скобками). Таким образом, для приведенного выше примера он считает первый (N) как 1, затем второй (N) как 2. Затем этот счетчик сбрасывается, как только он достигает атома, который не разветвлен (или заключен в скобки). Он продолжает получать 0, и счет начинается и снова сбрасывается. Проблема в том, что я не получаю ожидаемого результата. Ниже приведены мои результаты, ожидаемые результаты и код. Спасибо

Кроме того, мне нужно убедиться, что такие ситуации, как эти CC(CC(C)) не индексируются неправильно. Он не должен считать превышение и не сбрасывать, не непрерывно считать. Эта улыбка должна иметь вывод [0 0 1 1 1].

другой пример: CC(CCC)CCCC [0 0 1 1 1 0 0 0 0]

Для вложенных скобок я повторю этот процесс и просто начну считать с 1.

я получаю это

          SMILES                             branch_count
0  C(N)(N)CC(N)C  [0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0]
1            CCC                                [0, 0, 0]
2          C1CC1                          [0, 0, 0, 0, 0]
3      C1CC1(C)C              [0, 0, 0, 0, 0, 0, 1, 0, 0]
4         CC(C)C                       [0, 0, 0, 1, 0, 0]

когда это должно быть

          SMILES        branch_count
0  C(N)(N)CC(N)C  [0, 1, 2, 0, 0, 1, 0]
1            CCC           [0, 0, 0]
2          C1CC1           [0, 0, 0]
3      C1CC1(C)C        [0, 0, 0, 1, 0]
4         CC(C)C           [0, 0, 1, 0]


import pandas as pd
import numpy as np
from rdkit import Chem

def get_branch_count(smile):
    # Initialize variables
    branch_count = [0] * len(smile)
    bracket_count = 0
    current_count = 0
    
    # Loop through each character in the smile
    for i, c in enumerate(smile):
        # If the character is an open bracket, increment bracket count
        if c == "(":
            bracket_count += 1
        # If the character is a close bracket, decrement bracket count
        elif c == ")":
            bracket_count -= 1
            # If there are no more open brackets after this one, reset current count
            if bracket_count == 0:
                current_count = 0
        # If the character is not a bracket, update the current count
        else:
            if bracket_count > 0:
                # If the previous character was also a bracket, don't increment the count
                if smile[i-1] != ")":
                    current_count += 1
            else:
                current_count = 0
            branch_count[i] = current_count
            
    return branch_count

def collect_branch_count(smile_list):
    rows = []

    for smile in smile_list:
        branch_count = get_branch_count(smile)
        data = {"branch_count": branch_count}

        row = {"SMILES": smile}
        for key, value in data.items():
            row[key] = value
        rows.append(row)

    df = pd.DataFrame(rows)
    return df

smile_list = ["C(N)(N)CC(N)C", "CCC", "C1CC1", "C1CC1(C)C", "CC(C)C"]
df = collect_branch_count(smile_list)
print(df)

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
0
77
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Это мое решение.

Сначала я заменяю все C1 на C, чтобы оценить одну букву как необязательную группу. Затем я считаю открытые скобки. Если открыта только одна корзина, у меня новая группа. Если у меня есть закрывающая скобка, я проверяю, что следующая буква является открывающей, чтобы проверить, есть ли последовательная группа. Если нет, я сбрасываю счетчик на 0.

import pandas as pd

def smile_grouping(s):
    s = s.replace('C1', 'C')
    open_brackets = 0
    group_counter = 0

    res = []
    for i, letter in enumerate(s):
        if letter == '(':
            open_brackets += 1
            if open_brackets == 1:
                group_counter += 1
        elif letter == ')':
            open_brackets -= 1
        else:
            res.append(group_counter)

        if open_brackets == 0:
            if i+1<len(s) and s[i+1] != '(':
                group_counter = 0
    return res

Это результат

df = pd.DataFrame(
    {'smile':[
        "C(N)(N)CC(N)C",
        "CCC",
        "C1CC1",
        "C1CC1(C)C",
        "CC(C)C",
        "C(N)(N)(N)CC(N)C",
        "C((N)(N)N)CC(N)C",
        "CC(CCC)CCCC",
        "CC(CC(C))"
    ]})
df['branch_count'] = df['smile'].apply(smile_grouping)
>>> df
              smile                 branch_count
0     C(N)(N)CC(N)C        [0, 1, 2, 0, 0, 1, 0]
1               CCC                    [0, 0, 0]
2             C1CC1                    [0, 0, 0]
3         C1CC1(C)C              [0, 0, 0, 1, 0]
4            CC(C)C                 [0, 0, 1, 0]
5  C(N)(N)(N)CC(N)C     [0, 1, 2, 3, 0, 0, 1, 0]
6  C((N)(N)N)CC(N)C     [0, 1, 1, 1, 0, 0, 1, 0]
7       CC(CCC)CCCC  [0, 0, 1, 1, 1, 0, 0, 0, 0]
8         CC(CC(C))              [0, 0, 1, 1, 1]

Большое спасибо. Это работает, но для таких случаев, как эти smile branch_count 0 CCC(CCC) [0, 0, 0, 1] 1 CCC(CCC(CC)) [0, 0, 0, 1] Вся ветвь считается как 1 столбец . Есть ли у вас какие-либо идеи о том, как решить эту проблему? Так, например, они должны быть такими: 0 CCC(CCC) [0, 0, 0, 1, 1, 1] 1 CCC(CCC(CC)) [0, 0, 0, 1, 1, 1, 1, 1]

YZman 02.04.2023 16:39

@YZman Пожалуйста, смотрите мой обновленный ответ. Я переместил строку res.append(...) в блок else, поэтому group_counter всегда добавляется, если буква не ( или ).

mosc9575 02.04.2023 21:34
Ответ принят как подходящий

Цикл включает скобки как символы, поэтому для каждой открытой и закрытой скобки ваш код будет считать ее атомом. Вы должны проверить, является ли символ буквой или нет, используя .isalpha(). Тогда у вас также должна быть проверка (у меня n), должен ли символ быть заменен числом или нет. Например, в вашем плохом коде скобки и числа также были заменены на 0/1, а это означало, что у вас были дополнительные атомы, которые вам не нужны. Прочитайте мои комментарии для дополнительных объяснений и запустите этот код в своем собственном движке, чтобы убедиться, что он правильный (хотя я уже проверял несколько раз).

import pandas as pd
import numpy as np
from rdkit import Chem


# All changes in function
def get_branch_count(smile):
    # Initialize variables
    n = 0 # This is to make sure that only the needed characters are added, so it doesn't include 
    length_smile = 0
    for char in smile:
        if char.isalpha():
            length_smile += 1
    branch_count = [0] * length_smile
    bracket_count = 0
    bracket_together = 0 # Use this variable for when the brackets are next to each other for less confusing code
    current_count = 0
    # Loop through each character in the smile
    for i, c in enumerate(smile):
        if c == '(':
            bracket_count += 1
        
        # Continue after the IF statement because the letters are now inside of the brackets
        elif bracket_count >= 1 and c.isalpha():
            current_count = bracket_count
            branch_count[n] = current_count
            n += 1
        # This is to check if there are consecutive branches
        elif c ==')':
            if smile[i+1] != '(':
                bracket_count = 0
            
            
        # If the character is not surrounded by brackets and if it is alphabetical
        elif c.isalpha() and bracket_count == 0:
            current_count = 0
            branch_count[n] = current_count # Do this inside of each IF statement for the alphabetical chars so that it doesn't include the brackets
            n += 1
            
    return branch_count

def collect_branch_count(smile_list):
    rows = []

    for smile in smile_list:
        branch_count = get_branch_count(smile)
        data = {"branch_count": branch_count}

        row = {"SMILES": smile}
        for key, value in data.items():
            row[key] = value
        rows.append(row)

    df = pd.DataFrame(rows)
    return df

smile_list = ["C(N)(N)CC(N)C", "CCC", "C1CC1", "C1CC1(C)C", "CC(C)C"]
df = collect_branch_count(smile_list)
print(df)


Как видите, я изменил несколько вещей:

  • Вместо того, чтобы делать branch_count = [0] * len(smile), я изменил его на:

     ```python
     # This is to make sure that there are no extra numbers (for example the brackets and the non-alphabetical characters.
     length_smile = 0
     for char in smile:
         if char.isalpha():
             length_smile += 1
     branch_count = [0] * length_smile
     ```
    

Другие вопросы по теме