Parsing 标准化NFL球队名称

Parsing 标准化NFL球队名称,parsing,machine-learning,canonical-form,Parsing,Machine Learning,Canonical Form,这实际上是一个机器学习分类问题,但我想有一个非常好的快速和肮脏的方法来做。我想把一个描述NFL球队的字符串,比如“旧金山队”或“49人队”或“旧金山49人队”或“SF 49人队”,映射到球队的标准名称。(美国橄榄球联盟共有32支球队,所以这实际上只是意味着在32个垃圾箱中找到最接近的一个来放入给定的字符串。) 传入的字符串实际上并不是完全任意的(它们来自这样的结构化数据源:),因此不需要像上面的49ers示例那样处理每个疯狂的角落 我还应该补充一点,如果有人知道一个数据来源,其中既包含money

这实际上是一个机器学习分类问题,但我想有一个非常好的快速和肮脏的方法来做。我想把一个描述NFL球队的字符串,比如“旧金山队”或“49人队”或“旧金山49人队”或“SF 49人队”,映射到球队的标准名称。(美国橄榄球联盟共有32支球队,所以这实际上只是意味着在32个垃圾箱中找到最接近的一个来放入给定的字符串。)

传入的字符串实际上并不是完全任意的(它们来自这样的结构化数据源:),因此不需要像上面的49ers示例那样处理每个疯狂的角落

我还应该补充一点,如果有人知道一个数据来源,其中既包含moneyline Vegas赔率,也包含过去几年NFL比赛的实际比赛结果,那么就不需要这样做了。我需要规范化的原因是要匹配这两个不同的数据集,一个有几率,一个有结果:

非常欢迎提供更好、更可分析的数据源的想法


补充:子串匹配的想法可能很适合这个数据;谢谢通过选择距离最近的levenshtein距离的团队名称,是否可以使其更加健壮?

如果您同时知道源名称和目标名称,则只需映射它们即可。 在php中,只需使用一个数组,其中包含来自数据源的键和来自目标的值。然后,您将引用它们,如:

$map = array('49ers' => 'San Francisco 49ers',
             'packers' => 'Green Bay Packers');

foreach($incoming_name as $name) {
   echo $map[$name];
}

通过目测快速检查显示,两个数据集都包含团队的位置(即“明尼苏达州”)。其中只有一个有球队的名字。也就是说,一个列表如下所示:

Denver
Minnesota
Arizona
Jacksonville
另一个看起来像

Denver Broncos
Minnesota Vikings
Arizona Cardinals
Jacksonville Jaguars

看起来,在这种情况下,一些非常简单的子字符串匹配就可以做到这一点。

我认为,即使对于任意用户输入,这里也有一些非常强大的功能。首先,将每个团队(我使用3个字母的代码作为每个团队的标准名称)映射到一个完整的拼写版本,其中包含城市和团队名称以及城市和团队名称之间括号中的任何昵称

Scan[(fullname[First@#] = #[[2]])&, {
  {"ari", "Arizona Cardinals"},                 {"atl", "Atlanta Falcons"}, 
  {"bal", "Baltimore Ravens"},                  {"buf", "Buffalo Bills"}, 
  {"car", "Carolina Panthers"},                 {"chi", "Chicago Bears"}, 
  {"cin", "Cincinnati Bengals"},                {"clv", "Cleveland Browns"}, 
  {"dal", "Dallas Cowboys"},                    {"den", "Denver Broncos"}, 
  {"det", "Detroit Lions"},                     {"gbp", "Green Bay Packers"}, 
  {"hou", "Houston Texans"},                    {"ind", "Indianapolis Colts"}, 
  {"jac", "Jacksonville Jaguars"},              {"kan", "Kansas City Chiefs"}, 
  {"mia", "Miami Dolphins"},                    {"min", "Minnesota Vikings"}, 
  {"nep", "New England Patriots"},              {"nos", "New Orleans Saints"}, 
  {"nyg", "New York Giants NYG"},               {"nyj", "New York Jets NYJ"}, 
  {"oak", "Oakland Raiders"},                   {"phl", "Philadelphia Eagles"}, 
  {"pit", "Pittsburgh Steelers"},               {"sdc", "San Diego Chargers"}, 
  {"sff", "San Francisco 49ers forty-niners"},  {"sea", "Seattle Seahawks"}, 
  {"stl", "St Louis Rams"},                     {"tam", "Tampa Bay Buccaneers"}, 
  {"ten", "Tennessee Titans"},                  {"wsh", "Washington Redskins"}}]
然后,对于任何给定的字符串,为每个团队的全名找到最长的公共子序列。要优先选择在开头或结尾匹配的字符串(例如,“car”应该匹配“carolina panthers”而不是“arizona cardinals”),请将输入字符串和全名夹在空格之间。无论哪个团队的全名与输入字符串具有[sic:]最长的公共子序列,都是我们返回的团队。下面是算法的Mathematica实现:

teams = keys@fullnames;

(* argMax[f, domain] returns the element of domain for which f of that element is
   maximal -- breaks ties in favor of first occurrence. *)
SetAttributes[argMax, HoldFirst];
argMax[f_, dom_List] := Fold[If[f[#1] >= f[#2], #1, #2] &, First@dom, Rest@dom]

canonicalize[s_] := argMax[StringLength@LongestCommonSubsequence[" "<>s<>" ", 
                                 " "<>fullname@#<>" ", IgnoreCase->True]&, teams]
团队=keys@fullnames;
(*argMax[f,domain]返回域的元素,该元素的f是该域的元素
最大值——打破平局,有利于第一次出现。*)
SetAttributes[argMax,HoldFirst];
argMax[f#,dom#u List]:=Fold[If[f[#1]>=f[#2]、#1、#2]&,First@dom, Rest@dom]
规范化[s_3;]:=argMax[StringLength@LongestCommonSubsequence[“s”,
“”全名@#“”,IgnoreCase->True]&,团队]

噢,但问题是如何避免手动映射。但我想这真的没什么大不了的……:)在任何情况下,我认为拥有尽可能通用的规范化函数可能是有用的。你可以使用SOUNDEX之类的工具,但是数据的多样性和整个数据集的小规模使得通用解决方案不太可能。好主意——因此,要将其增加到通用解决方案中,您可以在长名称中添加额外的项目,例如“圣路易斯-圣路易斯公羊”,或者您已经使用SF。没错!虽然“圣路易斯”和“圣路易斯”的对决,但“路易斯”的搭配总是很丰富的。只是对于像“49人”和“49人”这样没有共同字母的替代品,你需要像你说的那样添加额外的项目。我几乎放弃了,因为你可能认为“圣路易斯”可以与“新奥尔良圣徒”和“圣路易斯公羊”相媲美,但事实上,在第一种情况下,最长的共享子串是“圣徒”在第二种情况下是“t louis”,因此它在不添加任何内容的情况下,对于这种变化来说确实足够健壮。