Определение рода по ФИО (1С)

Материал из КинтВики
Перейти к: навигация, поиск


Текущий вариант

// Функция получает пол по ФИО физлица
//
// Параметры
// 	ФамилияИмяОтчество - исходная строка
//
// Возвращаемое значение: пол в виде "М", "Ж" или "" если не удалось определить
// 	- 
//
Функция стрПолФИО(ФамилияИмяОтчество) Экспорт
	Фамилия = ""; Имя = ""; Отчество = "";
	стрПолучитьФИО(ФамилияИмяОтчество, Фамилия, Имя, Отчество);
	
	Если Отчество <> "" Тогда
		окончание1 = Сред(Отчество, СтрДлина(Отчество));
		Если окончание1 = "ч" ИЛИ окончание1 = "в" Тогда
			Возврат "М";
		ИначеЕсли окончание1 = "а" Тогда
			Возврат "Ж";
		КонецЕсли;
	КонецЕсли;
	
	окончание1 = Сред(Фамилия, СтрДлина(Фамилия));
	окончание2 = Сред(Фамилия, СтрДлина(Фамилия) - 1);
	окончание3 = Сред(Фамилия, СтрДлина(Фамилия) - 2);
	окончанияМужскихФамилий=",ов,ев,ий,ин,";
	окончанияЖенскихФамилий=",ова,ева,ина,ая,";
	Если Найти(окончанияМужскихФамилий, "," + окончание2 + ",") > 0 Тогда
		Возврат "М";
	ИначеЕсли Найти(окончанияЖенскихФамилий, "," + окончание2 + ",") > 0 
		ИЛИ Найти(окончанияЖенскихФамилий, "," + окончание3 + ",") > 0 
		Тогда
		Возврат "Ж";
	КонецЕсли;
	
	Если Имя <> "" Тогда
		окончание1 = Сред(Имя, СтрДлина(Фамилия));
		Если окончание1 = "а" ИЛИ окончание1 = "я"  ИЛИ окончание1 = "е" Тогда
			Возврат "Ж";
		Иначе
			Возврат "М";
		КонецЕсли;
	КонецЕсли;
	
	
	Возврат "";
КонецФункции


Процедура Тест_стрПолФИО() Экспорт
	
	Тестирование.ПроверитьРавенство("М", БазовыеТипы.стрПолФИО("Иванов Иван Иванович"));
	Тестирование.ПроверитьРавенство("М", БазовыеТипы.стрПолФИО("Иванов Иван"));
	Тестирование.ПроверитьРавенство("М", БазовыеТипы.стрПолФИО("Иванов"));
	Тестирование.ПроверитьРавенство("Ж", БазовыеТипы.стрПолФИО("Иванова"));
	Тестирование.ПроверитьРавенство("Ж", БазовыеТипы.стрПолФИО("Иванова Лидия Ивановна"));
	
	Тестирование.ПроверитьРавенство("Ж", БазовыеТипы.стрПолФИО("Чайко Лидия Ивановна"));
	Тестирование.ПроверитьРавенство("М", БазовыеТипы.стрПолФИО("Чайко Иван Иванович"));
	
	Тестирование.ПроверитьРавенство("М", БазовыеТипы.стрПолФИО("Попов Никита"));
	Тестирование.ПроверитьРавенство("Ж", БазовыеТипы.стрПолФИО("Попова Никита"));
	
	Тестирование.ПроверитьРавенство("Ж", БазовыеТипы.стрПолФИО("Чайко Лидия"));
	Тестирование.ПроверитьРавенство("Ж", БазовыеТипы.стрПолФИО("Чайко Ирина"));
	Тестирование.ПроверитьРавенство("М", БазовыеТипы.стрПолФИО("Чайко Иван"));
	
КонецПроцедуры


