2016-07-07 3 views
2

Rpostgresqlを使用してRコードをPL/Rコードに変換しようとしていますが、postgreqlデータベースにデータをプッシュ/プルしないようにしています。postgresqlデータベースのPL/RコードにRコードをプッシュ

コードdata.tableにdcastさ:

#libs 
library(RPostgreSQL); 
library(data.table); 

# connect 
drv <- dbDriver("PostgreSQL"); 
con <- dbConnect(drv, dbname="postgres", user="postgres"); 

# load 
cli_ranges <- dbGetQuery(con, "SELECT custid, prod_ranges, is_cli from cli_ranges;") 

# DT 
setDT(cli_ranges) 
setkeyv(cli_ranges , c("prod_ranges")) 

# pivot 
cli_ranges.pivoted <- dcast(cli_ranges, custid ~ paste0("is_cli_", prod_ranges), fun=sum, value.var = "is_cli") 

# send back to DB 
dbWriteTable(con, "cli_ranges_pivoted", cli_ranges.pivoted, row.names=F) 

コードRでは、高速&正常に動作しています。

私は今、PL/R機能にコードをプッシュしようとしています

CREATE OR REPLACE FUNCTION public.pivot() 
    RETURNS void AS 
$BODY$ 

[copy/paste R code] 

$BODY$ 
    LANGUAGE plr; 

...しかし、Rコード(dbWriteTable)の最後の行はスロー:

ERROR: R interpreter expression evaluation error 
DETAIL: Error in (function (classes, fdef, mtable) : 
    unable to find an inherited method for function 'dbWriteTable' for signature '"logical", "character", "data.frame"' 
CONTEXT: In PL/R function pivot 

変更データフレーム(as.data.frame(cli_ranges.pivoted))へのdata.tableも機能しません。 ...

1つのトリックはCREATE TABLE cli_ranges_pivoted AS SELECT pivot();を実行するためにdata.table /フレームを返すようにすることでしたが、私は実際に出力としてdata.frameをプッシュする方法がわからない

cli_ranges表:

dcast(すなわち旋回)datafram後
custid prod_ranges is_cli 
1  A   1 
1  B   1 
1  C   0 
2  A   1 
2  B   0 
2  C   1 
3  A   0 
3  B   1 
3  C   0 
4  A   1 
...  ...   ... 

は以下の通りである:

custid prod_ranges_A prod_ranges_B prod_ranges_C 
1  1    1    0 
2  1    0    1 
3  0    1    0 
4  1    ... 
... 

prod_rangesチャンにおける個別値の数多くの場合、旋回後の列数をあらかじめ定義することができます。

ENV:Postgresqlの9.5、R 3.3、PL/R 08.03.00.16、10勝64-ビット

答えて

1

あなたはhttp://gpdb.docs.pivotal.io/4330/ref_guide/pl_r.html例であなたが好きアンネスト機能を変更してみてください2及び3

かを、開始することができLukas EklundとErwind Brandstetterはこの記事で(私はLukasのソリューションを使っています) Unnest array by one levelでした。

CREATE OR REPLACE FUNCTION unnest_multidim(anyarray) 
RETURNS SETOF anyarray AS 
$BODY$ 
    SELECT array_agg($1[series2.i][series2.x]) FROM 
    (SELECT generate_series(array_lower($1,2),array_upper($1,2)) as x, series1.i 
    FROM 
    (SELECT generate_series(array_lower($1,1),array_upper($1,1)) as i) series1 
    ) series2 
GROUP BY series2.i 
$BODY$ 
LANGUAGE sql IMMUTABLE; 

、その後、あなたは配列を返すしてみてください、そしてこのような何か行うことができます:私はdbWriteTableが、それは次のように意図されたように動作するように得ることができなかった

CREATE OR REPLACE FUNCTION r_norm(n integer, mean float8, std_dev float8) 
RETURNS float8[] 
AS $$ 
x<-rnorm(n,mean,std_dev); 
y<-rnorm(n,mean,std_dev); 
final<-cbind(as.data.frame(x), as.data.frame(y)); 
return(final) 

$$ LANGUAGE 'plr'; 

CREATE TABLE test_norm_var AS SELECT R_output[1] as col1, R_output[2] as col2 FROM unnest_multidim(r_norm(10,0,1)) R_output; 

SELECT col1 FROM test_norm_var; 

EDIT

をPL/R関数... しかし、この方法を試すこともできます。

CREATE OR REPLACE FUNCTION pivot() 
    RETURNS VOID as $$ 

library(RPostgreSQL); 
library(data.table); 

drv <- dbDriver("PostgreSQL"); 
con <- dbConnect(drv, dbname ="postgres"); 

fields <- list(custid = "numeric",prod_ranges = "varchar(128)", is_cli = "numeric") 

custid <- c(1,1,1,2,2,2) 
prod_ranges <- c("A","B","C","A","B","C") 
is_cli <- c(1,1,0,1,0,1) 

cli_ranges <- data.frame(custid,prod_ranges,is_cli, stringsAsFactors = default.stringsAsFactors()) 

setDT(cli_ranges) 
setkeyv(cli_ranges , c("prod_ranges")) 

cli_ranges.pivoted <- as.data.frame(dcast(cli_ranges, custid ~ paste0("is_cli_", prod_ranges), fun=sum, value.var = "is_cli")) 

create_query <- paste0("CREATE TABLE cli_ranges (",paste0(colnames(cli_ranges.pivoted), collapse = " numeric, "), 
" numeric) DISTRIBUTED BY (",colnames(cli_ranges)[1],")") 

dbGetQuery(con, create_query); 

values_string <- "(" 
for (i in 1:dim(cli_ranges.pivoted)[1]){ 
for (j in 1:dim(cli_ranges.pivoted)[2]){ 
    if (j != dim(cli_ranges.pivoted)[2]) { 
     values_string <- paste0(values_string,cli_ranges.pivoted[i,j],",") 
    } else { 
     values_string <- paste0(values_string,cli_ranges.pivoted[i,j]) 
    } 
    } 
    if (i != dim(cli_ranges.pivoted)[1]){ 
     values_string <- paste0(values_string,"),(") 
    } else { 
     values_string <- paste0(values_string,")") 
    } 
} 

insert_query <- paste0("INSERT INTO cli_ranges (",paste0(colnames(cli_ranges.pivoted), collapse = ", "), 
") VALUES ", values_string) 

dbGetQuery(con, insert_query); 

$$ LANGUAGE plr; 
+0

問題は 'prod_ranges'の数が時間の経過と共に変化することです。つまり、' prod_ranges'値にテーブルを転記する 'dcast'の結果の列数を定義できません。 – ant1j

+0

dcastや出力へのあなたの入力(偽の数字を記入するなど)? – DDrake

+0

イラストは元の質問 – ant1j