使用 KDTree/KNN Return 最近邻
Use KDTree/KNN Return Closest Neighbors
我有两个 python pandas 数据帧。一个包含自 2007 年以来所有 NFL 四分卫的大学橄榄球统计数据以及他们的球员类型标签(精英、平均、低于平均水平)。另一个数据框包含本赛季所有大学橄榄球 qbs 数据以及预测标签。
我想 运行 进行某种分析,根据每个大学橄榄球 qb 的标签确定两个最接近的 NFL 比较。我想将两个可比较的 qb 作为两个新列添加到第二个数据框。
两个数据框中的特征名称相同。这是数据框的样子:
Player Year Team GP Comp % YDS TD INT Label
Player A 2020 ASU 12 65.5 3053 25 6 Average
对于上面的示例,我想要两个从第一个数据帧中找到距离玩家 A 最近的两个邻居,它们也具有标签 "Average"。
我想到的方法是使用 Scipy 的 KDTree 和 运行 查询树:
tree = KDTree(nfl[features], leafsize=nfl[features].shape[0]+1)
closest = []
for row in college.iterrows():
distances, ndx = tree.query(row[features], k=2)
closest.append(ndx)
print(closest)
但是,打印语句返回了一个空列表。这是解决我问题的正确方法吗?
.iterrows()
, will return namedtuples (index, Series) 其中 index 显然是行的索引,而 Series 是特征值,其中索引是列名(参见以下)。
正如您所拥有的那样,row
被存储为该元组,因此当您拥有 row[features]
时,它实际上不会做任何事情。您真正追求的是具有 row[1]
特征和价值的系列。因此,您可以直接调用它,也可以通过 for idx, row in df.iterrows():
在循环中将它们分解。然后你就可以调用那个系列 row
.
Scikit learn 是一个很好用的包(实际上是建立在 Scipy 上的,所以你会注意到相同的语法)。你必须根据你的规范编辑代码(比如过滤器只有 "Average" 玩家,也许你正在对类别列进行单热编码,在这种情况下可能需要将其添加到功能等。 ),但为了给你一个想法(我编造这些数据框只是为了举个例子……实际上 nfl 是准确的,但大学完全编造了),你可以在下面看到使用 kdtree 然后将每一行放入college
数据框,以查看它最接近 nfl
数据框中的哪 2 个值。我显然让它打印出了名字,但是正如你在 print(closest)
中看到的那样,原始数组就在那里。
import pandas as pd
nfl = pd.DataFrame([['Tom Brady','1999','Michigan',11,61.0,2217,16,6,'Average'],
['Aaron Rodgers','2004','California',12,66.1,2566,24,8,'Average'],
['Payton Manning','1997','Tennessee',12,60.2,3819,36,11,'Average'],
['Drew Brees','2000','Perdue',12,60.4,3668,26,12,'Average'],
['Dan Marino','1982','Pitt',12,58.5,2432,17,23,'Average'],
['Joe Montana','1978','Notre Dame',11,54.2,2010,10,9,'Average']],
columns = ['Player','Year','Team','GP','Comp %','YDS','TD','INT','Label'])
college = pd.DataFrame([['Joe Smith','2019','Illinois',11,55.6,1045,15,7,'Average'],
['Mike Thomas','2019','Wisconsin',11,67,2045,19,11,'Average'],
['Steve Johnson','2019','Nebraska',12,57.3,2345,9,19,'Average']],
columns = ['Player','Year','Team','GP','Comp %','YDS','TD','INT','Label'])
features = ['GP','Comp %','YDS','TD','INT']
from sklearn.neighbors import KDTree
tree = KDTree(nfl[features], leaf_size=nfl[features].shape[0]+1)
closest = []
for idx, row in college.iterrows():
X = row[features].values.reshape(1, -1)
distances, ndx = tree.query(X, k=2, return_distance=True)
closest.append(ndx)
collegePlayer = college.loc[idx,'Player']
closestPlayers = [ nfl.loc[x,'Player'] for x in ndx[0] ]
print ('%s closest to: %s' %(collegePlayer, closestPlayers))
print(closest)
输出:
Joe Smith closest to: ['Joe Montana', 'Tom Brady']
Mike Thomas closest to: ['Joe Montana', 'Tom Brady']
Steve Johnson closest to: ['Dan Marino', 'Tom Brady']
我有两个 python pandas 数据帧。一个包含自 2007 年以来所有 NFL 四分卫的大学橄榄球统计数据以及他们的球员类型标签(精英、平均、低于平均水平)。另一个数据框包含本赛季所有大学橄榄球 qbs 数据以及预测标签。
我想 运行 进行某种分析,根据每个大学橄榄球 qb 的标签确定两个最接近的 NFL 比较。我想将两个可比较的 qb 作为两个新列添加到第二个数据框。
两个数据框中的特征名称相同。这是数据框的样子:
Player Year Team GP Comp % YDS TD INT Label
Player A 2020 ASU 12 65.5 3053 25 6 Average
对于上面的示例,我想要两个从第一个数据帧中找到距离玩家 A 最近的两个邻居,它们也具有标签 "Average"。 我想到的方法是使用 Scipy 的 KDTree 和 运行 查询树:
tree = KDTree(nfl[features], leafsize=nfl[features].shape[0]+1)
closest = []
for row in college.iterrows():
distances, ndx = tree.query(row[features], k=2)
closest.append(ndx)
print(closest)
但是,打印语句返回了一个空列表。这是解决我问题的正确方法吗?
.iterrows()
, will return namedtuples (index, Series) 其中 index 显然是行的索引,而 Series 是特征值,其中索引是列名(参见以下)。
正如您所拥有的那样,row
被存储为该元组,因此当您拥有 row[features]
时,它实际上不会做任何事情。您真正追求的是具有 row[1]
特征和价值的系列。因此,您可以直接调用它,也可以通过 for idx, row in df.iterrows():
在循环中将它们分解。然后你就可以调用那个系列 row
.
Scikit learn 是一个很好用的包(实际上是建立在 Scipy 上的,所以你会注意到相同的语法)。你必须根据你的规范编辑代码(比如过滤器只有 "Average" 玩家,也许你正在对类别列进行单热编码,在这种情况下可能需要将其添加到功能等。 ),但为了给你一个想法(我编造这些数据框只是为了举个例子……实际上 nfl 是准确的,但大学完全编造了),你可以在下面看到使用 kdtree 然后将每一行放入college
数据框,以查看它最接近 nfl
数据框中的哪 2 个值。我显然让它打印出了名字,但是正如你在 print(closest)
中看到的那样,原始数组就在那里。
import pandas as pd
nfl = pd.DataFrame([['Tom Brady','1999','Michigan',11,61.0,2217,16,6,'Average'],
['Aaron Rodgers','2004','California',12,66.1,2566,24,8,'Average'],
['Payton Manning','1997','Tennessee',12,60.2,3819,36,11,'Average'],
['Drew Brees','2000','Perdue',12,60.4,3668,26,12,'Average'],
['Dan Marino','1982','Pitt',12,58.5,2432,17,23,'Average'],
['Joe Montana','1978','Notre Dame',11,54.2,2010,10,9,'Average']],
columns = ['Player','Year','Team','GP','Comp %','YDS','TD','INT','Label'])
college = pd.DataFrame([['Joe Smith','2019','Illinois',11,55.6,1045,15,7,'Average'],
['Mike Thomas','2019','Wisconsin',11,67,2045,19,11,'Average'],
['Steve Johnson','2019','Nebraska',12,57.3,2345,9,19,'Average']],
columns = ['Player','Year','Team','GP','Comp %','YDS','TD','INT','Label'])
features = ['GP','Comp %','YDS','TD','INT']
from sklearn.neighbors import KDTree
tree = KDTree(nfl[features], leaf_size=nfl[features].shape[0]+1)
closest = []
for idx, row in college.iterrows():
X = row[features].values.reshape(1, -1)
distances, ndx = tree.query(X, k=2, return_distance=True)
closest.append(ndx)
collegePlayer = college.loc[idx,'Player']
closestPlayers = [ nfl.loc[x,'Player'] for x in ndx[0] ]
print ('%s closest to: %s' %(collegePlayer, closestPlayers))
print(closest)
输出:
Joe Smith closest to: ['Joe Montana', 'Tom Brady']
Mike Thomas closest to: ['Joe Montana', 'Tom Brady']
Steve Johnson closest to: ['Dan Marino', 'Tom Brady']