对 pandas 数据框进行窗口化操作,以列出与前 n 个条目的欧氏距离

A windowed operation on a pandas data frame to list Euclidean distance from the previous n entries

我有一个已排序的(在 'values' 上)数据框,如下所示。未命名的列是索引。

        x_cord  y_cord  value
3384209 1650    1741    0.009752
3382265 1650    1740    0.009481
3384208 1649    1741    0.008943
3382264 1649    1740    0.008676
3384210 1651    1741    0.008473
... ... ... ...
1679661 46      865     0.000000
1679660 45      865     0.000000
1679659 44      865     0.000000
1679658 43      865     0.000000
5038847 1944    2592    0.000000

如何创建另一个列,其中包含到前 n 行的欧氏距离列表?例如

该列表始终最多包含十(或 n)个元素。

我怎样才能做到这一点?

仅供参考

def euc_distance(x1, y1, x2, y2):
    return math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)

首先,移动所有前 10 行,在每个移动的专用列中:

for i in range(1,11):
    df["x_cord_"+str(i)] = df["x_cord"].shift(i)
    df["y_cord_"+str(i)] = df["y_cord"].shift(i)

然后,计算每一行与现在存储在其专用列中的其他 10 个坐标之间的距离。 if 确保如果列中有 Nan,则结果列表将不包含此值。

df["distance"] = df.apply(lambda row: [euc_distance(row["x_cord"], row["y_cord"], row["x_cord_"+str(i)], row["y_cord_"+str(i)]) for i in range(1,11)  if not math.isnan(row["x_cord_"+str(i)])], axis=1)

最后,删除仅为计算创建的列。

df = df[["x_cord", "y_cord", "value", "distance"]]

输出:

          x_cord  y_cord       value    distance
3384209     1650    1741    0.009752    []
3382265     1650    1740    0.009481    [1.0]
3384208     1649    1741    0.008943    [1.4142135623730951, 1.0]
3382264     1649    1740    0.008676    [1.0, 1.0, 1.4142135623730951]
3384210     1651    1741    0.008473    [2.23606797749979, 2.0, 1.4142135623730951, 1.0]

可能还可以改进。

Numpy 助你一臂之力! (快速 解决方案,主要是矢量化):

def fun(k, z):
    na = np.full((k, z.shape[1]), np.nan)
    a = np.row_stack((na, z[:-k, :]))
    return np.linalg.norm(z - a, axis=1)

vfun = np.vectorize(fun, signature='(),(n,m)->(n)')

现在,您可以获得包含所有距离的数组 (n, k)

>>> k = 4  # just for nice printing; replace with 10 in your setting
>>> z = pd.DataFrame(vfun(range(1, k+1), df[['x_cord', 'y_cord']].values).T)
... z
             0            1            2            3
0          NaN          NaN          NaN          NaN
1     1.000000          NaN          NaN          NaN
2     1.414214     1.000000          NaN          NaN
3     1.000000     1.000000     1.414214          NaN
4     2.236068     2.000000     1.414214     1.000000
5  1828.496924  1826.262303  1826.741635  1827.140115
6     1.000000  1829.374757  1827.140115  1827.619216
7     1.000000     2.000000  1830.252715  1828.018052
8     1.000000     2.000000     3.000000  1831.130798
9  2568.332144  2567.592063  2566.852158  2566.112429

如果您愿意,可以将其转换为列表:

>>> z.apply(list, axis=1)
0                                 [nan, nan, nan, nan]
1                                 [1.0, nan, nan, nan]
2                  [1.4142135623730951, 1.0, nan, nan]
3                  [1.0, 1.0, 1.4142135623730951, nan]
4     [2.23606797749979, 2.0, 1.4142135623730951, 1.0]
5    [1828.4969237053695, 1826.2623031755325, 1826....
6    [1.0, 1829.3747565766835, 1827.1401150431786, ...
7    [1.0, 2.0, 1830.2527147910475, 1828.018052427273]
8                  [1.0, 2.0, 3.0, 1831.1307981681703]
9    [2568.3321436294023, 2567.592062614309, 2566.8...

综合起来:

out = df.assign(
    distances=pd.DataFrame(
        vfun(list(range(1, k+1)), df[['x_cord', 'y_cord']].values).T,
        index=df.index,
    ).apply(list, axis=1)
)

输出:

         x_cord  y_cord     value  \
3384209    1650    1741  0.009752   
3382265    1650    1740  0.009481   
3384208    1649    1741  0.008943   
3382264    1649    1740  0.008676   
3384210    1651    1741  0.008473   
1679661      46     865  0.000000   
1679660      45     865  0.000000   
1679659      44     865  0.000000   
1679658      43     865  0.000000   
5038847    1944    2592  0.000000   

                                                 distances  
3384209                               [nan, nan, nan, nan]  
3382265                               [1.0, nan, nan, nan]  
3384208                [1.4142135623730951, 1.0, nan, nan]  
3382264                [1.0, 1.0, 1.4142135623730951, nan]  
3384210   [2.23606797749979, 2.0, 1.4142135623730951, 1.0]  
1679661  [1828.4969237053695, 1826.2623031755325, 1826....  
1679660  [1.0, 1829.3747565766835, 1827.1401150431786, ...  
1679659  [1.0, 2.0, 1830.2527147910475, 1828.018052427273]  
1679658                [1.0, 2.0, 3.0, 1831.1307981681703]  
5038847  [2568.3321436294023, 2567.592062614309, 2566.8...  

对于您的情况,设置 k=10 而不是 4。