如何在两列熊猫的元素之间应用函数

时间:2019-03-12 14:34:57

标签: python pandas

我有一个需要两个元组输入的函数,例如:

def mult((x1,y1),(x2,y2)):
    return Eucledeandist((x1,y1),(x2,y2))

我有一个包含两列(x,y)的数据框,其中x和y代表点的坐标。现在,我需要计算数据框中每个点到每个其他点的距离。 我的意思是df的长度是否为'n'。我需要一个大小为nXn的输出,其中第(i,j)个条目是原始数据帧中第i个点与第j个点之间的距离。

如何使用df.apply函数执行此操作,而不是使用两个for循环?

示例代码以生成类似于我所拥有的数据框

df = pd.DataFrame({'x':np.random.randint(10, size=6), 'y':np.random.randint(10, size=6)})
df['(x,y)']=list(zip(df.x, df.y))

数据框应该这样

    x   y   (x,y)
0   9   4   (9, 4)
1   8   6   (8, 6)
2   8   4   (8, 4)
3   1   7   (1, 7)
4   7   1   (7, 1)
5   0   5   (0, 5)

列(x,y)只是将x和y列压缩在一起。我觉得这很容易,因为该函数接受元组输入。

编辑:对于未明确说明,我深表歉意。我以欧几里得距离为例来简化要求。实际要求是应使用函数来获得结果。函数执行的功能并不是很重要。

2 个答案:

答案 0 :(得分:2)

IIUC,不需要循环或应用,这确实很慢。

您可以改用基于欧几里德距离公式的矢量化解决方案

(1/H1) / (1/H1+1/J1)*100)

MCVE

np.sqrt(((df.values - df.values[:,None])**2).sum(2))

收益

df = pd.DataFrame({'x': [1,2,3,4], 'y':[10,20,30,40]})

    x   y
0   1   10
1   2   20
2   3   30
3   4   40

答案 1 :(得分:1)

使用scipy.spacial.distance模块中的pdistsquareform

示例

from scipy.spatial.distance import pdist, squareform

euc_dist = pdist(df[['x', 'y']])
df_dist = pd.DataFrame(squareform(euc_dist), index=df['(x,y)'], columns=df['(x,y)'])

print(df_dist)

(x,y)     (9, 4)    (8, 6)    (8, 4)    (1, 7)    (7, 1)    (0, 5)
(x,y)                                                             
(9, 4)  0.000000  2.236068  1.000000  8.544004  3.605551  9.055385
(8, 6)  2.236068  0.000000  2.000000  7.071068  5.099020  8.062258
(8, 4)  1.000000  2.000000  0.000000  7.615773  3.162278  8.062258
(1, 7)  8.544004  7.071068  7.615773  0.000000  8.485281  2.236068
(7, 1)  3.605551  5.099020  3.162278  8.485281  0.000000  8.062258
(0, 5)  9.055385  8.062258  8.062258  2.236068  8.062258  0.000000

如果您坚持使用.apply,则需要像这样构造它:

def mult(xy1, xy2):
    return Eucledeandist(xy1, xy2)

import itertools

df_coords = pd.DataFrame([[x, y] for x, y in itertools.combinations_with_replacement(df['(x,y)'], 2)], columns=['xy1', 'xy2'])
df_coords.apply(lambda row: mult(row['xy1'], row['xy2']) , axis=1)

尽管已经指出,这是非常低效的,不建议这样做。

相关问题