44# in-memory direct functionality
55
66
7-
7+ # ' @importFrom stats as.formula
8+ NULL
89
910
1011# ' Build a blocks_to_rowrecs()/rowrecs_to_blocks() control table that specifies a pivot from a \code{data.frame}.
@@ -87,6 +88,36 @@ build_unpivot_control <- function(nameForNewKeyColumn,
8788}
8889
8990
91+ # unpack control table into maps
92+ build_transform_maps <- function (controlTable ) {
93+ cCheck <- checkControlTable(controlTable , FALSE )
94+ if (! is.null(cCheck )) {
95+ stop(paste(" cdata:::build_transform_maps" , cCheck ))
96+ }
97+ # use control table to get into a triple-form (only one data column, all others keys).
98+ cells <- as.character(unlist(unlist(controlTable [, - 1 ])))
99+ cells_to_row_labels <- controlTable
100+ for (i in 1 : nrow(controlTable )) {
101+ cells_to_row_labels [i , ] <- cells_to_row_labels [i , 1 ]
102+ }
103+ cells_to_row_labels <- as.character(unlist(cells_to_row_labels [, - 1 ]))
104+ names(cells_to_row_labels ) <- cells
105+ cells_to_col_labels <- controlTable
106+ for (j in 2 : ncol(controlTable )) {
107+ cells_to_col_labels [, j ] <- colnames(controlTable )[[j ]]
108+ }
109+ cells_to_col_labels <- as.character(unlist(cells_to_col_labels [, - 1 ]))
110+ names(cells_to_col_labels ) <- cells
111+ rows_cols_to_cells <- cells
112+ names(rows_cols_to_cells ) <- paste(cells_to_row_labels , " ," , cells_to_col_labels )
113+ list (
114+ cells = cells ,
115+ cells_to_row_labels = cells_to_row_labels ,
116+ cells_to_col_labels = cells_to_col_labels ,
117+ rows_cols_to_cells = rows_cols_to_cells
118+ )
119+ }
120+
90121
91122# ' Map a set of columns to rows (takes a \code{data.frame}).
92123# '
@@ -122,6 +153,7 @@ build_unpivot_control <- function(nameForNewKeyColumn,
122153# ' @param columnsToCopy character array of column names to copy
123154# ' @param checkNames logical, if TRUE check names
124155# ' @param strict logical, if TRUE check control table name forms
156+ # ' @param use_data_table logical if TRUE try to use data.table for the pivots.
125157# ' @return long table built by mapping wideTable to one row per group
126158# '
127159# ' @seealso \code{\link{build_unpivot_control}}, \code{\link{blocks_to_rowrecs_q}}
@@ -143,14 +175,16 @@ rowrecs_to_blocks <- function(wideTable,
143175 ... ,
144176 checkNames = TRUE ,
145177 strict = FALSE ,
146- columnsToCopy = NULL ) {
178+ columnsToCopy = NULL ,
179+ use_data_table = TRUE ) {
147180 wrapr :: stop_if_dot_args(substitute(list (... )), " cdata::rowrecs_to_blocks" )
148181 if (! is.data.frame(wideTable )) {
149182 stop(" cdata::rowrecs_to_blocks wideTable shoud be a data.frame" )
150183 }
151184 if (! is.data.frame(controlTable )) {
152185 stop(" cdata::rowrecs_to_blocks controlTable shoud be a data.frame" )
153186 }
187+ rownames(wideTable ) <- NULL
154188 cCheck <- checkControlTable(controlTable , strict )
155189 if (! is.null(cCheck )) {
156190 stop(paste(" cdata::rowrecs_to_blocks" , cCheck ))
@@ -165,6 +199,35 @@ rowrecs_to_blocks <- function(wideTable,
165199 paste(badCells , collapse = ' , ' )))
166200 }
167201 }
202+
203+ if ( use_data_table &&
204+ requireNamespace(" data.table" , quietly = TRUE ) &&
205+ requireNamespace(" reshape2" , quietly = TRUE ) ) {
206+ maps <- build_transform_maps(controlTable )
207+
208+ # from rowrec to one value per row form (triple-like)
209+ d_thin_r <- data.table :: melt(data.table :: as.data.table(wideTable ),
210+ variable.name = " cdata_cell_label" ,
211+ value.name = " cdata_cell_value" ,
212+ id.vars = columnsToCopy ,
213+ measure.vars = maps $ cells )
214+ d_thin_r $ cdata_row_label <- maps $ cells_to_row_labels [d_thin_r $ cdata_cell_label ]
215+ d_thin_r $ cdata_col_label <- maps $ cells_to_col_labels [d_thin_r $ cdata_cell_label ]
216+
217+ # cast to block form
218+ f <- paste0(paste(c(columnsToCopy , " cdata_row_label" ), collapse = " + " ), " ~ " , " cdata_col_label" )
219+ r <- data.table :: dcast(d_thin_r , as.formula(f ), value.var = " cdata_cell_value" )
220+ colnames(r )[which(colnames(r )== " cdata_row_label" )] <- colnames(controlTable )[[1 ]]
221+ rownames(r ) <- NULL
222+ return (as.data.frame(r ))
223+ }
224+
225+ if ( use_data_table ) {
226+ warning(" cdata::rowrecs_to_blocks use_data_table==TRUE requires data.table and reshape2 packages" )
227+ }
228+
229+ # fall back to local impl
230+
168231 n_row_in <- nrow(wideTable )
169232 n_rep <- nrow(controlTable )
170233 n_row_res <- n_rep * n_row_in
@@ -194,6 +257,7 @@ rowrecs_to_blocks <- function(wideTable,
194257 res [[cn ]][indxs ] <- wideTable [[col ]]
195258 }
196259 }
260+ rownames(res ) <- NULL
197261 res
198262}
199263
@@ -233,6 +297,7 @@ rowrecs_to_blocks <- function(wideTable,
233297# ' @param columnsToCopy character, extra columns to copy (aribrary which row per group).
234298# ' @param checkNames logical, if TRUE check names
235299# ' @param strict logical, if TRUE check control table name forms
300+ # ' @param use_data_table logical if TRUE try to use data.table for the pivots.
236301# ' @return wide table built by mapping key-grouped tallTable rows to one row per group
237302# '
238303# ' @seealso \code{\link{build_pivot_control}}, \code{\link{rowrecs_to_blocks_q}}
@@ -258,14 +323,23 @@ blocks_to_rowrecs <- function(tallTable,
258323 ... ,
259324 columnsToCopy = NULL ,
260325 checkNames = TRUE ,
261- strict = FALSE ) {
326+ strict = FALSE ,
327+ use_data_table = TRUE ) {
262328 wrapr :: stop_if_dot_args(substitute(list (... )), " cdata::blocks_to_rowrecs" )
263329 if (! is.data.frame(tallTable )) {
264330 stop(" cdata::blocks_to_rowrecs tallTable shoud be a data.frame" )
265331 }
266332 if (! is.data.frame(controlTable )) {
267333 stop(" cdata::blocks_to_rowrecs controlTable shoud be a data.frame" )
268334 }
335+ rownames(tallTable ) <- NULL
336+ clear_key_column <- FALSE
337+ if (length(keyColumns )< = 0 ) {
338+ # avoid no-keys case
339+ tallTable $ cdata_key_column <- 1
340+ keyColumns <- " cdata_key_column"
341+ clear_key_column <- TRUE
342+ }
269343 cCheck <- checkControlTable(controlTable , strict )
270344 if (! is.null(cCheck )) {
271345 stop(paste(" cdata::blocks_to_rowrecs" , cCheck ))
@@ -278,6 +352,38 @@ blocks_to_rowrecs <- function(tallTable,
278352 paste(badCells , collapse = ' , ' )))
279353 }
280354 }
355+
356+ if ( use_data_table &&
357+ requireNamespace(" data.table" , quietly = TRUE ) &&
358+ requireNamespace(" reshape2" , quietly = TRUE ) ) {
359+ maps <- build_transform_maps(controlTable )
360+
361+ # from block form to one value per row form (triple-like)
362+ d_thin_b <- data.table :: melt(data.table :: as.data.table(tallTable ),
363+ variable.name = " cdata_col_label" ,
364+ value.name = " cdata_cell_value" ,
365+ id.vars = c(keyColumns , colnames(controlTable )[[1 ]]),
366+ measure.vars = colnames(controlTable )[- 1 ])
367+ d_thin_b $ cdata_row_label <- d_thin_b [[colnames(controlTable )[[1 ]]]]
368+ d_thin_b [[colnames(controlTable )[[1 ]]]] <- NULL
369+ d_thin_b $ cdata_cell_label <- maps $ rows_cols_to_cells [paste(d_thin_b $ cdata_row_label , " ," , d_thin_b $ cdata_col_label )]
370+
371+ # cast to rowrec form
372+ f <- paste0(paste(keyColumns , collapse = " + " ), " ~ " , " cdata_cell_label" )
373+ r <- data.table :: dcast(d_thin_b , as.formula(f ), value.var = " cdata_cell_value" )
374+ if (clear_key_column ) {
375+ r $ cdata_key_column <- NULL
376+ }
377+ rownames(r ) <- NULL
378+ return (as.data.frame(r ))
379+ }
380+
381+ if ( use_data_table ) {
382+ warning(" cdata::blocks_to_rowrecs use_data_table==TRUE requires data.table and reshape2 packages" )
383+ }
384+
385+ # fall back to local impl
386+
281387 # make simple grouping keys
282388 tallTable $ cdata_group_key_col <- 1
283389 if (length(keyColumns )> = 1 ) {
@@ -312,6 +418,7 @@ blocks_to_rowrecs <- function(tallTable,
312418 }
313419 }
314420 res $ cdata_group_key_col <- NULL
421+ rownames(res ) <- NULL
315422 res
316423}
317424
0 commit comments