Я пытаюсь получить вывод на основе этой процедуры, которую лучше всего объяснить на примере.
например в улыбке
С (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)
Это мое решение.
Сначала я заменяю все 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]
@YZman Пожалуйста, смотрите мой обновленный ответ. Я переместил строку res.append(...)
в блок else
, поэтому group_counter
всегда добавляется, если буква не (
или )
.
Цикл включает скобки как символы, поэтому для каждой открытой и закрытой скобки ваш код будет считать ее атомом. Вы должны проверить, является ли символ буквой или нет, используя .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
```
Большое спасибо. Это работает, но для таких случаев, как эти 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]