pymorphy2 icon indicating copy to clipboard operation
pymorphy2 copied to clipboard

Склонение фамилий

Open mtarenda opened this issue 3 years ago • 8 comments

Если я точно знаю, что слово - фамилия в именительном падеже (например, Рыжиков), как мне это явно задать, чтобы фамилия склонялась правильно?

mtarenda avatar May 11 '21 21:05 mtarenda

Обычно просто нужно выбрать правильное значение из списка значений -- то, что стоит в именительном падеже. Хуже, если такой фамилии там нет, как в данном случае -- тогда склонять её с помощью pymorphy не получится. Но фамилии достаточно регулярно склоняются, просто сделай свою карту склонений, если сильно нужно.

buriy avatar May 12 '21 04:05 buriy

Правильную форму не находит, "ов" отбрасывает. Пишет: рыжик, котельник, слабик и т.п. В теге пишет Name plur. Как делается карта склонений?

delph1n avatar May 12 '21 05:05 delph1n

"-ов", и.п. => м.р. , без окончания => р.п.: +а ("рыжикова") д.п.: +у ("рыжикову") в.п.: +а ("рыжикова") ... Впрочем, всё это уже забито в https://petrovich.nlpub.ru/ , попробуйте его.

buriy avatar May 12 '21 07:05 buriy

Еще одно решение:

https://ws3.morpher.ru/russian/declension?format=json&s=Рыжиков

{
  "Р": "Рыжикова",
  "Д": "Рыжикову",
  "В": "Рыжикова",
  "Т": "Рыжиковым",
  "П": "Рыжикове",
  "ФИО": {
    "Ф": "Рыжиков",
    "И": "",
    "О": ""
  }
}

bzaar avatar May 12 '21 12:05 bzaar

Спасибо! Лучше все же на питоне модуль, не веб-сервис. Помучаю Петровича.

mtarenda avatar May 12 '21 13:05 mtarenda

Пожалуйста! Вот еще один питоновский модуль:

https://morpher.ru/python/

bzaar avatar May 12 '21 13:05 bzaar

Кажется, такое нужно делать очень низкоуровнево, но всё же сделать можно.

import pymorphy2
m = pymorphy2.MorphAnalyzer()

Сначала нужно выяснить номер "правильной" парадигмы. Наверное, фамилию "Иванов" pymorphy2 знает и умеет склонять так, как надо.

>>> m.parse("Иванов")[0]
Parse(word='иванов', tag=OpencorporaTag('NOUN,anim,masc,Sgtm,Surn sing,nomn'), normal_form='иванов', score=0.962264, methods_stack=((DictionaryAnalyzer(), 'иванов', 37, 0),))

Здесь 37 - индекс парадигмы, а 0 - номер формы внутри парадигмы. Нам нужно число 37. Программно его можно достать так:

m.parse("Иванов")[0][4][0][2]

0 - самый вероятный разбор, 4 - methods_stack, 0 - первый элемент стэка (то есть DictionaryAnalyzer), 2 - элемент тюпла, в котором лежит индекс парадигмы.

Теперь воспользуемся этим номером парадигмы.

ru_dict = m._units[0][0].dict  # словарь, инициализированный данными для русского языка
stem = "рыжиков"
paradigm = ru_dict .build_paradigm_info(37)

(в более общем случае stem = ru_dict.build_stem(ru_dict.paradigms[37], 0, "рыжиков") или что-то такое)

И вот формы:

>>> for index, (_prefix, _tag, _suffix) in enumerate(paradigm):
...             word = _prefix + stem + _suffix
...             print(word, _tag)
...
рыжиков NOUN,anim,masc,Sgtm,Surn sing,nomn
рыжикова NOUN,anim,masc,Sgtm,Surn sing,gent
рыжикову NOUN,anim,masc,Sgtm,Surn sing,datv
рыжикова NOUN,anim,masc,Sgtm,Surn sing,accs
рыжиковым NOUN,anim,masc,Sgtm,Surn sing,ablt
рыжикове NOUN,anim,masc,Sgtm,Surn sing,loct
рыжикова NOUN,anim,femn,Sgtm,Surn sing,nomn
рыжиковой NOUN,anim,femn,Sgtm,Surn sing,gent
рыжиковой NOUN,anim,femn,Sgtm,Surn sing,datv
рыжикову NOUN,anim,femn,Sgtm,Surn sing,accs
рыжиковой NOUN,anim,femn,Sgtm,Surn sing,ablt
рыжиковой NOUN,anim,femn,Sgtm,Surn sing,loct
рыжиковы NOUN,anim,ms-f,Pltm,Surn plur,nomn
рыжиковых NOUN,anim,ms-f,Pltm,Surn plur,gent
рыжиковым NOUN,anim,ms-f,Pltm,Surn plur,datv
рыжиковых NOUN,anim,ms-f,Pltm,Surn plur,accs
рыжиковыми NOUN,anim,ms-f,Pltm,Surn plur,ablt
рыжиковых NOUN,anim,ms-f,Pltm,Surn plur,loct

bt2901 avatar May 18 '21 08:05 bt2901

Кажется, такое нужно делать очень низкоуровнево, но всё же сделать можно.

О, супер! Буду пробовать! Благодарю!

mtarenda avatar May 18 '21 14:05 mtarenda