The groupedapply mode
This mode is equivalent to the tapply mode, but it can be executed
without the nzLibrary for R client package. It exhibits similar behavior, but
enables you to run an aggregating table function and use an arbitrary SQL query, so long as it
conforms with some basic requirements.
The R file must contain:
- nz.mode
- Set to
groupedapply. - nz.fun
- The function run on processed groups.
The R file might additionally contain:
- nz.shaper
- The shaper function; required if output set to TABLE(ANY).
- nz.shaper.args
- Optional.
- nz.shaper.list
- Required if
shaperis set tostd.
This R source file might undergo the usual compilation and registration steps, or can be used directly as described In the Communication Channels section.
When a selection is made, move to the next step, which is the SQL
query:
SELECT ae_output_t.* FROM (SELECT
ROW_NUMBER() OVER (PARTITION BY pp ORDER BY oo) AS rn,
COUNT(*) OVER (PARTITION BY pp) AS ct,
tt.*
FROM tt) as input_t,
TABLE WITH FINAL (nzr..r_udtf_any(rn, ct, tt.cc,...,
'<R code>')) as ae_output_t;The noteworthy elements are:- tt
- The input table.
- rn and ct
- The control columns, which are processed by Netezza R code that is invoked when the
groupedapplymode is chosen. - r_udtf_any
- The R Adapter UTDF, which is a standard UDTF that internally invokes R and returns TABLE(ANY).
The control columns are used to determine when a new partition starts and ends. The internal R
loop looks similar to:
while (getNext()) {
rn <- getInputColumn(0)
ct <- getInputColumn(1)
if (rn == 1) {
# create a new data frame for this partition
}
# fetch the current row
if (ct == rn) {
# process the frame calling the user-provided
# function and return the function result
}
}The R loop assumes that the first two columns are the row number and the row count.
Based on their values, it creates a data.frame for each new data partition. When
the number of rows reaches the total count, the user function is called and the frame is passed as
its argument under the name of x.As an example, consider the contents of
grpdapp.R, which should then be saved
under
/nz/export/ae/workspace:nz.fun <- function(x)return(mean(x))
nz.mode <- 'groupedapply'
nz.shaper <- 'std'
nz.shaper.list <- list(a=NZ.DOUBLE, b=NZ.DOUBLE,
c=NZ.DOUBLE, d=NZ.DOUBLE)Given there is a table named iris (that is a copy of the standard R data set), you can call the
following query:
SELECT ae_output_t.* FROM (SELECT
ROW_NUMBER() OVER (PARTITION BY species ORDER BY sepal_length) AS rn,
COUNT(*) OVER (PARTITION BY species) AS ct,
iris.*
FROM iris) AS input_t,
TABLE WITH FINAL
(nzr..r_udtf_any(rn, ct, sepal_length, sepal_width,
petal_length, petal_width,
CAST('PLAIN_PATH=/nz/export/ae/workspace/grpdapp.R' AS
VARCHAR(64)))) AS ae_output_t;which produces output similar to:A | B | C | D
-------+-------+-------+-------
6.588 | 2.974 | 5.552 | 2.026
5.006 | 3.428 | 1.462 | 0.246
5.936 | 2.77 | 4.26 | 1.326
(3 rows)The same results can be achieved with the following
query:SELECT ae_output_t.* FROM (SELECT
ROW_NUMBER() OVER (PARTITION BY species ORDER BY sepal_length) AS rn,
COUNT(*) OVER (PARTITION BY species) AS ct,
iris.*
FROM iris) AS input_t,
TABLE WITH FINAL
(nzr..r_udtf_any(rn, ct, sepal_length, sepal_width, petal_length, petal_width,
CAST('CODE_PLAIN="return(mean(x))", MODE=groupedapply,
SHAPER_LIST="a=NZ.DOUBLE,b=NZ.DOUBLE,c=NZ.DOUBLE,
d=NZ.DOUBLE"'
AS VARCHAR(128)))) AS ae_output_t;