熊猫中最近的邻居匹配

时间:2019-04-18 22:32:53

标签: python pandas

给定两个DataFrames(t1,t2),它们都具有列“ x”,我如何将列添加到ID为t2且其“ x”值最接近t1中“ x”值的列到t1?

t1:
id  x
1   1.49
2   2.35

t2:
id  x
3   2.36
4   1.5

output:
id  id2
1   4
2   3

我可以通过创建一个新的DataFrame并在t1.groupby()上进行迭代并在t2上进行查找然后合并来完成此操作,但是在给定1700万行t1 DataFrame的情况下,这花费了非常长的时间。

是否有更好的方法来完成?我已经搜索了有关groupby,apply,transform,agg等的pandas文档。但是尽管我认为这将是一个普遍的问题,但是仍然没有一种优雅的解决方案。

4 个答案:

答案 0 :(得分:4)

使用merge_asof

df = pd.merge_asof(df1.sort_values('x'),
                   df2.sort_values('x'),
                   on='x', 
                   direction='nearest', 
                   suffixes=['', '_2'])

print(df)
Out[975]: 
   id     x  id_2
0   3  0.87     6
1   1  1.49     5
2   2  2.35     4

方法2 reindex

df1['id2']=df2.set_index('x').reindex(df1.x,method='nearest').values
df1
   id     x  id2
0   1  1.49    4
1   2  2.35    3

答案 1 :(得分:1)

转换为列表t1和t2,然后对它们进行排序 并使用zip()函数匹配ID

$score

//之后,您必须看到类似(1,4),(2,3)

的输出

答案 2 :(得分:1)

或者,您可以使用 round 1 精度

t1 = {'id': [1, 2], 'x': [1.49,2.35]}
t2 = {'id': [3, 4], 'x': [2.36,1.5]}
df1 = pd.DataFrame(t1)
df2 = pd.DataFrame(t2)
df  = df1.round(1).merge(df2.round(1), on='x', suffixes=('','2')).drop('x',1)
print(df)
      id   id2
0     1    4
1     2    3
  • add .drop('x',1) 删除绑定列'x'的输出。
  • 添加 suffixes=('','2') 重命名列标题。

答案 3 :(得分:1)

您可以使用t1中的每个元素到t2中的每个元素的距离来计算一个新数组,然后将argmin沿行取到正确的索引。这样的好处是您可以选择自己喜欢的距离函数,并且不需要数据帧的长度相等。 它创建一个大小为len(t1)* len(t2)的中间数组。使用内置的pandas可能会更节省内存,但是这应该尽可能快,因为所有操作都在numpy的C端完成。如果内存有问题,您总是可以批量执行此方法。

import numpy as np
import pandas as pd

t1 = pd.DataFrame({"id": [1, 2], "x": np.array([1.49, 2.35])})
t2 = pd.DataFrame({"id": [3, 4], "x": np.array([2.36, 1.5])})

现在是完成实际工作的部分。 .to_numpy()位非常重要,因为否则Pandas会尝试合并索引。第一行使用广播以内存有效的方式创建水平和垂直“重复”。

dist = np.abs(t1["x"][np.newaxis, :] - t2["x"][:, np.newaxis])
closest_idx = np.argmin(dist, axis=1)
closest_id = t2["id"][closest_idx].to_numpy()

output = pd.DataFrame({"id1": t1["id"], "id2": closest_id})
print(output)