首页 > 解决方案 > 使用 numpy/pandas 查找到参考项目的距离

问题描述

我想计算从一组点到一组参考点的距离,其中参考点的数量与点的数量不同(并且更小)。例如,想一想地点到他们所在城市中心的距离,或者孩子和他们父母之间的年龄差异(所以每个父母都有不同数量的孩子)。这绝不是使用的要求,pandas但我认为这会简单快捷。

给定一个数据集:

np.random.seed(4)
n = 10
city = np.arange(n)
location = city % 6
city = city // 6
x, y = np.random.random((2,n))
df = pd.DataFrame(np.transpose([city,location,x,y]),
                  columns=['city','location','x','y'])
# df:
#    city  location         x         y
# 0   0.0       0.0  0.967030  0.779383
# 1   0.0       1.0  0.547232  0.197685
# 2   0.0       2.0  0.972684  0.862993
# 3   0.0       3.0  0.714816  0.983401
# 4   0.0       4.0  0.697729  0.163842
# 5   0.0       5.0  0.216089  0.597334
# 6   1.0       0.0  0.976274  0.008986
# 7   1.0       1.0  0.006230  0.386571
# 8   1.0       2.0  0.252982  0.044160
# 9   1.0       3.0  0.434792  0.956653

对象按索引分组,对象与location=0引用相对应。所以我想计算所有对象的距离,city=0其中一个city=0 & location=0和类似的city=1(对于更大的数据集,依此类推)。所以以下工作:

dist = np.zeros(city.size)
for i in np.unique(city):
    group = (city == i)
    ref = group & (location == 0)
    dist[group] = ((x[group]-x[ref])**2 + (y[group]-y[ref])**2)**0.5

但是当然要花很长时间(我有大约一百万个“城市”和> 10 ^ 8个“位置”)。我尝试对组应用距离函数,认为这将获取每个箱并计算到其自己参考的距离,因为每个城市总是只有一个参考:

def fdist(group):
    return ((group['x']-group['x'][group['location'] == 0])**2 \
        + (group['y']-group['y'][group['location'] == 0])**2)**0.5

by_index = df[['x','y','location']].groupby(df['city'])
dist = by_index.apply(fdist)

但它只估计参考对象与自身的距离:

print(dist.values)
# array([  0.,  nan,  nan,  nan,  nan,   0.,  nan,  nan,  nan,  nan,   0.,
#    nan,  nan,  nan,  nan,   0.,  nan,  nan,  nan,  nan,   0.,  nan,
#    nan,  nan,  nan,  nan,  nan,  nan,  nan,  nan])

任何帮助将不胜感激。

标签: pythonpandasnumpy

解决方案


以下是我跟踪问题的方式——只是为了向您展示基本的调试:

def fdist(group):
    print("TRACE X")
    print(group['x'])
    print(group['x'][group['location'] == 0])
    print(group['x'] - group['x'][group['location'] == 0])

    return ((group['x']-group['x'][group['location'] == 0])**2 \
        + (group['y']-group['y'][group['location'] == 0])**2)**0.5

输出很清楚:

TRACE X
6    0.067974
7    0.673067
8    0.843953
9    0.644029
Name: x, dtype: float64
6    0.067974
Name: x, dtype: float64
6    0.0
7    NaN
8    NaN
9    NaN
Name: x, dtype: float64

您的术语group['x'][group['location'] == 0]是另一个 NumPy 行:,而不是标量。因此,当您进行减法时,您会得到逐元素减法,而不是您想要的标量减法。匹配元素为0,其他未定义。

读者练习:如何从该行中提取右手值6 0.067974?您的替代方法是制作一个完整的数组,将该行复制 4 次。


推荐阅读