我有一个大约100万行熊猫数据框,其中包含从联邦上诉法院的意见分析的数据。我需要提取审理案件的法官的名字。数据中包含在字符串中的每个案例(一行)具有未知数量的法官。该字符串(当前存储在一列中)包含大量多余的文本,并且格式和大小写不一致。我使用不同的法官名称词典(可以使用2575个regex键)来匹配基于下面描述的多个条件列出的法官。我先用最严格的匹配标准词典,然后逐步放宽标准。我还从源列中删除匹配的字符串。目前我尝试的方法太慢了(需要几天、几周甚至几个月)。 之所以有多个可能的词典是因为许多法官都有相同的(姓)。字符串通常不包括全名。我使用其他两列中包含的数据来获得正确的匹配:案件判决年份和审理案件的法院(两个整数)。我也有高质量和低质量的子串搜索词。如果需要的话,除了regex之外,我使用的字典可以随意以不同的格式重新创建。在
我尝试过的最快的解决方案是粗糙和不和谐的。在数据的初始解析(从原始文本文件中提取节和关键字)中,我做了以下工作:1)尽可能地删除多余的文本,2)将剩余文本排序到存储在pandas列中的列表中,3)作为字符串将年份和法院连接到列表中的每个项,以及4) 将这个连接字符串与我准备的字典匹配。那本词典没有使用正则表达式,大约有80万个关键字。这个过程花了大约一天的时间(包括所有其他解析),并且没有我想要的那么准确(因为它省略了某些名称格式的排列)。 下面的代码包含了我最近的一次尝试(目前正在运行,看起来是最慢的选项之一)。它会动态地创建子集字典,但最终还是会用regex键遍历那些较小的字典。我已经通读并尝试应用许多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个单独的列(我目前在一个单独的向量化函数中这样做)。然后,我将根据其他人口统计和传记信息,对这些法官进行其他调查。所产生的数据将向该地区的研究人员公开,代码将成为一个免费的、公开的平台的一部分,可用于研究其他法院。因此,对于许多不同机器的用户来说,精度和速度都是重要的考虑因素。在
对于任何偶然发现这个问题并在pandas中有类似复杂字符串匹配问题的人来说,这是我发现最快的解决方案。在
它不像我想要的那样完全矢量化,但是我用了数据框应用在类中使用此方法:
基本上,它将三列连接在一起,并使用连接的字符串执行哈希字典查找(而不是正则表达式)。乘法被用来有效地连接两个数字并排作为字符串。字典也有类似的准备键(值是所需的字符串)。通过使用列表和重复数据消除,我不必删除匹配的字符串。我没有为这个特定的函数计时,但是整个模块只花了10多个小时就处理了大约100万行。当我再次运行它时,我会尽量记住这个应用函数的具体时间,并将结果张贴在这里。这个方法很难看,但相当有效。在
相关问题 更多 >
编程相关推荐