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)
An implementation of figlet written in Python

All of the documentation and the majority of the work done was by Christopher Jones ([emai

Peter Waller 1.1k Jan 02, 2023
Simple python program to auto credit your code, text, book, whatever!

Credit Simple python program to auto credit your code, text, book, whatever! Setup First change credit_text to whatever text you would like to credit

Hashm 1 Jan 29, 2022
Question answering on russian with XLMRobertaLarge as a service

QA Roberta Ru SaaS Question answering on russian with XLMRobertaLarge as a service. Thanks for the model to Alexander Kaigorodov. Stack Flask Gunicorn

Gladkikh Prohor 21 Jul 04, 2022
Utility for Text Normalisation or Inverse Normalisation

Text Processor Text Normalisation or Inverse Normalisation for Indonesian, e.g. measurements "123 kg" - "seratus dua puluh tiga kilogram" Currency/Mo

Cahya Wirawan 2 Aug 11, 2022
A simple text editor for linux

wolf-editor A simple text editor for linux Installing using Deb Package Download newest package from releases CD into folder where the downloaded acka

Focal Fossa 5 Nov 30, 2021
A working (ish) python script to convert text to a gradient.

verticle-horiontal-gradient-script A working (ish) python script to convert text to a gradient. This script is poorly made with the well known python

prmze 1 Feb 20, 2022
Text to ASCII and ASCII to text

Text2ASCII Description This python script (converter.py) contains two functions: encode() is used to return a list of Integer, one item per character

4 Jan 22, 2022
text-to-speach bot - You really do NOT have time for read a newsletter? Now you can listen to it

NewsletterReader You really do NOT have time for read a newsletter? Now you can listen to it The Newsletter of Filipe Deschamps is a great place to re

ItanuRomero 8 Sep 18, 2021
Migrates translations to the REDCap native Multi-Language Management system

Automates much of the process of moving translations from the old Multilingual external module to the newer built-in Multi-Language Management (MLM) page.

UCI MIND 3 Sep 27, 2022
A neat little program to read the text from the "All Ten Fingers" program, and write them back.

ATFTyper A neat little program to read the text from the "All Ten Fingers" program, and write them back. How does it work? This program uses the Pillo

1 Nov 26, 2021
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
Correcting typos in a word based on the frequency dictionary

Auto-correct text Correcting typos in a word based on the frequency dictionary. This algorithm is based on the distance between words according to the

Anton Yakovlev 2 Feb 05, 2022
RSS Reader application for the Emacs Application Framework.

EAF RSS Reader RSS Reader application for the Emacs Application Framework. Load application (add-to-list 'load-path "~/.emacs.d/site-lisp/eaf-rss-read

EAF 15 Dec 07, 2022
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
An online markdown resume template project, based on pywebio

An online markdown resume template project, based on pywebio

极简XksA 5 Nov 10, 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 simple and clean python banner generator - Banners

🚩 A simple and clean python banner generator - Banners

Kumar Vicku 12 Oct 09, 2022
The Scary Story - A Text Adventure

This is a text adventure which I made in python 3. This is one of my first big projects so any feedback would be greatly appreciated.

2 Feb 20, 2022
A minimal code sceleton for a textadveture parser written in python.

Textadventure sceleton written in python Use with a map file generated on https://www.trizbort.io Use the following Sockets for walking directions: n

1 Jan 06, 2022
An extension to detect if the articles content match its title.

Clickbait Detector An extension to detect if the articles content match its title. This was developed in a period of 24-hours in a hackathon called 'H

Arvind Krishna 5 Jul 26, 2022