kdb+/q:给定要更新的键和值列表的快速矢量更新

kdb+/q: Fast vector update given a list of keys and values to be updated

给定一个 ids/keys 列表和一组常量列的相应值:

q)ikeys: 1 2 3 5;
q)ivals: 100 100.5 101.5 99.5;

更新以下 table 中的 `toupd 列的最快方法是什么,以便将与给定 ikeys 匹配的行更新为 ivals:i.e.[= 中的新值13=]

q) show tab;
    ikeys | `toupd `noupd
    ------|--------------
       1  |  0.5    1
       2  |  100.5  2
       3  |  500.5  4
       4  |  400.5  8
       5  |  400.5  16
       6  |  600.5  32
       7  |  700.5  64

更新为:

q) show restab;
    ikeys | `toupd `noupd
    ------|--------------
       1  |  100    1
       2  |  100.5  2
       3  |  101.5  4
       4  |  400.5  8
       5  |  99.5   16
       6  |  600.5  32
       7  |  700.5  64

此外,是否有一种规范的方法可以以这种方式更新多个列。

谢谢

这里有两种不同的方法。

tab lj ([ikeys] toupd: ivals)

m: ikeys
update toupd: ivals from tab where ikeys in m

我相信还有很多方法。如果您想找出最适合您的目的(和您的数据)的方法,请尝试对大型表使用 q)\t:1000 yourCodeHere 并查看最适合您的方法。

至于哪个是多列的规范方式,我想应该是更新,但这是个人喜好问题,最快的就可以了。

字典也是给定映射更新值的常用方法。使用 ikeys 列索引字典给出新值,然后我们用旧的 toupd 列值填充空值。

q)show d:ikeys!ivals
1| 100
2| 100.5
3| 101.5
5| 99.5
q)update toupd:toupd^d ikeys from tab
ikeys| toupd noupd
-----| -----------
1    | 100   1
2    | 100.5 2
3    | 101.5 4
4    | 400.5 8
5    | 99.5  16
6    | 600.5 32
7    | 700.5 64

还值得注意的是,where 子句的更新条件并不能保证在所有情况下都有效,例如如果您的映射值多于 ikeys 列中显示的值。

q)m:ikeys:1 2 3 5 7 11
q)ivals:100 100.5 101.5 99.5 100 100
q)update toupd: ivals from tab where ikeys in m
'length

点修正是另一种更容易推广到多个列的方法。它还可以利用就地修改,这将是内存效率最高的方法,因为它不会在内存中创建 table 的副本(假设为全局)。

ikeys:1 2 3 5
ivals:100 100.5 101.5 99.5
tab:([ikeys:1+til 7]toupd:.5 100.5 500.5 400.5 400.5 600.5 700.5;noupd:1 2 4 8 16 32 64)

q).[tab;(([]ikeys);`toupd);:;ivals]
ikeys| toupd noupd
-----| -----------
1    | 100   1
2    | 100.5 2
3    | 101.5 4
4    | 400.5 8
5    | 99.5  16
6    | 600.5 32
7    | 700.5 64

/amend in place
.[`tab;(([]ikeys);`toupd);:;ivals]

/generalise to two columns
q).[tab;(([]ikeys);`toupd`noupd);:;flip(ivals;1000 2000 3000 4000)]
ikeys| toupd noupd
-----| -----------
1    | 100   1000
2    | 100.5 2000
3    | 101.5 3000
4    | 400.5 8
5    | 99.5  4000
6    | 600.5 32
7    | 700.5 64

/you could amend in place here too
.[`tab;(([]ikeys);`toupd`noupd);:;flip(ivals;1000 2000 3000 4000)]