2017-02-03 21 views
0

У меня есть набор тегов, которые мне интересны при подсчете. Скажем, они:Подсчет в Python и создание матриц из результатов

pos_tags = ["NN", "NNS", "JJ"] 

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

sents = ["I want to go home.", "I have five dollars.", "The grass is green and wet."] 

я использовал nltk.pos_tag маркировать каждое слово с результатом бытия:

['I', 'want', 'to', 'go', 'home', '.'] 
[('I', 'PRP'), ('want', 'VBP'), ('to', 'TO'), ('go', 'VB'), ('home', 'NN'), ('.', '.')] 
['I', 'have', 'five', 'dollars', '.'] 
[('I', 'PRP'), ('have', 'VBP'), ('five', 'CD'), ('dollars', 'NNS'), ('.', '.')] 
['The', 'grass', 'is', 'green', 'and', 'wet', '.'] 
[('The', 'DT'), ('grass', 'NN'), ('is', 'VBZ'), ('green', 'JJ'), ('and', 'CC'), ('wet', 'NN'), ('.', '.')] 

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

В строках будет количество предложений. В этом случае, 3. Столбцы будут числом тегов. В этом случае, а также 3.

Окончательный результат будет выглядеть следующим образом:

[1, 0, 0 
0, 1, 0 
2, 0, 1] 

Это то, что я до сих пор:

def tagging(sents): 

    matrix = [] 
    pos_tags = ["NN", "NNS", "JJ"] 

    for sent in sents: 

     tokens = nltk.word_tokenize(sent) 

     tagged_tokens = nltk.pos_tag(tokens) 
     tagged_tokens_final = tagged_tokens 


    for key, val in tagged_tokens_final: 
     if val in common_pos_tags: 
      counting = val.count(val) 

ответ

1

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

tags = ['NN', 'NNS', 'JJ'] 

matrix = [None] * len(sents) 
for index, sent in enumerate(sents): 
    matrix[index] = do_counting(sent, tags) 

Если вы хотите расширить матрицу динамически, а предварительное выделение с [None] * len(sents), вы можете сделать это:

matrix = [] 
for sent in sents: 
    matrix.append(do_counting(sent, tags)) 

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

Разбор будет производиться с помощью nltk так же, как вы уже определились. Счёт наиболее легко выполняется с помощью объекта collections.Counter, который в значительной степени предназначен для этой цели. Он будет подсчитывать количество вхождений каждого тега. Затем мы можем выбрать теги мы хотим, основываясь на списке вы передаете в качестве второго аргумента:

from collections import Counter 
def do_counting(sentence, tags) 
    tokens = nltk.word_tokenize(sent) 
    tagged_tokens = nltk.pos_tag(tokens) 
    counts = Counter(tag for _, tag in tagged_tokens) 
    tag_counts = [counts[tag] for tag in tags] 
    return tag_counts 

Обратите внимание, что я игнорировать маркеры для целей подсчета. _ - допустимое имя переменной в Python, но обычно используется для указания отброшенных параметров. Счетчик может быть записана в виде

counts = Counter(item[0] for item in tagged_tokens) 

Это не было бы слишком трудно сделать подсчет себя вместо того, чтобы использовать Counter:

def do_counting(sentence, tags) 
    tokens = nltk.word_tokenize(sent) 
    tagged_tokens = nltk.pos_tag(tokens) 
    counts = [sum(items[1] == tag for items in tagged_tokens) for tag in tags] 
    return counts 

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

+0

Большое спасибо за ваше подробное объяснение - счетная часть особенно помогла! Для части матрицы я закончил использование np.array в библиотеке numpy - работал как шарм! – natalien

+0

Нет проблем. Вы можете создать массив numpy из конечного результата или использовать его для заполнения с самого начала. Я хотел придерживаться основного Python для этого ответа, потому что казалось, что вам нужно что-то более основное. –

2

существует различные типы матрицы в Python, Libs, но я только что сделал список списков

s1 = ['I', 'want', 'to', 'go', 'home', '.'] 
ts1 = [('I', 'PRP'), ('want', 'VBP'), ('to', 'TO'), ('go', 'VB'), ('home', 'NN'), ('.', '.')] 
s2 = ['I', 'have', 'five', 'dollars', '.'] 
ts2 = [('I', 'PRP'), ('have', 'VBP'), ('five', 'CD'), ('dollars', 'NNS'), ('.', '.')] 
s3 = ['The', 'grass', 'is', 'green', 'and', 'wet', '.'] 
ts3 = [('The', 'DT'), ('grass', 'NN'), ('is', 'VBZ'), ('green', 'JJ'), ('and', 'CC'), ('wet', 'NN'), ('.', '.')] 

pos_tags = ["NN", "NNS", "JJ"] 

вложенного список понимание делает штраф здесь построения списка списков
sum(sen,()) уплощается список кортежей - но не самое рекомендуется для выполнения

tagd_sents = [ts1, ts2, ts3] 

tagm = [[sum(sen,()).count(tag) for tag in pos_tags] for sen in tagd_sents] 

print(*tagm, sep='\n') 
[1, 0, 0] 
[0, 1, 0] 
[2, 0, 1] 

Mad Физик правильно о быстрой и грязной выше подсчета тегов, которые также слова в предложении, уважая structu данных re было бы безопаснее

+0

Определенно продвигать это для умного подхода. В частности, 'sum (sen,()) сделал мой день. При этом это не сработает, если один из тегов появится как есть в предложении. 'sum (x [1] для x in sen,())' может быть лучшей альтернативой. Тройное вложенное понимание, которое все еще достаточно разборчиво :) –