A simple Python module for parsing human names into their individual components

Overview

Name Parser

Build Status PyPI PyPI version Documentation

A simple Python (3.2+ & 2.6+) module for parsing human names into their individual components.

  • hn.title
  • hn.first
  • hn.middle
  • hn.last
  • hn.suffix
  • hn.nickname
  • hn.surnames (middle + last)

Supported Name Structures

The supported name structure is generally "Title First Middle Last Suffix", where all pieces are optional. Comma-separated format like "Last, First" is also supported.

  1. Title Firstname "Nickname" Middle Middle Lastname Suffix
  2. Lastname [Suffix], Title Firstname (Nickname) Middle Middle[,] Suffix [, Suffix]
  3. Title Firstname M Lastname [Suffix], Suffix [Suffix] [, Suffix]

Instantiating the HumanName class with a string splits on commas and then spaces, classifying name parts based on placement in the string and matches against known name pieces like titles and suffixes.

It correctly handles some common conjunctions and special prefixes to last names like "del". Titles and conjunctions can be chained together to handle complex titles like "Asst Secretary of State". It can also try to correct capitalization of names that are all upper- or lowercase names.

It attempts the best guess that can be made with a simple, rule-based approach. Its main use case is English and it is not likely to be useful for languages that do not conform to the supported name structure. It's not perfect, but it gets you pretty far.

Installation

pip install nameparser

If you want to try out the latest code from GitHub you can install with pip using the command below.

pip install -e git+git://github.com/derek73/python-nameparser.git#egg=nameparser

If you need to handle lists of names, check out namesparser, a compliment to this module that handles multiple names in a string.

Quick Start Example

>>> from nameparser import HumanName
>>> name = HumanName("Dr. Juan Q. Xavier de la Vega III (Doc Vega)")
>>> name
<HumanName : [
    title: 'Dr.'
    first: 'Juan'
    middle: 'Q. Xavier'
    last: 'de la Vega'
    suffix: 'III'
    nickname: 'Doc Vega'
]>
>>> name.last
'de la Vega'
>>> name.as_dict()
{'last': 'de la Vega', 'suffix': 'III', 'title': 'Dr.', 'middle': 'Q. Xavier', 'nickname': 'Doc Vega', 'first': 'Juan'}
>>> str(name)
'Dr. Juan Q. Xavier de la Vega III (Doc Vega)'
>>> name.string_format = "{first} {last}"
>>> str(name)
'Juan de la Vega'

The parser does not attempt to correct mistakes in the input. It mostly just splits on white space and puts things in buckets based on their position in the string. This also means the difference between 'title' and 'suffix' is positional, not semantic. "Dr" is a title when it comes before the name and a suffix when it comes after. ("Pre-nominal" and "post-nominal" would probably be better names.)

>>> name = HumanName("1 & 2, 3 4 5, Mr.")
>>> name
<HumanName : [
    title: ''
    first: '3'
    middle: '4 5'
    last: '1 & 2'
    suffix: 'Mr.'
    nickname: ''
]>

Customization

Your project may need some adjustment for your dataset. You can do this in your own pre- or post-processing, by customizing the configured pre-defined sets of titles, prefixes, etc., or by subclassing the HumanName class. See the full documentation for more information.

Full documentation

Contributing

If you come across name piece that you think should be in the default config, you're probably right. Start a New Issue and we can get them added.

Please let me know if there are ways this library could be structured to make it easier for you to use in your projects. Read CONTRIBUTING.md for more info on running the tests and contributing to the project.

GitHub Project

https://github.com/derek73/python-nameparser

