J中Rank的概念

The concept of Rank in J

如果我有一维数据比如

v1 =: 5 $ i.5
v1
0 1 2 3 4

然后 v1 -"1 0 v1 给我欧几里得向量,例如

v1 -"1 0 v1
 0  1  2  3 4
_1  0  1  2 3
_2 _1  0  1 2
_3 _2 _1  0 1
_4 _3 _2 _1 0

我们也可以很容易地找到欧氏距离矩阵。

这就是我找到二维向量的欧几里德向量和距离矩阵的方法

 v2=: <"1 ? 5 2 $ 10
   v2
┌───┬───┬───┬───┬───┐
│4 0│4 5│5 7│8 3│6 0│
└───┴───┴───┴───┴───┘
direction_vector=: <"1 @: (-"0 @:(-/"2 @: (>"0 @: (diff))))
distance =:     +/"1 @: *: @: (>"2 @:(direction_vector))
m =:        3 : '(i.(#y)) distance"0 _ y'
m v2
 0 25 50 25  4
25  0  5 20 29
50  5  0 25 50
25 20 25  0 13
 4 29 50 13  0

但是,我的问题是我不确定如何以智能和干净的方式找到二维数据的欧几里得向量和距离

从下面的table可以看出,我的算法用了超过1/3的时间来计算数据的方向向量。 14.5 秒还不错,但是当我有更大的数据集时,问题就出现了。

 Time (seconds)
+----------------+------+--------+---------+-----+----+------+
|name            |locale|all     |here     |here%|cum%|rep   |
+----------------+------+--------+---------+-----+----+------+
|direction_vector|base  |6.239582| 5.105430| 35.2| 35 |773040|
|move            |base  |9.741510| 1.753868| 12.1| 47 |  3390|
|script          |base  |1.969949| 1.443148|  9.9| 57 |    18|
|distance        |base  |5.650358| 1.318022|  9.1| 66 |579780|
|enclosestrings  |pcsv  |1.491832| 1.255603|  8.6| 75 |     1|
|diff            |base  |1.134585| 1.134585|  7.8| 83 |773186|
|makedsv         |pcsv  |1.728721| 0.236883|  1.6| 84 |     4|
|norm            |base  |0.221794| 0.221794|  1.5| 86 |  3390|
|xpt             |base  |0.194896| 0.194896|  1.3| 87 |  3390|
|ypt             |base  |0.193579| 0.193579|  1.3| 89 |  3390|
|writedsv        |pcsv  |2.067408| 0.186687|  1.3| 90 |     4|
|cosd            |base  |0.172359| 0.172359|  1.2| 91 |   113|
|[rest]          |      |        | 1.300733|  9.0|100 |      |
|[total]         |      |        |14.517587|100.0|100 |      |
+----------------+------+--------+---------+-----+----+------+

我想我绝对可以通过使用排名来简化 direction_vector 一个,但我卡住了。我尝试了 "2 1 "1 1 "1 2 "_ 1 "1 0 ...,但是 none 给了我一个明确的结果。

谁能帮我解决这个问题?谢谢!

我会首先注意到 v2 u/ v2 通过在 v2 的项目之间应用 u 从这些项目中生成 table。此外,您可以使用与 v2 u/ v2 相同的 u/~ v2 来稍微简化一下。下一个问题是 u 是什么,但在我们开始之前,装箱确实会减慢速度,您实际上不必为向量装箱才能工作,因为项目已经可以这样写了:

   [ v2=: 5 2 $ 4 0 4 5 5 7 8 3 6 0
4 0
4 5
5 7
8 3
6 0

这使项目成为向量,这是您希望能够使用的u/~ v2

现在,回到我们希望 u 成为什么的问题。我们将处理 v2 的项目 因为 u 被喂养 v2 的项目来制作 table,你想从每个项目中减去这些项目其他作为向量(等级 1),然后将它们平方,然后将它们加在一起。将其翻译成 J 你会得到 +/@:*:@:-"1 作为 u

    +/@:*:@:-"1/~ v2
 0 25 50 25  4
25  0  5 20 29
50  5  0 25 50
25 20 25  0 13
 4 29 50 13  0

如果你计时,我希望你会发现它比你的解决方案快得多,因为它不需要装箱。您关注等级的关键领域是它应用于 Table 副词 /

之后

希望这对您有所帮助,尽管方法略有不同,请告诉我您的时间安排。

新答案,以便我可以正确格式化结果。

从你的结果来看,我认为至少从我的测量来看,还有进一步改进的空间。通过将 +/ 更改为 +/"1 摆脱默认方法并移动到顺序应用程序,速度大约提高一倍。

   [ v2=: 5 2 $ 4 0 4 5 5 7 8 3 6 0
4 0
4 5
5 7
8 3
6 0
   (10000) 6!:2 '+/@:*:@:-"1/~ v2'
8.4647e_6
   (10000) 6!:2 '+/"1 *: -"1/~ v2'
3.1289e_6
      (+/"1 *: -"1/~ v2) -: (+/@:*:@:-"1/~ v2)
1
   +/"1 *: -"1/~ v2
 0 25 50 25  4
25  0  5 20 29
50  5  0 25 50
25 20 25  0 13
 4 29 50 13  0