Сравните массив с файлом и сформируйте группы из элементов массива - PullRequest
0 голосов
/ 03 января 2019

У меня есть текстовый файл с буквами (с разделителями табуляции), и массив Numpy (obj) с несколькими буквами (одна строка).В текстовом файле есть строки с разным количеством столбцов.Некоторые строки в текстовом файле могут иметь несколько копий одних и тех же букв (я хотел бы рассмотреть только одну копию буквы в каждой строке).Предполагается, что буквы в одной строке текстового файла похожи друг на друга.Кроме того, каждая буква массива NumPy obj присутствует в одной или нескольких строках текстового файла.

Ниже приведен пример текстового файла (вы можете скачать файл с здесь ):

b   q   a   i   m   l   r
j   n   o   r   o
e   i   k   u   i   s

В приведенном выше примере буква o упоминается два раза во втором ряду, а буква i - два раза в третьем ряду.Я хотел бы рассмотреть отдельные копии буквенных строк текстового файла.

Это пример obj: obj = np.asarray(['a', 'e', 'i', 'o', 'u'])

Я хочу сравнить obj со строкамитекстовый файл и образуют кластеры из элементов в obj.

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

Ниже приведен код Python, который я написал для этой задачи

import pandas as pd
import numpy as np

data = pd.read_csv('file.txt', sep=r'\t+', header=None, engine='python').values[:,:].astype('<U1000')
obj = np.asarray(['a', 'e', 'i', 'o', 'u'])

for i in range(data.shape[0]):
    globals()['data_row' + str(i).zfill(3)] = []
    globals()['clust' + str(i).zfill(3)] = []
    for j in range(len(obj)):
        if obj[j] in set(data[i, :]): globals()['data_row' + str(i).zfill(3)] += [j]

for i in range(len(obj)):
    globals()['obj_lst' + str(i).zfill(3)] = [0]*data.shape[0]  

    for j in range(data.shape[0]):
        if i in globals()['data_row' + str(j).zfill(3)]:
            globals()['obj_lst' + str(i).zfill(3)][j] = len(globals()['data_row' + str(j).zfill(3)])

    indx_max = globals()['obj_lst' + str(i).zfill(3)].index( max(globals()['obj_lst' + str(i).zfill(3)]) )
    globals()['clust' + str(indx_max).zfill(3)] += [i]  

for i in range(data.shape[0]): print globals()['clust' + str(i).zfill(3)]

>> [0]
>> [3]
>> [1, 2, 4]

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

1 Ответ

0 голосов
/ 03 января 2019

Вы можете сделать это, используя merge после stack на data (в пандах), затем немного groupby с nunique или idxmax, чтобы получить то, что вы хотите

#keep data in pandas
data = pd.read_csv('file.txt', sep=r'\t+', header=None, engine='python')
obj = np.asarray(['a', 'e', 'i', 'o', 'u'])

#merge to keep only the letters from obj
df = (data.stack().reset_index(0,name='l')
          .merge(pd.DataFrame({'l':obj})).set_index('level_0'))

#get the len of unique element of obj in each row of data
# and use transform to keep this lenght along each row of df
df['len'] = df.groupby('level_0').transform('nunique')

#get the result you want in a series
res = (pd.DataFrame({'data_row':df.groupby('l')['len'].idxmax().values})
         .groupby('data_row').apply(lambda x: list(x.index)))
print(res)

data_row
0          [0]
1          [3]
2    [1, 2, 4]
dtype: object

res содержит кластеры с индексом, являющимся строкой в ​​оригинале data

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...