【问题标题】:kdb+/q: Fast vector update given a list of keys and values to be updatedkdb+/q:给定要更新的键和值列表的快速向量更新
【发布时间】:2020-07-20 19:51:20
【问题描述】:

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

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

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

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

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

谢谢

【问题讨论】:

    标签: kdb


    【解决方案1】:

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

    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)]
    

    【讨论】:

    • 值得注意的是,由于内存分配是写时复制,就地修改只会避免为您正在更改的列分配内存,而不是为表中的所有列分配内存。
    【解决方案2】:

    这里有两种不同的方法。

    tab lj ([ikeys] toupd: ivals)
    

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

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

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

    【讨论】:

      【解决方案3】:

      字典也是给定映射更新值的常用方法。用 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
      

      【讨论】:

        猜你喜欢
        • 2023-03-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多