// Функция разделяет строку ФИО на фамилию, имя, отчество 
//
// Параметры
// 	ФамилияИмяОтчество - исходная строка
// 	Фамилия - результат, часть Фамилия
// 	Имя - результат, часть Имя
// 	Отчество - результат, часть Отчество
//
// Возвращаемое значение: Истина, если разделение выполнено успешно, иначе Ложь
//
Функция стрПолучитьФИО(ФамилияИмяОтчество, Фамилия, Имя, Отчество) Экспорт
	Фамилия = ""; Имя = ""; Отчество = "";
	ФИО = СокрЛП(ФамилияИмяОтчество);
	
	Если ПустаяСтрока(ФИО) Тогда Возврат Ложь; КонецЕсли;
	ПозПробела = Найти(ФИО, " ");
	Если ПозПробела = 0 Тогда 
		ПерваяБуква = Лев(Фамилия, 1);
		Если Врег(ПерваяБуква) <> ПерваяБуква Тогда 
			Возврат Ложь; 
		Иначе
			Фамилия = ФИО;
			Возврат Истина;
		КонецЕсли;
	КонецЕсли;
	
	Фамилия = Лев(ФИО, ПозПробела-1);
	ПерваяБуква = Лев(Фамилия, 1);
	Если Врег(ПерваяБуква) <> ПерваяБуква Тогда Фамилия = ""; Возврат Ложь; КонецЕсли;
	
	ИО = СокрЛ(Сред(ФИО, ПозПробела+1));
	ПерваяБуква = Лев(ИО, 1);
	Если Врег(ПерваяБуква) <> ПерваяБуква Тогда Фамилия = ""; Возврат Ложь; КонецЕсли;
	
	ПозПробела = Найти(ИО, " ");
	Если ПозПробела = 0 Тогда Имя = ИО; Возврат Истина; КонецЕсли;
	Имя = Лев(ИО, ПозПробела-1);
	
	Отчество = СокрЛ(Сред(ИО, ПозПробела+1));
	ПерваяБуква = Лев(Отчество, 1);
	Если Врег(ПерваяБуква) <> ПерваяБуква Тогда Отчество = ""; Возврат Ложь; КонецЕсли;
	Возврат Истина;
КонецФункции // стрПолучитьФИО()

На дельфи

Источник: http://forum.developing.ru/archive/index.php/t-1559.html

function GenCaseFIO(const s:string):string;
var
f,i,o,t:string; gen:TGender;
begin
f:=ExtractWord(1,S,StdWordDelims);
i:=ExtractWord(2,S,StdWordDelims);
o:=trim(ExtractWord(3,S,StdWordDelims)+' '+ExtractWord(4,S,StdWordDelims));
if length(o)>2 then begin
if (o[length(o)] in ['ч','в']) or ((o[length(o)] in ['ы','э']) and (o[length(o)-1]='л')) then gen:=masculine
else if (o[length(o)] = 'а') or ((o[length(o)] in ['ы','э']) and (o[length(o)-1]='з')) then gen:=feminine
else gen:=genunknown;
end else if length(f)>2 then begin
t:=f[length(f)]+f[length(f)];
if (t='ов') or (t='ий') then gen:=masculine
else if (t='ва') or (t='ий') then gen:=masculine
else gen:=genunknown;
end else
gen:=genunknown;
result:=SurnameInGenitiveCase(gen,f)+' '+NameInGenitiveCase(gen,i)+' '+PatronymicInGenitiveCase(gen,o);
end;

На foxpro

Источник: http://forum.vingrad.ru/forum/s/9d2ea4b47c82f5731dd6ca2f07b09550/topic-238659/anchor-entry1715662/0.html

	
FUNCTION Getpol (sss)
rrr=''
SSS=' '+ALLTRIM(UPPER(SSS))+' '
DO CASE g
CASE GETWORDCOUNT(SSS)=4
 IF 'ОГЛЫ'$SSS
 RRR='М'
 ENDIF
 IF 'КЫЗЫ'$SSS
 RR='Ж'
 ENDIF
