2014-10-16 11 views
5

Tôi có một số lớn data.frame (15 cột và 100.000 hàng) trong phiên R hiện có mà tôi muốn gửi đến một phiên bản Q/KDB. Từ KDB's cookbook, các giải pháp có thể là:Làm thế nào để gửi một data.frame từ R đến Q/KDB?

RServer for Q: sử dụng KDB để tạo phiên bản R mới dùng chung bộ nhớ. Điều này không làm việc vì dữ liệu của tôi là trong một dụ hiện của R.

RServe: chạy một máy chủ R và sử dụng giao thức TCP/IP để giao tiếp với Q/KDB khách hàng. Điều này không có tác dụng, bởi vì theo RServe's documentation, "mọi kết nối đều có không gian làm việc riêng và thư mục làm việc" và vì vậy tôi giả sử không thấy dữ liệu hiện có của mình.

R Math Library: Chức năng truy cập R của thông qua một thư viện toán học mà không cần một thể hiện của R. này không hoạt động, vì dữ liệu của tôi là đã có trong một thể hiện của R.

Vì vậy, bất kỳ ý tưởng khác về cách để gửi dữ liệu từ R đến Q/KDB?

Trả lời

2

mở một cổng ở Q. Tôi bắt đầu Q với một tập tin batch:

@echo off 
c:\q\w32\q -p 5001 

tải qserver.dll

tryCatch({ 
dyn.load("c:/q/qserver.dll")} 
    ,error = function(f){ 
    print("can't load qserver.dll") 
    }) 

Sau đó, sử dụng các

open_connection <- function(host="localhost", port=5001, user=NULL) { 
     parameters <- list(host, as.integer(port), user) 
     h <- .Call("kx_r_open_connection", parameters) 
    assign(".k.h", h, envir = .GlobalEnv) 
    return(h) 
} 

close_connection <- function(connection) { 
     .Call("kx_r_close_connection", as.integer(connection)) 
} 

execute <- function(connection, query) { 
     .Call("kx_r_execute", as.integer(connection), query) 
} 

d<<-open_connection(host="localhost",port=thePort) 

ex2 <- function(...) 
{ 
    query <- list(...) 
    theResult <- NULL 
    for(i in query) theResult <- paste0(theResult,i) 
    return(execute(d,paste0(theResult))) 
} 

sau đó EX2 có thể mất nhiều đối số để bạn có thể tạo truy vấn với các biến và chuỗi R

Edit: thats cho R từ Q, heres R để Q

2 Edit: cải thiện algo:

library(stringr) 
    RToQTable <- function(Rtable,Qname,withColNames=TRUE,withRowNames=TRUE,colSuffix = NULL) 
{ 
    theColnames <- if(!withColNames || length(colnames(Rtable))==0) paste0("col",as.character(1:length(Rtable[1,])),colSuffix) else colnames(Rtable) 
    if(!withRowNames || length(rownames(Rtable))==0) withRowNames <- FALSE 
    Rtable <- rbind(Rtable,"linesep") 
    charnum <- as.integer(nchar(thestr <- paste(paste0(theColnames,':("',str_split(paste(Rtable,collapse='";"'),';\"linesep\";\"')[[1]],');'),collapse="")) - 11) 
    if(withRowNames) 
    ex2(Qname,":([]",Qname,str_replace_all(paste0("`",paste(rownames(Rtable),collapse="`"))," ","_"),";",.Internal(substr(thestr,1L,charnum)),"))") else 
    ex2(Qname,":([]",.Internal(substr(thestr,1L,charnum)),"))") 
} 

> bigMat <- matrix(runif(1500000),nrow=100000,ncol=15) 
> microbenchmark(RToQTable(bigMat,"Qmat"),times=3) 
Unit: seconds 
         expr  min  lq  mean median  uq  max neval 
RToQTable(bigMat, "Qmat") 10.29171 10.315 10.32766 10.33829 10.34563 10.35298  3 

này sẽ làm việc cho một ma trận, vì vậy đối với một khung dữ liệu chỉ cần lưu một vector chứa các loại của mỗi cột, sau đó chuyển đổi khung dữ liệu thành ma trận, nhập ma trận thành Q và nhập các loại

Lưu ý rằng thuật toán này xấp xỉ O (hàng * cols^1.1), do đó bạn cần phải cắt các cột thành nhiều ma trận nếu bạn có nhiều hơn 20 để nhận được O (hàng * cols)

nhưng đối với ví dụ 150.000 hàng và 15 cột của bạn mất 10 giây để tối ưu hóa thêm có thể không cần thiết.

+1

Cảm ơn, nhưng giải pháp của bạn chỉ nói về ** truy vấn Q từ bên trong R ** bằng [Q-Server for R] (http://code.kx.com/wiki/Cookbook/IntegratingWithR#Calling_kdb.2B_from_R). Tôi cần gửi một 'data.frame' với 15 cột và 100.000 hàng ** từ R đến Q **. Bạn có thể chứng minh việc gửi một 'data.frame' lớn từ R đến Q không? – mchen

+0

Rất tiếc, tôi sẽ chỉnh sửa – hedgedandlevered

+0

Trợ giúp này có hữu ích không? xin vui lòng chấp nhận nếu như vậy, nếu không cho tôi biết những gì tôi có thể thêm – hedgedandlevered

Các vấn đề liên quan