Сопоставить массив строк с 2D-массивом - PullRequest
0 голосов
/ 31 октября 2019

У меня есть массив 1D строк (gene_name_list). Мне нужно найти строки в другом массиве 2D (fully_split), где присутствует каждая строка первого массива. Конечно, я могу решить это грубой силой следующим образом:

longest_gene_name = len(max(gene_name_list, key=len))
ensembl_list = np.full((len(gene_name_list)), '', dtype='U{}'.format(longest_gene_name))
for idx, gene_name in enumerate(gene_name_list):  
    for row in fully_split:                       
        if gene_name in row:                      
            ensembl_list[idx] = row[0]

Но это занимает слишком много времени, мне нужно более быстрое решение.

row[0] содержит специальные символы, которые я отображаю. Итак, если строка найдена, она будет найдена в части row[1:], а затем я беру row[0]. Не актуально, но уточнить.

Ответы [ 2 ]

1 голос
/ 01 ноября 2019

Основываясь на вашем описании, я делаю пару предположений:
- массив 2d имеет прямоугольную форму (т. Е. Не dtype=object), поскольку производительность NumPy в противном случае была бы бесполезной.
- len(fully_split) == len(gene_name_list), поскольку в вашем примере кода естьensembl_list[idx] = row[0] и idx является производным от gene_name_list

>>> gene_name_list = np.array('a bb c d eee'.split())

>>> fully_split = np.array([
...     'id1 a bb c d eee'.split(), # yes
...     'id2 f g hh iii j'.split(),
...     'id3 kk ll a nn o'.split(), # yes
...     'id4 q rr c t eee'.split(), # yes
...     'id5 v www xx y z'.split()
... ])

>>> longest_gene_name = len(max(gene_name_list, key=len))

>>> dtype = 'U{}'.format(longest_gene_name)

>>> ensembl_list = np.zeros_like(gene_name_list, dtype=dtype)

>>> mask = np.isin(fully_split, gene_name_list).any(axis=1)

>>> ensembl_list[mask] = fully_split[mask, 0]

>>> ensembl_list
array(['id1', '', 'id3', 'id4', ''], dtype='<U3')
1 голос
/ 01 ноября 2019

Разделяя время выполнения, я не думаю, что метод грубой силы, который вы опубликовали, соответствует тому, что вы описываете словами:

Мне нужно найти строки в другом двумерном массиве, где каждая строка первого массива присутствует.

Ваш код в лучшем случае находит все строки там хотя бы одна строк массива 1D присутствует в строке2D-массив.

Следующий код выполняет то, что вы просили в словах, используя регулярное выражение.

import re

pattern = r'*'.join(map(re.escape, np.sort(gene_name_list)))
rows = [''.join(np.sort(x)) for x in fully_split]
res = [re.search(pattern, r) for r in rows]

Поскольку порядок не имеет значения, gene_name_list лексикографически сортируется, и строки объединяются с использованиемрегулярное выражение специальный символ '*' в качестве разделителя. Это шаблон, в котором будет производиться поиск.
Затем каждая строка двумерного массива fully_split снова будет лексикографически отсортирована, и строки будут объединены в одну строку. Поиск по регулярному выражению выполняется в каждой строке, чтобы проверить, есть ли совпадение.

res - это список, вы получаете None для тех строк, где совпадение не найдено, и соответствующее MatchObjectсовпадение найдено.

Это иллюстрирует концепцию. Чтобы быть ближе к ожидаемому результату (где вы храните первый элемент строки), замените последнюю строку на:

res = [l[0] if re.search(pattern, r) else None for r, l in zip(rows, fully_split)]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...