Ввести / очистить названия мест с помощью сравнения строк - PullRequest
0 голосов
/ 25 июня 2019

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

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

Набор данных с действительными городами США можно бесплатно скачать по адресу https://simplemaps.com/data/us-cities.

import pandas as pd
import numpy as np
from difflib import SequenceMatcher as SM

cities = pd.read_csv('Downloads/uscitiesv1.5.csv')

CITIES = [tuple([row['state_name'].upper(), row['county_name'].upper(), row['city'].upper()]) for i, row in cities.iterrows()]

### Helper functions
def distance(a, b):
    return SM(a = a.upper(), b = b.upper(), autojunk = False).ratio()

def findLocation(location):

    ## If more than 2 locations empty, return blank
    if sum([l == '' for l in location]) > 2:
        return ('', '', '')

    ## Cannot guess city if city empty
    if location[2] == '':
        return ('', '', '')

    comparison = {}

    exactOK = [[False, True, True], [True, False, True]]

    for LOC in CITIES:

        exactCompare = [(a == b) for a, b in zip(location, LOC)]

        ## Return location if 2 out of 3 exact matches including city
        if exactCompare in exactOK:
            return LOC

        distState =     distance(location[0], LOC[0])
        distCounty =    distance(location[1], LOC[1])
        distCity =      distance(location[2], LOC[2])

        ## The sum of scores for each of State, County, City
        sumDist = sum([distState, distCounty, distCity])

        comparison.update({LOC: sumDist})

    return max(comparison, key=comparison.get)

def emptyNA(s):

    if str(s).upper() in ['NA', 'MISSING', 'NOT CLEAR', '', ' ', 'NAN']:
        return ''
    else:
        return s

### Full location cleaning function
def cleanCities(data):

    if len(data.columns) != 3:
        print('invalid input')
        return
    if not all(data.dtypes == 'object'):
        print('invalid input')
        return

    data = data.applymap(lambda s: s.upper())

    ## Handle NAs
    data = data.applymap(lambda s: emptyNA(s))
    data = data.fillna('')

    ## Convert input to list of tuples
    cities = [(r[0], r[1], r[2]) for i, r in data.iterrows()]

    for i, city in enumerate(cities):

        ## Implicitly leave exact matches as is
        if city not in CITIES:

            ## Replace
            cities[i] = findLocation(city)

    newData = pd.DataFrame(cities)
    newData.columns = ['state_clean', 'county_clean', 'city_clean']

    return newData

ВотПосмотрим, как эта функция будет работать с каким-то грязным вводом.

test = {'State': ['MARLYAND', '', 'ARZONA', 'NORTHCAROLINA',
                  'FLODA', 'WASHINGTON',  'KENTCKY',  'COLORADO',
                  'ARKANSAS',  'MISSING'],
        'County': ['CAROLINE', 'DOÑANA',  'APAE',  'MITCHELL',
                   'ESCAMBEA',  'LWS',  'CAMPBELL',  'FREMONT',
                   'ARKANSAS',  'ST. LOUIS'],
        'City': ['CHOPTNK',  'AFTON',  'MCNARY',  'LEDGER',  'GOULDNG',
                 'MOSSYROCK',  '',  'CAÑON CITY',  'CROKETS BLUFF',
                 'FRENCHRVER']}

test = pd.DataFrame.from_dict(test)
cleaned = cleanCities(test)

print(test)
           State     County           City
0       MARLYAND   CAROLINE        CHOPTNK
1                    DOÑANA          AFTON
2         ARZONA       APAE         MCNARY
3  NORTHCAROLINA   MITCHELL         LEDGER
4          FLODA   ESCAMBEA        GOULDNG
5     WASHINGTON        LWS      MOSSYROCK
6        KENTCKY   CAMPBELL               
7       COLORADO    FREMONT     CAÑON CITY
8       ARKANSAS   ARKANSAS  CROKETS BLUFF
9        MISSING  ST. LOUIS     FRENCHRVER


print(cleaned)
      state_clean county_clean       city_clean
0        MARYLAND     CAROLINE         CHOPTANK
1      NEW MEXICO     DOÑA ANA            AFTON
2         ARIZONA       APACHE           MCNARY
3  NORTH CAROLINA     MITCHELL           LEDGER
4         FLORIDA     ESCAMBIA         GOULDING
5      WASHINGTON        LEWIS        MOSSYROCK
6                                              
7        COLORADO      FREMONT       CAÑON CITY
8        ARKANSAS     ARKANSAS  CROCKETTS BLUFF
9       MINNESOTA    ST. LOUIS     FRENCH RIVER
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...