Если все сокращения являются префиксами, вы можете использовать строковый метод .startswith()
либо для короткой, либо для длинной версии состояния.
>>> test_value = "Flor"
>>> test_value.upper().startswith("FL")
True
>>> "Florida".lower().startswith(test_value.lower())
True
Однако если у вас есть более сложные сокращения, difflib.get_close_matches
, вероятно, делай что хочешь!
>>> import pandas as pd
>>> import difflib
>>> df = pd.DataFrame({"states": ("Florida", "Texas"), "st": ("FL", "TX")})
>>> df
states st
0 Florida FL
1 Texas TX
>>> difflib.get_close_matches("Flor", df["states"].to_list())
['Florida']
>>> difflib.get_close_matches("x", df["states"].to_list(), cutoff=0.2)
['Texas']
>>> df["st"][df.index[df["states"]=="Texas"]].iloc[0]
'TX'
Вы, вероятно, захотите попробовать/исключить IndexError
при чтении первого члена возвращаемого списка из difflib и, возможно, настроить отсечку, чтобы получить меньше ложных совпадений с близкими состояниями (возможно, предложить все состояния как возможности для некоторых пользователя или требуют больше букв для близких состояний).
Вы также можете увидеть лучшие результаты, сочетая два; сначала проверьте префиксы, прежде чем пытаться найти нечеткое совпадение.
Собираем все вместе
def state_from_partial(test_text, df, col_fullnames, col_shortnames):
if len(test_text) < 2:
raise ValueError("must have at least 2 characters")
# if there's exactly two characters, try to directly match short name
if len(test_text) == 2 and test_text.upper() in df[col_shortnames]:
return test_text.upper()
states = df[col_fullnames].to_list()
match = None
# this will definitely fail at least for states starting with M or New
#for state in states:
# if state.lower().startswith(test_text.lower())
# match = state
# break # leave loop and prepare to find the prefix
if not match:
try: # see if there's a fuzzy match
match = difflib.get_close_matches(test_text, states)[0] # cutoff=0.6
except IndexError:
pass # consider matching against a list of problematic states with different cutoff
if match:
return df[col_shortnames][df.index[df[col_fullnames]==match]].iloc[0]
raise ValueError("couldn't find a state matching partial: {}".format(test_text))
Остерегайтесь состояний, которые начинаются с «Новый» или «М» (и, возможно, других), которые все довольно близки и, вероятно, потребуют специальной обработки. Тестирование здесь творит чудеса.
person
ti7
schedule
30.09.2020