Comments
  • Feature: Add first and middle name(s) initials

    Feature: Add first and middle name(s) initials

    Initials can be quite important when comparing two names in order to determine whether they are the same or not. I have added a property to HumanName called initials which holds the first letters of the first name and the middle names. The list-version of the property is a list of single characters. The string-version is build from the list and has a dot and space after each character.

    Some examples:

    >>> HumanName("John Doe")
    <HumanName : [
    	title: '' 
    	initials: 'J.' 
    	first: 'John' 
    	middle: '' 
    	last: 'Doe' 
    	suffix: ''
    	nickname: ''
    ]>
    >>> HumanName("Dr. Juan Q. Xavier Velasquez y Garcia")
    <HumanName : [
    	title: 'Dr.' 
    	initials: 'J. Q. X.' 
    	first: 'Juan' 
    	middle: 'Q. Xavier' 
    	last: 'Velasquez y Garcia' 
    	suffix: ''
    	nickname: ''
    ]>
    >>> HumanName("Doe, John Boris D.")
    <HumanName : [
    	title: '' 
    	initials: 'J. B. D.' 
    	first: 'John' 
    	middle: 'Boris D.' 
    	last: 'Doe' 
    	suffix: ''
    	nickname: ''
    ]>
    >>> HumanName("Doe, John Boris D.").initials
    'J. B. D.'
    >>> HumanName("Doe, John Boris D.").initials_list
    ['J', 'B', 'D']
    

    Since the property is derived from the first and middle names, it will not be counted in the len function nor will it be displayed in the str function.

    Each time the first or middle names are updated using the setter, the initials are updated as well. The initial creation of the initials is executed in the post_process phase.

    I have added tests and updated the documentation where needed.

    I hope this pull request is in line with the quality requirements and vision of the library. The changes should be backwards compatible, but please let me know if I have missed anything!

    enhancement 
    opened by rinkstiekema 20
  • Parsing title and last name, e.g.

    Parsing title and last name, e.g. "Mr XXX" should be last name, not first name

    Love this library - very useful.

    However, I've noticed that parsing names in the format Prefix Lastname (e.g. Mr Magoo) parse with a blank name.last and the last name in the first name position (e.g. name.first == Magoo, name.last == ''). I think this should be the other way round!

    I may have time to fix this in your code later, but for now i'm using the following kludge to make it work in my code...

    if name.title != '': if name.last == '': name.last = name.first name.first = ''

    enhancement 
    opened by danhartropp 16
  • Wrong capitalized letter in Portuguese names

    Wrong capitalized letter in Portuguese names

    First of all, congrats for the great project.

    I have found a small issue related to Portuguese names. By running the following code:

    from nameparser import HumanName
    name = HumanName('joao da silva do amaral de souza')
    name.capitalize()
    str(name)
    

    I get the following result:

    'Joao da Silva Do Amaral de Souza'

    when it should be:

    'Joao da Silva do Amaral de Souza'

    The d from do should be lowercase.

    enhancement 
    opened by kelvins 10
  • Option to get None instead of empty string

    Option to get None instead of empty string

    Hey,

    is there an option to get None instead of an empty string for the components? E.g.

    >>> name = HumanName("1 & 2, 3 4 5, Mr.")
    >>> name.title
    None
    >>>name.first
    '3'
    
    enhancement 
    opened by Xennis 9
  • error on two joiner words

    error on two joiner words

    If a name contains two joiner words one after another, s.a. "John of the Doe", get: HumanName:ERROR:parser.py:Couldn't find 'The' in pieces. error.

    bug 
    opened by daryanypl 7
  • possibly incorrect parsing of

    possibly incorrect parsing of "grand"

    Just noticed that if I parse "Grand Rounds", it returns:

    >>> name
    <HumanName : [
    	title: 'Grand' 
    	first: '' 
    	middle: '' 
    	last: 'Rounds' 
    	suffix: ''
    	nickname: ''
    ]>
    

    Kinda odd no?

    enhancement wontfix probabilistic 
    opened by thehesiod 6
  • a few common special cases

    a few common special cases

    Sister Souljah -- "Sister" is more of a title than last name. His Holiness the Dalai Lama -- "His Holiness" -- the two words together is the title. Bob Jones, composer
    Bob Jones, author Bob Jones, compositeur -- (French for composer)

    Here's the code I used:

            name = HumanName('Sister Souljah')
            library_sort_name = u' '.join([name.first, name.middle, name.suffix, name.nickname, name.title])
            if name.last:
                library_sort_name = u''.join([name.last, ", ", library_sort_name])
            print "library_sort_name=%s" % library_sort_name
            
            name = HumanName('His Holiness the Dalai Lama')
            library_sort_name = u' '.join([name.first, name.middle, name.suffix, name.nickname, name.title])
            if name.last:
                library_sort_name = u''.join([name.last, ", ", library_sort_name])
            print "library_sort_name=%s" % library_sort_name
            
            name = HumanName('Bob Jones, author')
            library_sort_name = u' '.join([name.first, name.middle, name.suffix, name.nickname, name.title])
            if name.last:
                library_sort_name = u''.join([name.last, ", ", library_sort_name])
            print "library_sort_name=%s" % library_sort_name
            
            name = HumanName('Bob Jones, compositeur')
            library_sort_name = u' '.join([name.first, name.middle, name.suffix, name.nickname, name.title])
            if name.last:
                library_sort_name = u''.join([name.last, ", ", library_sort_name])
            print "library_sort_name=%s" % library_sort_name
    
    
    enhancement 
    opened by daryanypl 6
  • First name Van (which is also sometimes a prefix) not handled correctly

    First name Van (which is also sometimes a prefix) not handled correctly

    >>> from nameparser import HumanName
    ... HumanName('Van Nguyen')
    0: <HumanName : [
        title: '' 
        first: 'Van Nguyen' 
        middle: '' 
        last: '' 
        suffix: ''
        nickname: ''
    ]>
    >>> import nameparser
    >>> nameparser.VERSION
    1: (0, 3, 3)
    >>>
    
    bug 
    opened by htoothrot 6
  • Can't handle Japanese names

    Can't handle Japanese names

    name = nameparser.HumanName("鈴木太郎")

    name Traceback (most recent call last): File "", line 1, in UnicodeEncodeError: 'ascii' codec can't encode characters in position 36-39: ordinal not in range(128)

    Also: the concept of "last name" and "first name" isn't valid for Chinese, Japanese, Korean (CJK) names.

    bug 
    opened by pludemann 5
  • Judge-related titles not parsing

    Judge-related titles not parsing

    Hey -

    First off, awesome package. I've been working with a dataset of ~3000 judges and associated titles, and noticed nameparser doesn't pick most (well, any) of them up. Below is the filtered list with at least a few examples/variations on each. I'm happy to do the changes if you'd like. Let me know.

    common

    Magistrate Judge John F. Forster, Jr Magistrate Judge Joaquin V.E. Manibusan, Jr Magistrate-Judge Elizabeth Todd Campbell Mag-Judge Harwell G Davis, III Mag. Judge Byron G. Cudmore Chief Judge J. Leon Holmes Chief Judge Sharon Lovelace Blackburn Judge James M. Moody Judge G. Thomas Eisele Judge Callie V. S. Granade Judge C Lynwood Smith, Jr Senior Judge Charles R. Butler, Jr Senior Judge Harold D. Vietor Senior Judge Virgil Pittman
    Honorable Terry F. Moorer Honorable W. Harold Albritton, III Honorable Judge W. Harold Albritton, III Honorable Judge Terry F. Moorer Honorable Judge Susan Russ Walker Hon. Marian W. Payson Hon. Charles J. Siragusa

    rare

    US Magistrate Judge T Michael Putnam Designated Judge David A. Ezra Sr US District Judge Richard G Kopf

    enhancement 
    opened by end0 5
  • Ph.D., Esq., M.D., C.F.P., etc. are titles, not suffixes

    Ph.D., Esq., M.D., C.F.P., etc. are titles, not suffixes

    Moving the previous issue from the Google Code because I like the idea and would like to implement it, someday. Originally posted by jayqhacker, Feb 7, 2012.


    Ph.D., Esq., M.D. and other titles are classified as suffixes. This is perhaps convenient for parsing, since they appear at the end of a name, but they are in fact titles. A suffix distinguishes people and is part of your legal name; a title does not and (in most countries) is not. "J. Smith Jr." and "J. Smith Sr." are certainly different people, whereas "J. Smith", "J. Smith, PhD" and "J. Smith, MD" may or may not be.

    I propose titles end up in the .title field, and suffices end up in the .suffix field.

    Name parsing is a hard problem; ultimately I think you'd want a statistical, machine learning approach, but you can probably get pretty far with rules.

    The two issues are: 1) some suffixes are part of your name, some aren't; and 2) some titles come before your name, some after.

    You could solve both by splitting titles into pre- and post-titles, and making suffixes just ('jr','sr','2','i','ii','iii','iv','v').


    Project Member #3 derek73

    I played with adding a new list to keep track of titles that were added at the end. If we treat the suffixes as a definitive and complete list, then we can assume anything else is a title. The initials "i" and "v" are problematic, but we could probably assume that they are initials in the case of "John V".

    I like the idea of separating out the parts of the name that definitely signify another person, and your definition of suffix. Thinking about it, I guess a suffix always comes directly after the name? Like you wouldn't have "John Doe, Phd, Jr". Also the case of having 2 suffixes seems somewhat remote, e.g. "'Smith, John E, III, Jr'"? So I guess that would make the patterns look something like this.

    # no commas:      title first middle middle middle last suffix|title_suffix title_suffix
    # suffix comma:   title first middle last, suffix|title_suffix [, title_suffix]
    # lastname comma: last, title first middles[,] suffix|title_suffix [,title_suffix]
    
    SUFFIXES = set((
        'jr','sr','2','i','ii','iii','iv','v',
    ))
    
    TITLE_SUFFIXES = set((
        'phd','md','esquire','esq','clu','chfc','cfp',
    ))
    

    I got as far as finding that equality test would need to be updated. It got me wondering if perhaps we should change the equality test, per your example, to test that ' '.join(first, middle, last, suffix) are the same. Perhaps its easy enough for someone to test if unicode() representations are equal on their own if they want titles too. Or maybe that's too smart.


    That sounds like a reasonable approach. I don't personally use equality, but you might consider having it do the "dumb" least-surprise exact comparison, and adding a similarity method that returns a float in 0.0 - 1.0, eventually aiming for something like the probability that these two names reference the same person.

    Also, watch out for "King John V." ;)

    enhancement wontfix probabilistic 
    opened by derek73 5
  • Issue in names that contain comma(,) and has more than 3 words.

    Issue in names that contain comma(,) and has more than 3 words.

    Hi Derek, I have a usecase where I need to parse names containing comma(,), but the library seems to work differently in this case. from nameparser import HumanName as hm #1) here first name should be-E ANNE and lastname should be-LEONARDO hm("E Anne D,Leonardo") <HumanName : [ title: '' first: 'Leonardo' middle: '' last: 'E Anne D' suffix: '' nickname: '' ]>

    #2) here first name should be-Marry Ann and lastname should be-Luther hm("Mary Ann H,Luther") <HumanName : [ title: '' first: 'Luther' middle: '' last: 'Mary Ann H' suffix: '' nickname: '' ]>

    Even if I removed the comma from the name, it has different output.

    hm("Mary Ann H Luther") <HumanName : [ title: '' first: 'Mary' middle: 'Ann H' last: 'Luther' suffix: '' nickname: '' ]>

    opened by da-sbarde 1
  • Capitalizing Suffixes

    Capitalizing Suffixes

    I believe acronym-based suffixes are being incorrectly capitalized.

    > python3
    Python 3.8.10 (default, Jun 22 2022, 20:18:18) 
    [GCC 9.4.0] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import nameparser
    >>> nameparser.__version__
    '1.1.1'
    >>> n = nameparser.HumanName('GREGORY HOUSE M.D.')
    >>> n
    <HumanName : [
    	title: '' 
    	first: 'GREGORY' 
    	middle: '' 
    	last: 'HOUSE' 
    	suffix: 'M.D.'
    	nickname: ''
    ]>
    >>> n.capitalize()
    >>> n
    <HumanName : [
    	title: '' 
    	first: 'Gregory' 
    	middle: '' 
    	last: 'House' 
    	suffix: 'M.d.'
    	nickname: ''
    ]>
    >>> 
    
    

    I believe the suffix should be 'M.D.'

    bug 
    opened by DLu 0
  • output string formatting space before suffix if suffix does not exist

    output string formatting space before suffix if suffix does not exist

    I have this name: John Smith I'd like to reformat the name to look like this: Smith, John

    I've set the formatting I'd like to use:

    from nameparser.config import CONSTANTS
    CONSTANTS.string_format = "{last} {suffix}, {title} {first} ({nickname}) {middle}"
    

    The result I get is: Smith , John due to the space that precedes {suffix} in my string_format.

    However, I'd like the suffix to follow the last name if it ever occurs. Does your package allow for the trimming of space if no suffix exists, or should I implement this on my end?

    Apologies if this is already addressed in the documentation! Thank you!

    enhancement 
    opened by jocelynpender 0
  • Problem parsing name with , V

    Problem parsing name with , V

    nameparser version 1.1.1

    When I use HumanName with the string "John W. Ingram, V", it can't parse correctly but if I remove the comma, it works. Also, if I try using IV (4th) instead of V (5th), then it works with the comma so I think even though V seems to be recognized in the documentation, it isn't fully working.

    from nameparser import HumanName
    >>> name = HumanName("John W. Ingram, V")
    >>> name
    <HumanName : [
    	title: '' 
    	first: 'V' 
    	middle: '' 
    	last: 'John W. Ingram' 
    	suffix: ''
    	nickname: ''
    ]>
    >>> name = HumanName("John W. Ingram V")
    >>> name
    <HumanName : [
    	title: '' 
    	first: 'John' 
    	middle: 'W.' 
    	last: 'Ingram' 
    	suffix: 'V'
    	nickname: ''
    ]>
    
    
    bug 
    opened by pusateri 0
  • Weak Arabic Name handling

    Weak Arabic Name handling

    The library does not handle Arabic names well, even the most common patterns. I'm no expert on the topic, but I'm Arabic and know the common patterns.

    Compound Names My first name is "Mohamad Ali", but the library identifies "Ali" as my middle name. Arabic full names of the form "Mohamad X Surname" are almost always meant to have "Mohamad X" as a first name (with exceptions such as when X is "El" or "Al", in which case the surname is compound with the first word being "El" or "Al"). Other exceptions are "Bin" (the library handles these correctly). Examples: Mohamad Khalil, Mohamad Amin, Mohamad Ali, Mohamad El Amin, Mohamad Bin Salman, etc...

    Well-known Surname Suffixes Some names like "Mohamad Zeineddine" can be written as "Mohamad Zein El Dine". Here the first name is Mohamad and the surname is "Zein El Dine" which is equivalent to "Zeineddine". "El Dine"/"eddine" is an extremely common suffix to have in Arabic surnames (e.g. Zeineddine, Alameddine, Charafeddine, Safieddine, Saifeddine, etc...). Other suffixes like "-allah"/"-ullah"/"-ollah" are extremely common as well (e.g., Nasrallah). This is to say that "El Dine" and "Allah" are almost always the 2nd part of a surname (at least one more word is needed on the left to complete the surname)

    Middle names hardly exist An Arabic-looking name is a good hint that there is no middle name. Arabic cultures adopt chaining of names instead of middle names (first name, followed by father's name, followed by father's father's name, etc..., and then the surname).

    Edit: Honestly, the Wikipedia page discusses this really well https://en.wikipedia.org/wiki/Arabic_name

    enhancement 
    opened by us88 1
Releases(v1.1.2.1)
基于Pytex的数学建模工具,实现将md文件转换成pdf/tex文档的前后端

Pytex-for-MCM 基于Pytex的数学建模工具,实现将md文件转换成pdf/tex文档的前后端。

3 May 17, 2021
Phone Number formatting for PlaySMS Platform - BulkSMS Platform

BulkSMS-Number-Formatting Phone Number formatting for PlaySMS Platform - BulkSMS Platform. Phone Number Formatting for PlaySMS Phonebook Service This

Edwin Senunyeme 1 Nov 08, 2021
ChirpText is a collection of text processing tools for Python 3.

ChirpText is a collection of text processing tools for Python 3. It is not meant to be a powerful tank like the popular NTLK but a small package which

Le Tuan Anh 5 Nov 30, 2022
Find a Doc is a free online resource aimed at helping connect the foreign community in Japan with health services in their native language.

Find a Doc - Localization Find a Doc is a free online resource aimed at helping connect the foreign community in Japan with health services in their n

Our Japan Life 18 Dec 19, 2022
Fuzz a language by mixing up only few words.

afasi Fuzz a language by mixing up only few words. Status Beta. Note: The default branch is default. Use Examples Version General Help Translate Help

Stefan Hagen 2 Dec 14, 2022
StealBit1.1 and earlier strings and config extraction scripts

StealBit1.1 and earlier scripts Use strings_decryptor.py to extract RC4 encrypted strings from a StealBit1.1 sample(s). Use config_extractor.py to ext

Soolidsnake 5 Dec 29, 2022
Meeting, rendezvous, confluence (Finnish kohtaaminen) mark up, down, and up again.

kohtaaminen Meeting, rendezvous, confluence (Finnish kohtaaminen) mark up, down, and up again. Given a zip file containing a tree of html and media fi

Stefan Hagen 2 Dec 14, 2022
This repository contains scripts to control a RGB text fan attached to a Raspberry Pi.

RGB Text Fan Controller This repository contains scripts to control a RGB text fan attached to a Raspberry Pi. Setup The Raspberry Pi and RGB text fan

Luke Prior 1 Oct 01, 2021
Hamming code generation, error detection & correction.

Hamming code generation, error detection & correction.

Farhan Bin Amin 2 Jun 30, 2022
汉字转拼音(pypinyin)

汉字拼音转换工具(Python 版) 将汉字转为拼音。可以用于汉字注音、排序、检索(Russian translation) 。 基于 hotoo/pinyin 开发。 Documentation: http://pypinyin.rtfd.io/ GitHub: https://github.co

Huang Huang 4.2k Jan 03, 2023
Hotpotato is a recipe portfolio App that assists users to discover and comment new recipes.

Hotpotato Hotpotato is a recipe portfolio App that assists users to discover and comment new recipes. It is a fullstack React App made with a Redux st

Nico G Pierson 13 Nov 05, 2021
JSON and CSV data for Swahili dictionary with over 16600+ words

kamusi JSON and CSV data for swahili dictionary with over 16600+ words. This repo consists of data from swahili dictionary with about 16683 words toge

Jordan Kalebu 8 Jan 13, 2022
Word-Generator - Generates meaningful words from dictionary with given no. of letters and words.

Meaningful Word Generator Generates meaningful words from dictionary with given no. of letters and words. This might be useful for generating short li

Mohammed Rabil 1 Jan 01, 2022
Etranslate is a free and unlimited python library for transiting your texts

Etranslate is a free and unlimited python library for transiting your texts

Abolfazl Khalili 16 Sep 13, 2022
Hspell, the free Hebrew spellchecker and morphology engine.

Hspell, the free Hebrew spellchecker and morphology engine.

16 Sep 15, 2022
Auto translate Localizable.strings for multiple languages in Xcode

auto_localize Auto translate Localizable.strings for multiple languages in Xcode Usage put your origin Localizable.strings file in folder pip3 install

Wesley Zhang 13 Nov 22, 2022
A python tool one can extract the "hash" from a WINDOWS HELLO PIN

WINHELLO2hashcat About With this tool one can extract the "hash" from a WINDOWS HELLO PIN. This hash can be cracked with Hashcat, more precisely with

33 Dec 05, 2022
一个可以可以统计群组用户发言,并且能将聊天内容生成词云的机器人

当前版本 v2.2 更新维护日志 更新维护日志 有问题请加群组反馈 Telegram 交流反馈群组 点击加入 演示 配置要求 内存:1G以上 安装方法 使用 Docker 安装 Docker官方安装

机器人总动员 117 Dec 29, 2022
Microsoft's Cascadia Code font customized to my liking.

Microsoft's Cascadia Code font customized to my liking. Also includes some simple batch patch and bake scripts to batch patch glyphs and bake font features into fonts!

Frederik List 3 Jan 29, 2022
Returns unicode slugs

Python Slugify A Python slugify application that handles unicode. Overview Best attempt to create slugs from unicode strings while keeping it DRY. Not

Val Neekman 1.3k Jan 04, 2023