CASE GETWORDCOUNT(SSS)=3
 IF 'ИЧ '$GETWORDNUM(SSS,3)+' '
 RRR='М'
 ENDIF
 IF 'НА '$GETWORDNUM(SSS,3)+' '
 RRR='Ж'
 ENDIF
 IF EMPTY(RRR)
  IF 'ЕВ '$GETWORDNUM(SSS,1)+' ' OR 'ОВ '$GETWORDNUM(SSS,1)+' ' OR 'ИН '$GETWORDNUM(SSS,1)+' ' OR 'ИЙ '$GETWORDNUM(SSS,1)+' '
  RRR='М'
  ENDIF
  IF 'ЕВА '$GETWORDNUM(SSS,1)+' ' OR 'ОВА '$GETWORDNUM(SSS,1)+' ' OR 'ИНА '$GETWORDNUM(SSS,1)+' ' OR 'АЯ '$GETWORDNUM(SSS,1)+' '
  RRR='Ж'
  ENDIF
 ENDIF
CASE GETWORDCOUNT(SSS)<3
 IF 'ЕВ '$GETWORDNUM(SSS,1)+' ' OR 'ОВ '$GETWORDNUM(SSS,1)+' ' OR 'ИН '$GETWORDNUM(SSS,1)+' ' OR 'ИЙ '$GETWORDNUM(SSS,1)+' '
  RRR='М'
  ENDIF
 IF 'ЕВА '$GETWORDNUM(SSS,1)+' ' OR 'ОВА '$GETWORDNUM(SSS,1)+' ' OR 'ИНА '$GETWORDNUM(SSS,1)+' ' OR 'АЯ '$GETWORDNUM(SSS,1)+' '
  RRR='Ж'
  ENDIF
ENDCASE
RETURN rrr
ENDFUNC

Систематизация распознавания пола и этноса по ФИО

Источник: http://ivan.begtin.name/2010/05/04/%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D0%B0%D1%82%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F-%D1%80%D0%B0%D1%81%D0%BF%D0%BE%D0%B7%D0%BD%D0%B0%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F-%D0%BF%D0%BE%D0%BB%D0%B0-%D0%B8/

Какое-то время назад я эту тему поднимал в посте «Распознавание национальности по имени» – http://ivbeg.livejournal.com/119528.html

Но там было нечто вроде результатов экспериментов, сейчас же затрону тему систематизации того как можно обрабатывать ФИО и какую информацию можно на основе ФИО извлечь.

Предыстория этого текста исключительно практическая, поскольку я очень много с данными работаю, то периодически возникают задачи по тому как обогатить, улучшить, извлечь и отклассифицировать данные. Так, например, анализ ФИО даёт возможность добавить как минимум 2 новых среза – гендерный и этнический (более правильное название определения национальности).

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

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

Почему систематизация ? Лично я придерживаюсь того мнения что систематизации мало не бывает. Иногда это вредит – поскольку приводит к значительному углублению в детали, но чаще это помогает поскольку позволяет лучше понять предметную область и прежде чем приступать к воплощению в коде каких-либо алгоритмов – понять, с чем же имеем дело и как обеспечить простоту анализа данных в сочетании с максимально возможным охватом.

В случае ФИО, начало систематизации начинается с шаблонов.

Шаблоны

Форм записи ФИО не очень много и они вполне поддаются систематизации и укладываются в несколько шаблонов которые, в свою очередь, разделяются на несколько элементов.

Этих элементов немного и их можно перечислить:

s – Фамилия (surname)

f – Личное имя (first name)

m – Отчество (midname)

S – Однобуквенная запись фамилии

F – Однобуквенная запись имени

M – Обнобуквенная запись отчества.

Далее при анализе ФИО я буду исходить из того что ФИО – это не только фамилия, имя и отчество, но в реальной жизни это гораздо большее число форм написания того же.

При этом у использования этих элементов есть свои особенности в частности есть устоявшиеся сочетания в которых они присутствуют. Далее я приведу перечень шаблонов для определения этих сочетаний:

sfm – Фамилия, имя и отчество. Например, Пилипенко Мария Геннадьевна

fms – Имя, Отчество, Фамилия. Например, Александр Аронович Хромов

sFM – Фамилия и по первой букве от имени и отчества. Например, Васильев И. И. или Минниханов Р Е

FMs – первые буквы от имени и отчества и фамилия полностью. Пример: А. Ю. Макаренко, Н.Г. Буранов

sfM – фамилия и имя полностью и первая буква от отчества. Примеры: Ефимов Борис А., Карманова Мария В.

