R - > kdb:将R数据作为二进制对象传递给kdb +

时间:2014-12-27 22:42:57

标签: r ipc kdb

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

我能够通过herehere所述的kdb+表达式找到仅涉及字符串序列化的解决方案。

2 个答案:

答案 0 :(得分:3)

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

杨添加了两个函数:convert_binary,convert_r [de]序列化数据,这基本上就是你要求的。但是,返回值是十六进制数组。要与现有的执行函数合并,我们需要使用 paste(collapse ="")转换为字符串,然后使用 sprintf 执行。以下是示例,它将r中的robj发送到kdb中的d:

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

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

robj是r对象。例如我尝试使用data.frame(dim = 60,000x100)。 convert_r()采取< 0.5s转换; 粘贴(折叠="")花费13秒转换为单个字符串,然后执行(h,...)采取< 1s来传输数据。

我没有找到任何编写过函数的人通过序列化二进制数据向Rdb发送R数据(我不知道为什么),所以我自己创建了一个。这是代码:

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调用函数将导致分段错误

2)序列化不知道如何转换日期/日期时间类型的对象。传输到kdb后,序列化将使所有 0N

除非你想实现从R到K的日期/日期时间/数据。表转换,否则不要调用 convert_r() send_data()< / em>这些类型的函数。

另一方面,有一个快速的解决方法。对于data.table,只需在调用函数之前使用 as.data.frame 将其转换为data.frame类。 对于date / datetime类,在发送到kdb之前使用 as.character()转换为字符串。然后施展到&#34; D&#34;或&#34; P&#34;在KDB里直接。

3)序列化data.frame包括其他信息,如行,行名,类信息等。您需要在传输后操作kdb内的数据。

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

相同的数据(60,000x100)现在需要&lt; 1到完成,从R到kdb端到端。

PS&GT;我可能在代码中输入了一个拼写错误,因为我不知道如何粘贴漂亮的代码。我实际上输入了它。如果您在代码

中发现任何重大错误,请与我们联系

答案 1 :(得分:0)

最稳定的&#34;从R与kdb交互的方法是使用字符串查询接口。如果你想要实际的对象[de]序列化,那么建议你查看C接口并从R调用该lib以与KDB交互。