【问题标题】:R -> kdb: Pass R data to kdb+ as binary objectsR -> kdb:将 R 数据作为二进制对象传递给 kdb+
【发布时间】:2014-12-27 22:42:57
【问题描述】:

R 对象(更具体地说,时间序列表示为xtsdata.table 对象,即基于时间的列和数字列)插入kdb+ 数据库的最有效方法是什么?

我只能通过q 表达式找到涉及字符串序列化的解决方案,如herehere 所述。

【问题讨论】:

    标签: r ipc kdb


    【解决方案1】:

    我的解决方案受到了这个版本的启发 qserver.c from github

    Yang 增加了两个函数:convert_binary,convert_r 对数据进行[反]序列化,基本上就是你想要的。但是,返回值是一个十六进制数组。要与现有的执行功能结合,我们需要使用 paste(collapse="") 转换成字符串,然后使用 sprintf 执行。下面是例子,它将R中的robj发送到kdb中的d:

    execute(h, sprintf("d:-9!0x%s",paste(convert_r(robj),collapse="")))
    

    问题是如果数组很大,paste(collapse="") 需要相当长的时间。

    robj 是 r 对象。例如我用 data.frame (dim = 60,000x100) 尝试了它。 convert_r() 转换耗时 paste(collapse="") 用了 13s 转换成一个字符串,然后 execute(h, ...) 用了

    我还没有找到任何人编写了通过序列化二进制数据将 R 数据发送到 kdb 的函数(我不知道为什么),所以我自己做了一个。代码如下:

    SEXP kx_r_send_data(SEXP connection, SEXP robj, SEXP varname)
    {
      K result, conversion, serialized;
      kx_connection = INTEGER_VALUE(connection);
      conversion = from_any_robject(robj);
      serialized = b9(2, conversion);
      result = k(kx_connection, "{[d;v] v set -9!d;}", r1(serialized), ks((S)CHARACTER_VALUE(varname)), (K)0);
      SEXP s = from_any_kobject(result);
      r0(result);
      r0(conversion);
      r0(serialized);
      return s;
    }
    

    我假设你有修改 qserver.c 和重新编译 qserver.o 的知识 然后在 qserver.R 中添加一个函数:

    send_data <- function(connection, r_obj, varname) {
      .Call("kx_r_send_data", as.integer(connection), r_obj, varname)
    }
    

    这才是在 C 级别通过序列化二进制将 R 数据发送到 kdb 的真正方式。

    注意:

    1) 转换不适用于 data.table,因为它不是标准的 R 类。用data.table调用函数会导致segmentation fault

    2) 序列化不知道如何转换 date/datetime 类型的对象。转入kdb后,序列化会使其全部0N

    除非你想实现从 R 到 K 的 date/datetime/data.table 转换,不要调用 convert_r()send_data() 这些类型的函数。

    另一方面,有一个快速的解决方法。对于data.table,只需在调用函数之前使用as.data.frame 将其转换为data.frame 类。 对于日期/日期时间类,使用 as.character() 在发送到 kdb 之前转换为字符串。然后直接在 KDB 中转换为“D”或“P”。

    3) 序列化的data.frame中包含了行、行名、类信息等其他信息,需要在传输后对kdb内部的数据进行操作。

    我建议编写一个 R 包装函数来处理这些异常情况,然后调用 send_data() 将数据传递给 kdb。然后使用 execute(h, ...) 将数据操作成 kdb 内部的标准格式。

    相同的数据 (60,000x100) 现在需要

    PS> 我可能在代码中有错字,因为我不知道如何在此处粘贴漂亮的代码。我实际上是把它打出来的。如果您在代码中发现任何严重的拼写错误,请告诉我

    【讨论】:

    • 我的代码有两个参数的 ks。 1. (S)CHARACTER_VALUE(varname),将“varname”转换为 SEXP 类型的字符, 2. (K)0 ,取整型并 regrun 作为 K 对象。此外,"S" 类型是大写的,它是 SEXP 类型,即您需要包含 "rserver.c" 和 "qserver.c" 才能工作。查看“来自 github 的 qserver.c”中的 base.c 以了解如何设置要编译的 env。对于您的 k 括号,您能否检查一下代码中某处是否有错字@statquant
    【解决方案2】:

    与 R 中的 kdb 交互最“稳定”的方式是使用字符串查询接口。如果您想要实际的对象 [反] 序列化,那么建议您查看 C 接口并从 R 调用该库以与 KDB 交互。

    【讨论】:

    • 感谢您的洞察力。鉴于我不熟悉 C 并且公共领域中不存在这样的 R/Rcpp 包装器,社区中的任何人都会有兴趣发布这样做的 R 包吗?我什至会在经济上支持它。
    • 我也不是,否则我愿意这样做:) 这里有一些关于将库加载到 R 中的信息,我的一位同事之前已经非常成功地完成了:users.stat.umn.edu/~geyer/rc
    • 使用字符串查询接口只有在从kdb中提取数据而不是在kdb中插入大数据时才有效。我上面提供的是用于插入的。其他一些方法是设置一个 Rserver,然后从 RServer 拉取 kdb 端的数据。但这是我试图避免的另一层设置。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-27
    • 2016-03-24
    相关资源
    最近更新 更多