Fs – Первая буква имени и фамилия. Например, А. Румянцев или В Ручкин .

sF – фамилия полностью и первая буква от имени. Примеры: Борисов Г., Рахмонова Е.

s – только фамилия. Например: Хазанов, Минниханов, Дудкина, Малых

fs - имя, фамилия. Например: Арут Карапетян, Борис Рыбин

sf – фамилия, имя. Например: Климов Максим, Мирных Алексей, Дудяк Елена

fm – имя, отчество. Например: Иван Петрович, Василий Аркадьевич, Рахиль Альбертовна

f – личное имя. Примеры: Иван, Петр, Алексей, Равиль, Аслан и т.д.

SFM – по первой букве от фамилии, имени, отчества. Примеры: В.Р.Е, Е.Н.М.

Является ли этот список шаблонов исчерпывающим? Весьма вероятно что нет, однако все остальные случаи будут достаточно редкими чтобы рассматривать их как исключения и систематизировать именно с точки зрения исключений.

Правила разбора ФИО

Когда известны все основные шаблоны и есть входящий поток для разбора можно приступать к описанию логики анализа.

Прежде чем определять пол персоны или этнос важно разложить ФИО на элементы и для этой цели необходимо определить каким шаблоном ФИО написано. Как это сделать?

1. Вначале разбить ФИО на элементы исходя из того что разделителями могут выступать пробелы и точки.

2. Определяется количество частей после чего идёт ветвление на проверку по шаблонам. Если 1 часть (1 слово) – то шаблон s или f. Если две части, то sf, fm, fs, sF или Fs

3. Для ФИО из 3-х частей проводится простая проверка не состоят ли какие-либо части из одной буквы. Если да и более двух, то быстро определяются такие шаблоны как SFM, sFM и FMs

4. Далее как определить какая из частей каким типом элементов является. Есть два способа и их комбинация.

Способ 1. Базы имён, фамилий и отчеств

Всего уникальных имён сравнительно немного – десятки тысяч. То же самое с отчествами. Сложнее с фамилиями – их могут быть сотни тысяч и миллионы. Однако при наличии значительных массивов возможно создание баз имён, фамилий и отчеств, а далее ручная и полуавтоматическая разметка по полу и этносу.

Способ 2. Регулярные выражения

Для отчеств – окончания на -вич и -вна. Для фамилий выражений больше. Например, таки как:

 ^(.*)(о|е|ё)в$, ^(.*)швили$ 

и так далее, несколько десятков. А также есть набор выражений для имён, но там всё несколько сложнее и это отдельная тема.

Для каждого из выражений может быть сопоставление его с полом или этнической группой.

Способ 3. Использование баз и выражений совместно

Если запись находится в базе – исходить их признаков в базе, если нет – применять разметку регулярным выражением.

-

5. После идентификация шаблона мы имеем его описание и, если его идентификация потребовала определения типа элементов, то и предположения о поле и, возможно, этносе персоны. Для полноты картины необходимо проверить все остальные элементы регулярными выражениями и/ли по базам.

6. В конечном итоге результатом являются:

- выявленный формат шаблона

- размеченные элементы (фамилия, имя, отчество)

А также, или все имеющиеся или один производный признак пола и, при возможности определения, этноса.

Или же возврат, и производного, и всех признаков. Об особенностях определения признаков в следующем пункте.

Особенности

Все было бы очень просто если бы не некоторые особенности которые важно помнить и учитывать.

1. Есть множество случаев когда пол определить невозможно даже определив шаблон и отдельные элементы. Связано это не с несовершенством методов проверки, а с тем что далеко не всегда информация о поле содержится в ФИО. Вот несколько примеров: Малых А.А. – имя и отчество присутствуют только в виде первых букв, а фамилия Малых является универсальной и может принадлежать, как женщине, так и мужчине. Точно также с фамилиями на -ко, -их и множестве других. Фактически во всех случаях шаблонов sFM, FMs, Fs, sF и s у нас недостаточно элементов несущих информацию и определение ограничено имеющейся информацией. В виду этого результатом метода по определению пола по ФИО могут быть 4 варианта ответа: женский, мужской, универсальный и неизвестно.

