У меня есть приблизительно 1 миллион строк данных о пандах, содержащих данные, проанализированные на основании федерального апелляционного суда.Мне нужно извлечь имена судей, рассматривающих дела.Данные имеют неизвестное количество судей по делу (одна строка), которые содержатся в строке.Эта строка (в настоящее время хранится в одном столбце) содержит много лишнего текста, а также имеет несовместимое форматирование и использование заглавных букв.Я использую разные словари имен судей (с возможностью использования 2575 ключей регулярных выражений) для сопоставления судей, перечисленных на основе нескольких критериев, описанных ниже.Сначала я использую словарь с самыми строгими критериями соответствия и постепенно ослабляю критерии.Я также удаляю соответствующую строку из исходного столбца.Нынешние методы, которые я пробовал, слишком медленны (занимают дни, недели или даже месяцы).Причина существования нескольких возможных словарей в том, что многие судьи имеют одинаковые (фамилии) имена.Строки обычно не содержат полных имен.Я использую данные, содержащиеся в двух других столбцах, чтобы получить правильное соответствие: год, когда дело было решено, и суд, рассматривающий дело (оба целых числа).У меня также есть более и менее качественные условия поиска подстроки.Словари, которые я использую, могут быть созданы по желанию в разных форматах, кроме регулярных выражений, если это необходимо.
Самое быстрое решение, которое я пробовал, было грубым и непифоничным.При первоначальном разборе данных (извлечении разделов и ключевых слов из необработанных текстовых файлов), который происходит в каждом конкретном случае, я сделал следующее: 1) удалил лишний текст в максимально возможной степени, 2) отсортировал оставшиесятекст в список, хранящийся в столбце панд, 3) объединяет в виде строк год и суд для каждого элемента в этом списке, и 4) сопоставляет эту объединенную строку со словарем, который я подготовил аналогичным образом.Этот словарь не использовал регулярные выражения и имел приблизительно 800 000 ключей.Этот процесс занял около суток (с учетом всех других разборов) и был не столь точным, как мне бы хотелось (потому что в нем отсутствовали определенные перестановки формата имени).Приведенный ниже код содержит мою последнюю попытку (которая в данный момент выполняется и выглядит одной из самых медленных).Он создает подмножества словарей на лету и все равно в конечном итоге перебирает эти меньшие словари с ключами регулярных выражений.Я прочитал и попытался применить решения из многих вопросов stackoverflow, но не смог найти работоспособное решение.Я открыт для любой идеи на основе Python.Данные - это реальные данные, которые я очистил с помощью предыдущей функции.
import numpy as np
import pandas as pd
test_data = {'panel_judges' : ['CHAGARES, VANASKIE, SCHWARTZ',
'Sidney R. Thomas, Barry G. Silverman, Raymond C. Fisher, Opinion by Thomas'],
'court_num' : [3, 9],
'date_year' : [2014, 2014]}
test_df = pd.DataFrame(data = test_data)
name_dict = {'full_name' : ['Chagares, Michael A.',
'Vanaskie, Thomas Ignatius',
'Schwartz, Charles, Jr.',
'Schwartz, Edward Joseph',
'Schwartz, Milton Lewis',
'Schwartz, Murray Merle'],
'court_num' : [3, 3, 1061, 1097, 1058, 1013],
'circuit_num' : [3, 3, 5, 9, 9, 3],
'start_year' : [2006, 2010, 1976, 1968, 1979, 1974],
'end_year' : [2016, 2019, 2012, 2000, 2005, 2013],
'hq_match' : ['M(?=ICHAEL)? ?A?(?=\.)? ?CHAGARES',
'T(?=HOMAS)? ?I?(?=GNATIUS)? ?VANASKIE',
'C(?=HARLES)? SCHWARTZ',
'E(?=DWARD)? ?J?(?=OSEPH)? ?SCHWARTZ',
'M(?=ILTON)? ?L?(?=EWIS)? ?SCHWARTZ',
'M(?=URRAY)? ?M?(?=ERLE)? ?SCHWARTZ'],
'lq_match' : ['CHAGARES',
'VANASKIE',
'SCHWARTZ',
'SCHWARTZ',
'SCHWARTZ',
'SCHWARTZ']}
names = pd.DataFrame(data = name_dict)
in_col = 'panel_judges'
year_col = 'date_year'
out_col = 'fixed_panel'
court_num_col = 'court_num'
test_df[out_col] = ''
test_df[out_col].astype(list, inplace = True)
def judge_matcher(df, in_col, out_col, year_col, court_num_col,
size_column = None):
general_cols = ['start_year', 'end_year', 'full_name']
court_cols = ['court_num', 'circuit_num']
match_cols = ['hq_match', 'lq_match']
for match_col in match_cols:
for court_col in court_cols:
lookup_cols = general_cols + [court_col] + [match_col]
judge_df = names[lookup_cols]
for year in range(df[year_col].min(),
df[year_col].max() + 1):
for court in range(df[court_num_col].min(),
df[court_num_col].max() + 1):
lookup_subset = ((judge_df['start_year'] <= year)
& (year < (judge_df['end_year'] + 2))
& (judge_df[court_col] == court))
new_names = names.loc[lookup_subset]
df_subset = ((df[year_col] == year)
& (df[court_num_col] == court))
df.loc[df_subset] = matcher(df.loc[df_subset],
in_col, out_col, new_names, match_col)
return df
def matcher(df, in_col, out_col, lookup, keys):
patterns = dict(zip(lookup[keys], lookup['full_name']))
for key, value in patterns.items():
df[out_col] = (
np.where(df[in_col].astype(str).str.upper().str.contains(key),
df[out_col] + value + ', ', df[out_col]))
df[in_col] = df[in_col].astype(str).str.upper().str.replace(key, '')
return df
df = judge_matcher(test_df, in_col, out_col, year_col, court_num_col)
Вывод, который я получаю в настоящее время, по существу правильный (хотя имена должны быть отсортированы и в списке).Правильный «Шварц» выбран, и все совпадения верны.Проблема в скорости.Моя цель - иметь дедуплицированный, отсортированный (в алфавитном порядке) список судей на каждой панели, либо храниться в одном столбце, либо разбиваться на 15 отдельных столбцов (в настоящее время я делаю это в отдельной векторизованной функции).Затем я проведу другие поиски этих судей на основе другой демографической и биографической информации.Полученные данные будут доступны для исследователей в этой области, и код станет частью бесплатной общедоступной платформы, которую можно будет использовать и для изучения других судов.Таким образом, точность и скорость являются важными факторами для пользователей на разных машинах.