2

次の形式のデータがあります。

Bxxxx, Mxxxx F  Birmingham   AL (123) 555-2281  NCC Clinical Mental Health, Counselor Education, Sexual Abuse Recovery, Depression/Grief/Chronically or Terminally Ill, Mental Health/Agency Counseling English 99.52029    -99.8115
Axxxx, Axxxx Brown  Birmingham   AL (123) 555-2281  NCC Clinical Mental Health, Depression/Grief/Chronically or Terminally Ill, Mental Health/Agency Counseling English 99.52029    -99.8115
Axxxx, Bxxxx    Mobile   AL (123) 555-8011  NCC Childhood & Adolescence, Clinical Mental Health, Sexual Abuse Recovery, Disaster Counseling English 99.68639    -99.053238
Axxxx, Rxxxx Lunsford   Athens   AL (123) 555-8119  NCC, NCCC, NCSC Career Development, Childhood & Adolescence, School, Disaster Counseling, Supervision   English 99.804501   -99.971283
Axxxx, Mxxxx    Mobile   AL (123) 555-5963  NCC Clinical Mental Health, Counselor Education, Depression/Grief/Chronically or Terminally Ill, Mental Health/Agency Counseling, Supervision   English 99.68639    -99.053238
Axxxx, Txxxx    Mountain Brook   AL (123) 555-3099  NCC Addictions and Dependency, Career Development, Childhood & Adolescence, Corrections/Offenders, Sexual Abuse Recovery    English 99.50214    -99.75557
Axxxx, Lxxxx    Birmingham   AL (123) 555-4550  NCC Addictions and Dependency, Eating Disorders English 99.52029    -99.8115
Axxxx, Wxxxx    Birmingham   AL (123) 555-2328  NCC     English 99.52029    -99.8115
Axxxx, Rxxxx    Mobile   AL (123) 555-9411  NCC Addictions and Dependency, Childhood & Adolescence, Couples & Family, Sexual Abuse Recovery, Depression/Grief/Chronically or Terminally Ill English 99.68639    -99.053238

そして、人名だけを抽出する必要があります。理想的には、 humanName を使用して、フィールドname.firstname.middlename.lastname.title...を持つ一連の名前オブジェクトを取得できます。

状態を表す最初の 2 つの連続した大文字に到達するまで反復を試み、それから前のものをリストに格納してから humanName を呼び出しましたが、それは惨事でした。私はこの方法を試し続けたくありません。

単語の始まりと終わりを感知する方法はありますか? それは役に立つかもしれません...

おすすめは?

4

2 に答える 2

1

最善の策は、別のデータ ソースを見つけることです。真剣に。これはファークされています。

それができない場合は、次のような作業を行います。

  1. すべてのダブル スペースをシングル スペースに置き換えます。
  2. スペースで行を分割する
  3. リストの最後の 2 項目を取ります。それらは緯度と経度です
  4. リストを逆方向にループして、各項目を潜在的な言語のリストにルックアップします。ルックアップが失敗した場合、言語は終了です。
  5. 残りのリスト項目をスペースで結合します
  6. 行で、最初の開き括弧を見つけます。約 13 または 14 文字を読み取り、すべての句読点を空の文字列に置き換え、通常の電話番号として再フォーマットします。
  7. 電話番号の後の行の残りの部分をカンマで分割します。
  8. その分割を使用して、リスト内の各項目をループします。テキストが複数の大文字で始まる場合は、証明書に追加します。それ以外の場合は、実践分野に追加してください。
  9. 手順 6 で見つけたインデックスに戻り、それまでの行を取得します。スペースで分割し、最後の項目を取ります。それが州です。あとは名前と市区町村だけ!
  10. スペース分割行の最初の 2 項目を取ります。これまでのところ、それが名前の最良の推測です。
  11. 3番目の項目を見てください。1 文字の場合は、名前に追加し、リストから削除します。
  12. ここから US.zip をダウンロードします: http://download.geonames.org/export/zip/US.zip
  13. 米国のデータ ファイルでは、すべてをタブで分割します。都市名と州の略語であるインデックス 2 と 4 のデータを取得します。すべてのデータをループし、省略形 + ":" + 都市名 (つまり AK:Sand Point) として連結された各行を新しいリストに挿入します。
  14. 手順 13 と同じ形式で、ライン内の残りのアイテムの可能なすべての結合を組み合わせます。したがって、2 行目は AL:Brown Birmingham と AL:Birmingham になります。
  15. 各組み合わせをループし、手順 13 で作成したリストで検索します。見つかった場合は、分割リストから削除します。
  16. 文字列分割リストの残りのすべての項目を人の名前に追加します。
  17. 必要に応じて、カンマで名前を分割します。index[0] は姓です index[1] は残りのすべての名前です。ミドルネームについては何も仮定しないでください。

笑いのために、私はこれを実装しました。楽しみ。

import itertools

# this list of languages could be longer and should read from a file
languages = ["English", "Spanish", "Italian", "Japanese", "French",
             "Standard Chinese", "Chinese", "Hindi", "Standard Arabic", "Russian"]

languages = [language.lower() for language in languages]

# Loop through US.txt and format it. Download from geonames.org.
cities = []
with open('US.txt', 'r') as us_data:
    for line in us_data:
        line_split = line.split("\t")
        cities.append("{}:{}".format(line_split[4], line_split[2]))

# This is the dataset
with open('state-teachers.txt', 'r') as teachers:
    next(teachers)  # skip header

    for line in teachers:
        # Replace all double spaces with single spaces
        while line.find("  ") != -1:
            line = line.replace("  ", " ")

        line_split = line.split(" ")

        # Lat/Lon are the last 2 items
        longitude = line_split.pop().strip()
        latitude = line_split.pop().strip()

        # Search for potential languages and trim off the line as we find them
        teacher_languages = []

        while True:
            language_check = line_split[-1]
            if language_check.lower().replace(",", "").strip() in languages:
                teacher_languages.append(language_check)
                del line_split[-1]
            else:
                break

        # Rejoin everything and then use phone number as the special key to split on
        line = " ".join(line_split)

        phone_start = line.find("(")
        phone = line[phone_start:phone_start+14].strip()

        after_phone = line[phone_start+15:]

        # Certifications can be recognized as acronyms
        # Anything else is assumed to be an area of practice
        certifications = []
        areas_of_practice = []

        specialties = after_phone.split(",")
        for specialty in specialties:
            specialty = specialty.strip()
            if specialty[0:2].upper() == specialty[0:2]:
                certifications.append(specialty)
            else:
                areas_of_practice.append(specialty)

        before_phone = line[0:phone_start-1]
        line_split = before_phone.split(" ")

        # State is the last column before phone
        state = line_split.pop()

        # Name should be the first 2 columns, at least. This is a basic guess.
        name = line_split[0] + " " + line_split[1]

        line_split = line_split[2:]

        # Add initials
        if len(line_split[0].strip()) == 1:
            name += " " + line_split[0].strip()
            line_split = line_split[1:]

        # Combo of all potential word combinations to see if we're dealing with a city or a name
        combos = [" ".join(combo) for combo in set(itertools.permutations(line_split))] + line_split

        line = " ".join(line_split)
        city = ""

        # See if the state:city combo is valid. If so, set it and let everything else be the name
        for combo in combos:
            if "{}:{}".format(state, combo) in cities:
                city = combo
                line = line.replace(combo, "")
                break

        # Remaining data must be a name
        if line.strip() != "":
            name += " " + line

        # Clean up names
        last_name, first_name = [piece.strip() for piece in name.split(",")]

        print first_name, last_name
于 2013-06-27T20:59:57.733 に答える