2. Есть множество региональной специфики в том что касается написания имён и отчеств. В частности в азербайжанских казахских ФИО часто присутствует «Оглы» или «Кызы». Например, Асланов Ази Ахад оглы

3. Много специфики в именах используемых в национальных республиках России и бывшем СССР. Точность распознавания будет зависеть от наличия датасетов по регионам.

4. Описанный подход не охватывает случаи намерянных и случайных искажений. Например, когда вместо точки используют запятую или указывают ФИО вроде «Гадя Петрович Хренова». А также случаи с опечатками – это несколько более сложная, но не сверхсложная задача.

5. Определения этноса задача сложная, в первую очередь, в виду значительных объёмов классифицируемой информации. Фактически её можно разделить на принципы определения различных этнических особенностей в ФИО разных народов. Например, окончания фамилий на «-ян» у армян или «-дзе» и «-швили» у грузин. А также на основе баз имён разных народов. Однако есть много случаев когда определить этнос сложно поскольку имя может указывать лишь на то из какого языка оно происходит. А в некоторых случаях имена могут иметь множественное значение. Например имя Артур – весьма популярно среди армян и это армянское имя переводящееся как «свет истины» и одновременно это нередкое современное имя в России среди русских.

Примеры

Собственно всё вышеперечисленное какое-то время я реализовал довольно давно в виде довольно простого закрытого веб-сервиса который на входе кушает текст, а на выходе выдаёт JSON с результатами. Работает это всё настолько просто назвать это алгоритмом у меня язык не поворачивается – просто «полезная штука», ничего более.

Вот несколько примеров.

Текст: Бегтин И.В.

Разбор в формате JSON:

{‘format’: ’sFM’, ‘gender’: ‘m’, ’sn’: u’Бегтин’, ‘fn_s’: u’И’, ‘text’: u’Бегтин И.В.’, ‘mn_s’: u’В’, ‘parsed’: True}

Текст: Иван Викторович Бегтин

Разбор в формате JSON:

{‘format’: ‘fms’, ‘gender’: u’m', ‘mn’: u’Викторович’, ’sn’: u’Бегтин’, ‘text’: u’Бегтин Иван Викторович’, ‘parsed’: True, ‘fn’: u’Иван’}

Где: fn – имя, sn – фамилия, mn – отчество, fn_s – первая буква имени, format – выявленный формат описания ФИО, parsed – флаг что формат был определён, gender – пол в виде одного из признаков m, f, u и «-» если определение пола не прошло.

Нет только признаков этноса, поскольку сейчас они присутствуют только для имён

Статистика

В качестве небольшого дополнения приведу некоторые статистические наблюдения.

Для проверки точности я взял небольшой массив примерно в 5 600 000 неуникальных записей из публичных официальных документов. А то есть с частыми повторениями одного и того же ФИО, но в разных формах. Например: где-то упоминается: Кудрявцев Е.В., где-то Кудрявцев Евгений, где-то Кудрявцев Евгений Викторович и так далее.

В результате сформировалась следующая таблица частот использования тех или иных форм записи.

Шаблон Частота sfm 49,38% sFM 35,71% FMs 13,42% fms 1,24% sF 0,069% sf 0,055% Fs 0,038% sfM 0,029% s 0,026% fs 0,0010% f 0.0007%

Фактически можно увидеть что при 4 основных написания – sfm, sFM, FMs и fms лидируют по частоте встречаемости. Но, как я упоминал ранее, здесь есть специфика в официальности. Если же анализировать другие массивы, то распределение шаблонов по популярности будет иным.

В качестве резюме

В общем-то разбор ФИО – это довольно простой пример на уровне «систематизации очевидного». Куда сложнее задачи по разбору адресов или, например, товарных позиций. Но ничего неразрешимого нет при условии последовательного упрощения и шаблонизации форматов представления, иногда многоуровневой.

Источник: http://ivan.begtin.name/2010/05/04/%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D0%B0%D1%82%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F-%D1%80%D0%B0%D1%81%D0%BF%D0%BE%D0%B7%D0%BD%D0%B0%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F-%D0%BF%D0%BE%D0%BB%D0%B0-%D0%B8/