diff --git a/CRAN-SUBMISSION b/CRAN-SUBMISSION deleted file mode 100644 index acf7ac38..00000000 --- a/CRAN-SUBMISSION +++ /dev/null @@ -1,3 +0,0 @@ -Version: 0.1.17 -Date: 2025-03-02 08:04:21 UTC -SHA: a3c09fdbce18b9424775820d9d01304294ea806f diff --git a/DESCRIPTION b/DESCRIPTION index 1289d6b2..61f1d07e 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -16,8 +16,8 @@ Description: Analyze repertory grids, a qualitative-quantitative to quantitatively analyze and visualize repertory grid data (e.g. 'Fransella', 'Bell', & 'Bannister', 2004, ISBN: 978-0-470-09080-0). The package is part of the The package is part of the project. -Version: 0.1.18.9006 -Date: 2025-05-12 +Version: 0.1.18 +Date: 2025-07-08 Encoding: UTF-8 URL: https://github.com/markheckmann/OpenRepGrid Imports: diff --git a/NAMESPACE b/NAMESPACE index 563e040f..73c9de28 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -99,13 +99,15 @@ export(getNoOfElements) export(getRatingLayer) export(getScale) export(getScaleMidpoint) +export(grid_to_df_long) +export(grid_to_df_wide) export(gridlist) export(grids_bootstrap) export(grids_leave_n_out) export(grids_perturbate) export(home) +export(importDataframe) export(importExcel) -export(importExcelInternal) export(importGridcor) export(importGridcorInternal) export(importGridstat) @@ -115,7 +117,6 @@ export(importGridsuiteInternal) export(importScivesco) export(importScivescoInternal) export(importTxt) -export(importTxtInternal) export(indexBias) export(indexBieri) export(indexConflict1) @@ -177,6 +178,7 @@ export(ring) export(sapply_pb) export(saveAsExcel) export(saveAsTxt) +export(saveAsWorksheet) export(setConstructAttr) export(setElementAttr) export(setMeta) diff --git a/NEWS.md b/NEWS.md index fa1fdb08..5a21f3e2 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,13 @@ -# OpenRepGrid 0.1.18 (dev version) - +# OpenRepGrid 0.1.18 + +* `saveAsExcel` can export a list of grids now (#67) +* `saveAsWorksheet` adds a grid as a new sheet to a `openxlsx` `Workbook` object. +* `makeGrid` and `randomGrid` can add construct pole preference. +* `importExcel` now also understands the long format (#65) and can import from several sheets at once (#68) +* `importDataframe` converts a dataframe into a repgrid. Three different formats can be read in. See the sample + dataframes `df_element_columns`, `df_construct_columns`, and `df_long` (#61) +* `saveAsExcel` now supports output in wide and long format. The output is also formatted now (#64) +* `bertinCluster`: now restores the original `par()` settings after changing the plot layout (#63) * `importTxt` reads preferred poles from section `PREFERRED`, `importExcel` reads rightmost column `preferred_poles` (#57) * `preferredPoles` sets the preferred construct poles, `preferredPolesByIdeal` sets the preferred pole bases on the ideal elements ratings, `alignByPreferredPole` aligns constructs by pole preference (#57) diff --git a/R/bertin.r b/R/bertin.r index 9ac5f1fb..fcdba876 100644 --- a/R/bertin.r +++ b/R/bertin.r @@ -335,7 +335,7 @@ bertinBase <- function(nrow, ncol, labels = "", labels.elements = "", } colorRow <- function(cr) { - par(new = TRUE) # next plot will overplot not earse the old one, necessary for setting the same regions + old_par <- par(new = TRUE) # next plot will overplot not erase the old one, necessary for setting the same regions plot.new() # plot.window(xlim=0:1, ylim=0:1) #, xaxs="i", yaxs="i")#, asp =nrow/ncol) if (cr >= 1 & cr <= nrow) { # color current row cr @@ -348,10 +348,11 @@ bertinBase <- function(nrow, ncol, labels = "", labels.elements = "", labels = labels.rows, col = col.mark.text, cex = cex.text ) } + par(old_par) } colorColumn <- function(cc) { - par(new = TRUE) # next plot will overplot not earse the old one, necessary for setting the same regions + old_par <- par(new = TRUE) # next plot will overplot not earse the old one, necessary for setting the same regions plot.new() # plot.window(xlim=0:1, ylim=0:1) #, xaxs="i", yaxs="i")#, asp =nrow/ncol) if (cc >= 1 & cc <= ncol) { # color current column cc @@ -373,6 +374,7 @@ bertinBase <- function(nrow, ncol, labels = "", labels.elements = "", segments(x.lines[cc], y1.lines, x.lines[cc], y2.lines[cc], lwd = 3, col = "white") # overplot old stroke in white segments(x.lines[cc], y1.lines, x.lines[cc], y2.lines[cc], col = col.mark.fill) } + par(old_par) } renewColumn <- function(cc) { @@ -440,7 +442,7 @@ bertinBase <- function(nrow, ncol, labels = "", labels.elements = "", # set plotting parameters # old.par <- par(no.readonly = TRUE) # save parameters # on.exit(par(old.par)) # reset old par when done - op <- par(oma = rep(0, 4), mar = rep(0, 4), xaxs = "i", yaxs = "i") + old_par <- par(oma = rep(0, 4), mar = rep(0, 4), xaxs = "i", yaxs = "i") if (print) { # in case no new printing should occur par(new = FALSE) } else { @@ -466,7 +468,7 @@ bertinBase <- function(nrow, ncol, labels = "", labels.elements = "", colorRow(cr) colorColumn(cc) } - # par(op) + par(old_par) invisible(NULL) } @@ -786,16 +788,14 @@ bertinCluster <- function(x, dmethod = c("euclidean", "euclidean"), x <- x[con.ord, el.ord] # reorder repgrid object + old_par <- par(fig = c(xsegs[c(1, 4)], ysegs[c(2, 4)])) plot.new() - par(fig = c(xsegs[c(1, 4)], ysegs[c(2, 4)]), new = TRUE) - # par(fig = c(0, .8, .2, 1), new=T) - - bertin(x, xlim = xlim.bertin, ylim = ylim.bertin, add = TRUE, ...) # print reordered bertin + bertin(x, xlim = xlim.bertin, ylim = ylim.bertin, add = FALSE, ...) # print reordered bertin # x dendrogram (horizontal) elements if (!is.na(cmethod[2])) { dend.x.fig <- c(xsegs[2:3], ysegs[1:2]) + c(0, 0, y.off, -y.off) # adjust for offsets - par(fig = dend.x.fig, new = T, mar = c(0, 0, 0, 0)) + par(fig = dend.x.fig, new = TRUE, mar = c(0, 0, 0, 0)) # trick: new = TRUE avoids opening a new plot window in next plot ymax.el <- attr(dend.el, "height") plot(dend.el, horiz = F, xlab = "", xaxs = "i", yaxs = "i", yaxt = "n", @@ -819,17 +819,7 @@ bertinCluster <- function(x, dmethod = c("euclidean", "euclidean"), axis(1, las = 1, cex.axis = cex.axis, col = col.axis, col.axis = col.axis) } } + par(old_par) # return hclust objects for elements and constructs invisible(list(constructs = fit.constructs, elements = fit.elements)) } - -# TODO: use of layout does not work with bertinCluster -# a future version could use layout -# layout (matrix(1:4), 2) -# bertinCluster(bell2010) - -# bertinCluster(bell2010, type="t", bor=grey(.5)) -# dev.new() -# bertinCluster(bell2010, type="t", dm="manhattan", cm="single") -# dev.new() -# bertinCluster(bell2010, type="t", dm="manhattan", cm="centroid") diff --git a/R/data-openrepgrid.r b/R/data-openrepgrid.r index 89740731..12029b02 100644 --- a/R/data-openrepgrid.r +++ b/R/data-openrepgrid.r @@ -4,8 +4,10 @@ # # ////////////////////////////////////////////////////////////////////////////// +# _____________ ---- +# REPGRID ---- -# Bell (2010) ---- +## Bell (2010) ---- #' Grid data from Bell (2010). #' @@ -54,7 +56,7 @@ NULL # save("bell2010", file="../data/bell2010.RData") -# Bell and McGorry (1992) ---- +## Bell and McGorry (1992) ---- #' Grid data from Bell and McGorry (1992). #' @@ -112,7 +114,7 @@ NULL # save("bellmcgorry1992", file="../data/bellmcgorry1992.RData") -# Boeker (1996) ---- +## Boeker (1996) ---- #' Grid data from Boeker (1996). #' @@ -171,7 +173,7 @@ NULL # saveAsExcel(boeker, "inst/extdata/boeker.xlsx") -# Fransella, Bell & Bannister (2003) ---- +## Fransella, Bell & Bannister (2003) ---- #' Grid data from Fransella, Bell and Bannister (2003). #' @@ -211,7 +213,7 @@ NULL # save("fbb2003", file="../data/fbb2003.RData") -# Feixas and Saul (2004) ---- +## Feixas and Saul (2004) ---- #' Grid data from Feixas and Saul (2004). #' @@ -277,7 +279,7 @@ NULL -# Leach et al. (2001) ---- +## Leach et al. (2001) ---- #' Pre- and post therapy dataset from Leach et al. (2001). #' @@ -368,7 +370,7 @@ NULL -# Mackay (1992) ---- +## Mackay (1992) ---- #' Grid data from Mackay (1992). #' @@ -405,7 +407,7 @@ NULL # save("mackay1992", file="../data/mackay1992.RData") -# Raeithel (1998) ---- +## Raeithel (1998) ---- #' Grid data from Raeithel (1998). #' @@ -457,7 +459,7 @@ NULL -# Slater (1977a) ---- +## Slater (1977a) ---- #' Drug addict's grid data set from Slater (1977, p. 32). #' @@ -509,7 +511,7 @@ NULL # save("slater1977a", file="../data/slater1977a.RData") -# Slater (1977b) ---- +## Slater (1977b) ---- #' Grid data from Slater (1977). #' @@ -555,3 +557,118 @@ NULL # slater1977b <- makeRepgrid(args) # slater1977b <- setScale(slater1977b, 1, 10) # save("slater1977b", file="../data/slater1977b.RData") + + +# _____________ ---- +# DATAFRAME ---- + +## df_element_columns ---- + +#' Sample dataframe with grid data (elements are columns) +#' +#' This dataframe can be converted into a `repgrid` object via [importDataframe()]. The dataframe column names are the +#' minimum of the rating scale (`1`), the element names (`element_1` to `element_4`), the maximum of the rating scale +#' (`5`), and optionally a column indicating the `preferred` pole. Each row contains the constructs' entries (left +#' pole, ratings, right pole, preferred pole). The preferred pole must be one of `left`, `right`, `none`, `NA` (see +#' [preferredPoles()]). See sample data [df_element_columns]. +#' +#' \tabular{lccccrr}{ +#' `1` \tab `element_1` \tab `element_2` \tab `element_3` \tab `element_4` \tab `5` \tab `preferred` \cr +#' `left_pole_1` \tab `1` \tab `5` \tab `3` \tab `4` \tab `right_pole_1` \tab `left` \cr +#' `left_pole_2` \tab `3` \tab `1` \tab `1` \tab `3` \tab `right_pole_2` \tab `right` \cr +#' `left_pole_3` \tab `4` \tab `2` \tab `5` \tab `1` \tab `right_pole_3` \tab `none` \cr +#' } +#' @name df_element_columns +#' @family grid_dataframe +#' @docType data +#' @seealso [importDataframe()] +#' @keywords data +#' @examples +#' df_element_columns +#' importDataframe(df_element_columns) +NULL + +# # dataframe with columns as elements +# file <- system.file("extdata", "grid_01.xlsx", package = "OpenRepGrid") +# x <- importExcel(file) +# x <- x[1:3, 1:4] # smaller version +# df_element_columns <- grid_to_wide_format(x) +# save("df_element_columns", file="data/df_element_columns.RData") +# rg2 <- importDataframe(df_element_columns) + + +## df_construct_columns ---- + +#' Sample dataframe with grid data (constructs are columns) +#' +#' This dataframe can be converted into a `repgrid` object via [importDataframe()]. The columns names are `elements` +#' followed by the constructs (`left_pole_1:right_pole_1` to `left_pole_3:right_pole_3`). The poles are separated by a +#' colon by default (change via arg `pole_sep`). The rows contain the elements' entries (element name and ratings). The +#' min and max of the rating scale should be passed explicitly via the args `rmin` and `rmax`. See sample data +#' [df_construct_columns]. +#' +#' \tabular{lrrrr}{ +#' `elements` \tab `left_pole_1:right_pole_1` \tab `left_pole_2:right_pole_2` \tab `left_pole_3:right_pole_3` \cr +#' `element_1` \tab `5` \tab `3` \tab `2` \cr +#' `element_2` \tab `3` \tab `3` \tab `4` \cr +#' `element_3` \tab `1` \tab `5` \tab `2` \cr +#' `element_4` \tab `4` \tab `3` \tab `3` \cr +#' } +#' @name df_construct_columns +#' @family grid_dataframe +#' @seealso [importDataframe()] +#' @docType data +#' @keywords data +#' @examples +#' df_construct_columns +#' importDataframe(df_construct_columns, format = "construct_columns", rmin = 1, rmax = 5) +NULL + +# # dataframe with columns as constructs +# file <- system.file("extdata", "grid_01.xlsx", package = "OpenRepGrid") +# x <- importExcel(file) +# x <- x[1:3, 1:4] # smaller version +# df_construct_columns <- grid_to_long_format(x) %>% +# mutate(construct = paste0(left_pole, ":", right_pole)) %>% +# pivot_wider(id_cols = "element", names_from = "construct", values_from = "rating") +# save("df_construct_columns", file="data/df_construct_columns.RData") +# rg2 <- importDataframe(df_construct_columns, format = "c", rmin = 1, rmax = 5) + + +## df_long ---- + +#' Sample dataframe with grid data (long) +#' +#' This dataframe can be converted into a `repgrid` object via [importDataframe()]. +#' The `long` format has this name because it has few columns and many rows. It is a common format +#' in data analytics. Here, each row contains a different element-construct combination and the corresponding rating +#' value. The format looks like this: +#' +#' \tabular{lllrlrr}{ +#' `element` \tab `left_pole` \tab `right_pole` \tab `rating` \tab `preferred_pole` \tab `rmin` \tab `rmax` \cr +#' `element 1` \tab `left pole 1` \tab `right pole 1` \tab `5` \tab `left` \tab `1` \tab `5` \cr +#' `element_2` \tab `left pole 1` \tab `right pole 1` \tab `3` \tab `left` \tab `1` \tab `5` \cr +#' `element_3` \tab `left pole 1` \tab `right pole 1` \tab `1` \tab `left` \tab `1` \tab `5` \cr +#' } +#' +#' The columns `element`, `left_pole`, `right_pole`, and `rating` are mandatory, the columns `preferred_pole`, `rmin`, +#' and `rmax` are optional. `rmin` and `rmax` contain the min and max of the rating scale. Alternatively, you may +#' pass `rmin` and `rmax` as arguments in the function call. +#' +#' @name df_long +#' @family grid_dataframe +#' @seealso [importDataframe()] +#' @docType data +#' @keywords data +#' @examples +#' df_long +#' importDataframe(df_long, format = "long") +NULL + +# # # dataframe with columns as constructs +# file <- system.file("extdata", "grid_01.xlsx", package = "OpenRepGrid") +# x <- importExcel(file) +# x <- x[1:3, 1:4] # smaller version +# df_long <- grid_to_long_format(x) +# save("df_long", file="data/df_long.RData") +# rg2 <- importDataframe(df_long, format = "long") diff --git a/R/dev-functions.r b/R/dev-functions.r index 4fd68889..2a3a0b7e 100644 --- a/R/dev-functions.r +++ b/R/dev-functions.r @@ -22,40 +22,40 @@ #' @param options Use random sentences as constructs and elements (1) or #' not (0). If not, the elements and constructs are given #' default names and are numbered. +#' @param preferred Add preferred pole info? (default `TRUE`) #' @return `repgrid` object. #' #' @export #' @examples \dontrun{ -#' #' x <- randomGrid() #' x -#' x <- randomGrid(10, 25) +#' x <- randomGrid(10, 25, preferred = FALSE) #' x #' x <- randomGrid(10, 25, options = 0) #' x #' } #' -randomGrid <- function(nc = 10, ne = 15, nwc = 8, nwe = 5, range = c(1, 5), prob = NULL, options = 1) { +randomGrid <- function(nc = 10, ne = 15, nwc = 8, nwe = 5, range = c(1, 5), prob = NULL, options = 1, preferred = TRUE) { if (options == 1) { # full constructs and element names elem <- randomSentences(ne, nwe) left <- randomSentences(nc, nwc) right <- randomSentences(nc, nwc) } else { # short element and construct names - elem <- paste("element", seq_len(ne), sep = "") - left <- paste("lconstruct", seq_len(nc), sep = "") - right <- paste("rconstruct", seq_len(nc), sep = "") + elem <- paste("element", seq_len(ne)) + left <- paste("left pole", seq_len(nc)) + right <- paste("right pole", seq_len(nc)) } - scores <- sample(range[1]:range[2], nc * ne, - replace = TRUE, prob = prob - ) + scores <- sample(range[1]:range[2], nc * ne, replace = TRUE, prob = prob) + preferred_pole <- sample(c("left", "right", NA_character_), replace = TRUE, size = nc, prob = c(.7, .2, .1)) args <- list( name = elem, l.name = left, r.name = right, - scores = scores + scores = scores, + preferred_pole = if (preferred) preferred_pole else NULL ) x <- makeRepgrid(args) - setScale(x, min = range[1], max = range[2], step = 1) + setScale(x, min = range[1], max = range[2]) } diff --git a/R/export.r b/R/export.r index ee03828b..1f2956b1 100644 --- a/R/export.r +++ b/R/export.r @@ -171,44 +171,252 @@ saveAsTxt <- function(x, file = NA) { ############################# EXPORT EXCEL #################################### -#' Save grid in a Microsoft Excel file (.xlsx) +#' Save grids as Microsoft Excel file (.xlsx) #' -#' `saveAsExcel` will save the grid as a Microsoft Excel file -#' (`.xlsx`). +#' `saveAsExcel` will save one or more grids in an Excel file (`.xlsx`). #' -#' @param x A `repgrid` object. -#' @param file Filename to save the grid to. The name should have -#' the suffix `.xlsx`. -#' @param sheet Index of the sheet to write to. -#' @return Invisibly returns the name of the file. +#' @param x A `repgrid` object or a list of grids. +#' @param file File path. Suffix must be `.xlsx`. +#' @param format Two output formats are supported: `wide` (default) where each column represents one element, each row +#' represent one constructs (a common grid representation), and `long` where each row contains an element-construct +#' combination and the corresponding rating value. See [importExcel()] for details and examples. +#' @param sheet Vector of sheet names with same length as `x`. If `NULL` (default), `default_sheet` is used. If `x` +#' is a list if grids, a sequential index is appended. For named list entries (if `x` is a list of grids), the name +#' overwrites the default sheet name. +#' @param default_sheet Default sheet name to use if not supplied in `sheet` or via list names of `x`. +#' @return Invisibly returns file path. #' @export -#' @seealso [importExcel()] -#' @examples \dontrun{ +#' @seealso [importExcel()], [saveAsWorksheet()] +#' @example inst/examples/example-save-as-excel.R #' -#' x <- randomGrid(options = 0) -#' saveAsExcel(x, "grid.xlsx") -#' } -#' -saveAsExcel <- function(x, file, sheet = 1) { - # check for correct file extension +saveAsExcel <- function(x, file, format = "wide", sheet = NULL, default_sheet = "grid") { ext <- tools::file_ext(file) if (ext != "xlsx") { - stop("The file extension must be '.xlsx' but you have '.", ext, "'", call. = FALSE) + stop("The file extension must be '.xlsx'. Found '", ext, "' instead.", call. = FALSE) + } + wb <- openxlsx::createWorkbook() + wb <- saveAsWorksheet(x, wb = wb, format = format, sheet = sheet, default_sheet = default_sheet) + openxlsx::saveWorkbook(wb, file, overwrite = TRUE) + invisible(file) +} + + +#' Add grids as sheets to an openxlsx Workbook +#' +#' `saveAsWorksheet` will add one or more grids to an a [openxlsx](https://CRAN.R-project.org/package=openxlsx) +#' `Workbook` object. +#' +#' @param wb A [openxlsx](https://CRAN.R-project.org/package=openxlsx) `Workbook` object. +#' @inheritParams saveAsExcel +#' @return Invisibly returns Workbook object. +#' @export +#' @seealso [saveAsExcel()] +#' @example inst/examples/example-save-as-worksheet.R +#' +saveAsWorksheet <- function(x, wb, format = "wide", sheet = NULL, default_sheet = "grid") { + stop_if_not_inherits(wb, "Workbook") + if (!is_list_of_repgrids(x)) { + sheet <- sheet %||% default_sheet + wb <- add_one_sheet_with_grid(x, wb = wb, format = format, sheet = sheet) + } else { + ii <- seq_along(x) + list_names <- get_names_na(x) + # sheet name precedence: sheet, list, default + if (length(sheet) == length(x)) { + sheets <- sheet + } else { # if (is.null(sheet) + default_names <- paste(default_sheet, ii) + sheets <- ifelse(is.na(list_names), default_names, list_names) + } + for (i in ii) { + wb <- add_one_sheet_with_grid(x[[i]], wb = wb, format = format, sheet = sheets[i]) + } + } + invisible(wb) +} + + + +# saveAsExcelv2 <- function(x, file, format = "wide", sheet = "grid") { +# ext <- tools::file_ext(file) +# if (ext != "xlsx") { +# stop("The file extension must be '.xlsx'. Found '", ext, "' instead.", call. = FALSE) +# } +# if (is.null(wb)) { +# wb <- openxlsx::createWorkbook() +# } +# if (!is_list_of_repgrids(x)) { +# wb <- add_one_sheet_with_grid(x, wb = wb, format = format, sheet = sheet) +# } else { +# ii <- seq_along(x) +# list_names <- get_names_na(x) +# sheets_numbered <- paste(sheet %||% "grid", ii) +# sheets <- ifelse(is.na(list_names), sheets_numbered) +# for (i in ii) { +# wb <- add_one_sheet_with_grid(x[[i]], wb = wb, format = format, sheet = sheets[i]) +# } +# } +# openxlsx::saveWorkbook(wb, file, overwrite = TRUE) +# invisible(file) +# } +# +# saveAsExcel_v1 <- function(x, file, format = "wide", sheet = NULL) { +# if (is_list_of_repgrids(x)) { +# +# } +# +# stop_if_not_is_repgrid(x) +# ext <- tools::file_ext(file) +# if (ext != "xlsx") { +# stop("The file extension must be '.xlsx'. Found '", ext, "' instead.", call. = FALSE) +# } +# format <- match.arg(tolower(format), c("wide", "long")) +# +# if (format == "wide") { +# df <- grid_to_df_wide(x) +# sheet <- sheet %||% "grid (wide format)" +# jj_rows <- seq_len(nrow(df) + 1) +# jj_elements <- seq_len(ncol(x)) + 1 +# j_left_pole <- 1 +# j_right_pole <- ncol(x) + 2 +# j_preferred <- ncol(df) +# +# style_header <- openxlsx::createStyle(textDecoration = "bold", fgFill = "grey90", border = "bottom") +# style_center <- openxlsx::createStyle(halign = "center") +# style_pole_left <- openxlsx::createStyle(textDecoration = "bold", halign = "right", border = "right") +# style_pole_right <- openxlsx::createStyle(textDecoration = "bold", halign = "left", border = "left") +# style_text_grey <- openxlsx::createStyle(fontColour = "grey50") +# +# wb <- openxlsx::createWorkbook() +# +# openxlsx::addWorksheet(wb, sheet) +# openxlsx::writeData(wb, sheet, x = df, headerStyle = style_header, rowNames = FALSE, colNames = TRUE) +# openxlsx::addStyle(wb, sheet, style = style_center, rows = jj_rows, cols = jj_elements, stack = TRUE, gridExpand = TRUE) +# openxlsx::addStyle(wb, sheet, style = style_pole_left, rows = jj_rows, cols = j_left_pole, stack = TRUE, gridExpand = TRUE) +# openxlsx::addStyle(wb, sheet, style = style_pole_right, rows = jj_rows, cols = j_right_pole, stack = TRUE, gridExpand = TRUE) +# openxlsx::addStyle(wb, sheet, style = style_text_grey, rows = jj_rows, cols = j_preferred, stack = TRUE, gridExpand = TRUE) +# openxlsx::setColWidths(wb, sheet, cols = c(j_left_pole, j_right_pole, j_preferred), widths = c(20, 20, 13)) +# openxlsx::saveWorkbook(wb, file, overwrite = TRUE) +# } else { +# df <- grid_to_df_long(x) +# sheet <- sheet %||% "grid (long format)" +# jj_rows <- seq_len(nrow(df) + 1) +# jj_cols <- seq_len(ncol(df)) +# jj_cols_optional <- 5:7 +# j_preferred <- 5 +# ii_end_construct <- rle(df$left_pole)$lengths %>% cumsum() %>% head(-1) + 1 +# +# style_header <- openxlsx::createStyle(textDecoration = "bold", fgFill = "grey90", border = "bottom") +# style_border_left <- openxlsx::createStyle(border = "left") +# style_border_bottom <- openxlsx::createStyle(border = "bottom", borderStyle = "dashed") +# style_text_grey <- openxlsx::createStyle(fontColour = "grey50") +# +# wb <- openxlsx::createWorkbook() +# openxlsx::addWorksheet(wb, sheet) +# openxlsx::writeData(wb, sheet, x = df, headerStyle = style_header, rowNames = FALSE, colNames = TRUE) +# openxlsx::addStyle(wb, sheet, style = style_border_left, rows = jj_rows, cols = j_preferred, stack = TRUE, gridExpand = TRUE) +# openxlsx::addStyle(wb, sheet, style = style_text_grey, rows = jj_rows, cols = jj_cols_optional, stack = TRUE, gridExpand = TRUE) +# openxlsx::addStyle(wb, sheet, style = style_border_bottom, rows = ii_end_construct, cols = jj_cols, stack = TRUE, gridExpand = TRUE) +# openxlsx::setColWidths(wb, sheet, cols = jj_cols, widths = c(20, 20, 20, 10, 13, 10, 10)) +# openxlsx::freezePane(wb, sheet, firstActiveRow = 2) +# openxlsx::saveWorkbook(wb, file, overwrite = TRUE) +# } +# invisible(file) +# } + +add_one_sheet_with_grid <- function(x, wb, format = "wide", sheet = "grid") { + stop_if_not_is_repgrid(x) + stop_if_not_inherits(wb, "Workbook") + + format <- match.arg(tolower(format), c("wide", "long")) + + sheet <- sheet %||% "grid" + if (sheet %in% names(wb)) { + stop("Worksheet ", shQuote(sheet), " already exists", call. = FALSE) } - # build matrix to write to Excel + if (format == "wide") { + df <- grid_to_df_wide(x) + jj_rows <- seq_len(nrow(df) + 1) + jj_elements <- seq_len(ncol(x)) + 1 + j_left_pole <- 1 + j_right_pole <- ncol(x) + 2 + j_preferred <- ncol(df) + + style_header <- openxlsx::createStyle(textDecoration = "bold", fgFill = "grey90", border = "bottom") + style_center <- openxlsx::createStyle(halign = "center") + style_pole_left <- openxlsx::createStyle(textDecoration = "bold", halign = "right", border = "right") + style_pole_right <- openxlsx::createStyle(textDecoration = "bold", halign = "left", border = "left") + style_text_grey <- openxlsx::createStyle(fontColour = "grey50") + + openxlsx::addWorksheet(wb, sheet) + openxlsx::writeData(wb, sheet, x = df, headerStyle = style_header, rowNames = FALSE, colNames = TRUE) + openxlsx::addStyle(wb, sheet, style = style_center, rows = jj_rows, cols = jj_elements, stack = TRUE, gridExpand = TRUE) + openxlsx::addStyle(wb, sheet, style = style_pole_left, rows = jj_rows, cols = j_left_pole, stack = TRUE, gridExpand = TRUE) + openxlsx::addStyle(wb, sheet, style = style_pole_right, rows = jj_rows, cols = j_right_pole, stack = TRUE, gridExpand = TRUE) + openxlsx::addStyle(wb, sheet, style = style_text_grey, rows = jj_rows, cols = j_preferred, stack = TRUE, gridExpand = TRUE) + openxlsx::setColWidths(wb, sheet, cols = c(j_left_pole, j_right_pole, j_preferred), widths = c(20, 20, 13)) + } else { + df <- grid_to_df_long(x) + jj_rows <- seq_len(nrow(df) + 1) + jj_cols <- seq_len(ncol(df)) + jj_cols_optional <- 5:7 + j_preferred <- 5 + ii_end_construct <- rle(df$left_pole)$lengths %>% + cumsum() %>% + head(-1) + 1 + + style_header <- openxlsx::createStyle(textDecoration = "bold", fgFill = "grey90", border = "bottom") + style_border_left <- openxlsx::createStyle(border = "left") + style_border_bottom <- openxlsx::createStyle(border = "bottom", borderStyle = "dashed") + style_text_grey <- openxlsx::createStyle(fontColour = "grey50") + + openxlsx::addWorksheet(wb, sheet) + openxlsx::writeData(wb, sheet, x = df, headerStyle = style_header, rowNames = FALSE, colNames = TRUE) + openxlsx::addStyle(wb, sheet, style = style_border_left, rows = jj_rows, cols = j_preferred, stack = TRUE, gridExpand = TRUE) + openxlsx::addStyle(wb, sheet, style = style_text_grey, rows = jj_rows, cols = jj_cols_optional, stack = TRUE, gridExpand = TRUE) + openxlsx::addStyle(wb, sheet, style = style_border_bottom, rows = ii_end_construct, cols = jj_cols, stack = TRUE, gridExpand = TRUE) + openxlsx::setColWidths(wb, sheet, cols = jj_cols, widths = c(20, 20, 20, 10, 13, 10, 10)) + openxlsx::freezePane(wb, sheet, firstActiveRow = 2) + } + wb +} + + + +#' Export a grid to dataframe with wide format +#' @param x A `repgrid` object. +#' @export +#' @keywords internal +grid_to_df_wide <- function(x) { + stop_if_not_is_repgrid(x) enames <- elements(x) cnames <- constructs(x) - scores <- ratings(x, names = FALSE) - mm <- getScale(x) # min, max + ratings <- ratings(x, names = FALSE) + min_max <- getScale(x) + preferred_pole <- preferredPoles(x) - part1 <- c(mm[1], enames, mm[2]) - part2 <- cbind(cnames$leftpole, scores, cnames$rightpole) - m <- rbind(part1, part2) - m <- unname(m) + df <- cbind(cnames$leftpole, as.data.frame(ratings), cnames$rightpole, preferred_pole) + names(df) <- c(min_max[1], enames, min_max[2], "preferred_pole") + df +} - # write to disk - openxlsx::write.xlsx(m, file, colNames = FALSE, rowNames = FALSE, sheet = sheet) - invisible(file) +#' Export a grid to dataframe with long format +#' @param x A `repgrid` object. +#' @export +#' @keywords internal +grid_to_df_long <- function(x) { + stop_if_not_is_repgrid(x) + element <- left_pole <- right_pole <- preferred_pole <- NULL # register for R CMD CHECK + df <- grid_to_df_wide(x) + names(df)[c(1L, ncol(x) + 2)] <- c("left_pole", "right_pole") + df_long <- df %>% + tidyr::pivot_longer(-c(left_pole, right_pole, preferred_pole), names_to = "element", values_to = "rating") + rmin <- getScale(x)["min"] + rmax <- getScale(x)["max"] + df_long <- df_long %>% + dplyr::select(element, left_pole, right_pole, rating, preferred_pole) %>% + dplyr::mutate(rmin = rmin, rmax = rmax) + df_long } diff --git a/R/gridlist.R b/R/gridlist.R index 3356c199..7b4e8b71 100644 --- a/R/gridlist.R +++ b/R/gridlist.R @@ -104,3 +104,8 @@ rep.repgrid <- function(x, n = 1, ...) { l <- replicate(n, x) as.gridlist(l) } + + +is_list_of_repgrids <- function(x) { + is.list(x) && all(vapply(x, is.repgrid, logical(1))) +} diff --git a/R/import.r b/R/import.r index be66d3f2..66ee6048 100644 --- a/R/import.r +++ b/R/import.r @@ -1,4 +1,6 @@ -################### import repgrid data from other (grid) programs ############ +# _______________---- +# IMPORT GRID DATA ----------- + # # programs currently supported: # @@ -68,7 +70,7 @@ convertImportObjectToRepGridObject <- function(import) { } -############################ GRIDSTAT ######################################### +## GRIDSTAT ---- # gridstat output has the following form. # 1) first line: some description elements. @@ -390,11 +392,8 @@ multigridFileToSinglegridFiles <- function(file) { #' names are assigned to elements and constructs. #' #' @export +#' @family import #' @references Bell, R. C. (1998) GRIDSTAT: A program for analyzing the data of a repertory grid. Melbourne: Author. -#' -#' @seealso [importGridcor()], [importGridstat()], [importScivesco()], [importGridsuite()], [importTxt()], -#' [importExcel()] -#' #' @examples \dontrun{ #' #' # supposing that the data file gridstat.dat is in the current working directory @@ -430,7 +429,7 @@ importGridstat <- function(file, dir = NULL, min = NULL, max = NULL) { -############################# GRIDCOR ######################################### +## GRIDCOR ------------------------------------------------------------------------------------ # gridcor outpout has the following form: # "As you can see in this sample file, the first line contains the number of constructs (10), @@ -609,17 +608,11 @@ importGridcorInternal <- function(file, dir = NULL) { #' #' Also note that both Gridcor and Gridstat data files do have the same suffix `.dat`. Make sure not to mix them up. #' @export +#' @family import #' @references Feixas, G., & Cornejo, J. M. (2002). GRIDCOR: Correspondence Analysis #' for Grid Data (version 4.0). Barcelona: Centro de Terapia Cognitiva. #' Retrieved from . #' -#' @seealso [importGridcor()], -#' [importGridstat()], -#' [importScivesco()], -#' [importGridsuite()], -#' [importTxt()], -#' [importExcel()] -#' #' @examples \dontrun{ #' #' # supposing that the data file gridcor.dat is in the current directory @@ -647,9 +640,7 @@ importGridcor <- function(file, dir = NULL) { } - - -############################# GRIDSUITE ####################################### +## GRIDSUITE ------------------------------------------------------------------------------------ # # On www.gridsuite.de there are example files and XSD schemes available. @@ -780,9 +771,7 @@ importGridsuiteInternal <- function(file, dir = NULL) { #' current mechanism will cause false assignments. #' #' @export -#' @seealso [importGridcor()], [importGridstat()], [importScivesco()], [importGridsuite()], [importTxt()], -#' [importExcel()] -#' +#' @family import #' @examples \dontrun{ #' #' # supposing that the data file gridsuite.xml is in the current directory @@ -810,7 +799,7 @@ importGridsuite <- function(file, dir = NULL) { } -############################# sci:vesco ####################################### +## sci:vesco ------------------------------------------------------------------------------------ # scivesco saves single grids in .scires files which have an XML structure. # Note: not all nodes are imported by importScivesco() @@ -1110,10 +1099,7 @@ convertScivescoImportObjectToRepGridObject <- function(import) { #' @export #' @references Menzel, F., Rosenberger, M., Buve, J. (2007). Emotionale, intuitive und #' rationale Konstrukte verstehen. *Personalfuehrung, 4*(7), 91-99. -#' -#' @seealso [importGridcor()], [importGridstat()], [importScivesco()], [importGridsuite()], [importTxt()], -#' [importExcel()] -#' +#' @family import #' @examples \dontrun{ #' #' # supposing that the data file scivesco.scires is in the current directory @@ -1141,7 +1127,8 @@ importScivesco <- function(file, dir = NULL) { } -############################# IMPORT .TXT ####################################### +## .txt ------------------------------------------------------------------------------------ + #' ImportTxtInternal is the parser for importTxt. #' @@ -1205,8 +1192,7 @@ importScivesco <- function(file, dir = NULL) { #' for maximum rating value in grid. #' @return List of relevant data. #' -#' @export -#' @keywords internal +#' @noRd #' @examples \dontrun{ #' #' # supposing that the data file sample.txt is in the current directory @@ -1397,22 +1383,22 @@ importTxtInternal <- function(file, dir = NULL, min = NULL, max = NULL) { #' thus strongly recommended to set the scale range correctly. #' #' @export -#' @seealso [importGridcor()], [importGridstat()], [importScivesco()], [importGridsuite()], [importTxt()], -#' [importExcel()] +#' @family import #' @examples #' # Import a .txt file delivered along with the package #' file <- system.file("extdata", "grid_01.txt", package = "OpenRepGrid") #' rg <- importTxt(file) #' -#' \dontrun{ #' # To see the structure of the file, try opening it as follows. #' # (may not work on all systems) +#' \dontrun{ #' file.show(file) #' } #' #' # Import more than one .txt file #' files <- system.file("extdata", c("grid_01.txt", "grid_02.txt"), package = "OpenRepGrid") #' rgs <- importTxt(files) +#' importTxt <- function(file, dir = NULL, min = NULL, max = NULL) { imps <- lapply(as.list(file), importTxtInternal, # make import objects for each .txt file dir = dir, min = min, max = max @@ -1426,164 +1412,306 @@ importTxt <- function(file, dir = NULL, min = NULL, max = NULL) { } -############################# IMPORT EXCEL #################################### +## DATAFRAME ------------------------------------------------------------------------------------ -#' workhorse function (parser) for importExcel. -#' -#' @inheritParams importExcel -#' @export -#' @keywords internal -importExcelInternal <- function(file, dir = NULL, sheet = 1, - min = NULL, max = NULL) { - if (!is.null(dir)) { - file <- paste(dir, file, sep = "/", collapse = "") +#' Convert dataframe to repgrid object (internal) +#' @param x A dataframe with predefined format. +#' @param rmin,rmax Min and max of the rating scale. +#' @return A reogrid object +#' @noRd +df_wide_to_grid <- function(x, rmin = NULL, rmax = NULL) { + if (!is.data.frame(x)) { + stop("'x' must be a dataframe. Got '", class(x)[1], "' instead.") } - - # read in Excel file - x <- openxlsx::read.xlsx(file, sheet = sheet, colNames = FALSE) # read .xlxs or .xls file - - # remove NA lines if too many rows in Excel - na.rows <- apply(x, 1, function(x) all(is.na(unlist(x)))) - x <- x[!na.rows, ] - - last_col_value <- str_trim(x[1L, ncol(x)]) - last_col_numeric <- last_col_value %>% - str_trim() %>% - str_detect("^[0-9]+$") - last_col_has_preferred_poles <- tolower(last_col_value) %>% str_detect("^preferred.*") - - nc <- nrow(x) - 1L # number of constructs + nms <- names(x) <- trimws(names(x)) + col_last <- tail(nms, 1) + # last_col_numeric <- grepl("^[0-9]+$", col_last) + last_col_has_preferred_poles <- grepl("^preferred.*", tolower(col_last)) + nc <- nrow(x) # number of constructs ne <- ncol(x) - 2L - last_col_has_preferred_poles # number of elements - elements_col_start <- 2L - elements_col_end <- ncol(x) - 1L - last_col_has_preferred_poles - cols_elements <- elements_col_start:elements_col_end - - rows_ratings <- seq_len(nc) + 1L + col_left_poles <- 1 + col_right_poles <- ne + 2L + cols_elements <- seq_len(ne) + 1L + rows_ratings <- seq_len(nc) - l <- list() - - # read elements - l$elements <- as.list(as.character(unlist(x[1, cols_elements]))) # list of element names - - # read constructs and trim blanks - l$emergentPoles <- as.list(as.character(x[rows_ratings, 1L])) - l$contrastPoles <- as.list(as.character(x[rows_ratings, ne + 2L])) - - if (last_col_has_preferred_poles) { - l$preferredPoles <- as.list(as.character(x[rows_ratings, ncol(x)])) + ratings <- x[rows_ratings, cols_elements] %>% + as.matrix() %>% + as.numeric() + if (any(is.na(ratings))) { + stop("\nNA ratings are not allowed.", call. = FALSE) } - # read ratings and convert to numeric - ratings <- x[rows_ratings, cols_elements] - ratings <- sapply(ratings, function(x) as.numeric(as.character(x))) # convert to numerics - l$ratings <- split(ratings, 1L:nrow(ratings)) # convert df to list row-wise - # read range info if available - rmin <- as.numeric(as.vector(x[1L, 1L])) - rmax <- as.numeric(as.vector(x[1L, ne + 2L])) + # determine rating range + rmin <- rmin %||% suppressWarnings(as.numeric(trimws(nms[col_left_poles]))) # supress NA conversion, NA handled below + rmax <- rmax %||% suppressWarnings(as.numeric(trimws(nms[col_right_poles]))) - # if not availabe infer range data and issue warning - if (identical(rmin, numeric(0)) || identical(rmax, numeric(0))) { - warning("the minimum and/or the maximum value of the rating scale have not been set explicitly.", - "The scale range was thus inferred by scanning the available ratings and may be wrong.", - "See ?importExcel for more information", + # if unknown range, infer from data with warning + if (identical(rmin, numeric(0)) || is.na(rmin) || identical(rmax, numeric(0)) || is.na(rmax)) { + warning("The range of the rating scale was not supplied via args `rmin` and `rmax`.", + "\nI will set the min and max rating as scale range. This may be incorrect!", + "\nSee `?importExcel` for more information", call. = FALSE ) rmin <- min(ratings, na.rm = TRUE) # infer rating range rmax <- max(ratings, na.rm = TRUE) } - # overwrite scale range if given in arguments - if (!is.null(min)) { - rmin <- min + # easier than building from scratch, as makeEmptyRepgrid() appears not suited here + rg <- randomGrid(ne = ne, nc = nc, range = c(rmin, rmax), options = 0) + ratings(rg) <- ratings + elements(rg) <- nms[cols_elements] + leftpoles(rg) <- x[[col_left_poles]] + rightpoles(rg) <- x[[col_right_poles]] + preferredPoles(rg) <- x[["preferred_pole"]] # if not present => NULL => NA + rg +} + + +df_long_to_wide <- function(df, rmin = NULL, rmax = NULL) { + left_pole <- preferred_pole <- right_pole <- NULL # register vars for R CMD CHECK + if (!is.data.frame(df)) { + stop("'df' must be a dataframe. Got '", class(df)[1], "' instead.") } - if (!is.null(max)) { - rmax <- max + cols_required <- c("element", "left_pole", "right_pole", "rating") + cols_optional <- c("preferred_pole", "rmin", "rmax") + nms <- names(df) + cols_missing <- cols_required[!cols_required %in% nms] + if (length(cols_missing) > 0) { + stop("\nMissing columns: ", paste(shQuote(cols_missing), collapse = ", "), + "\nSee `importDataframe()` for long format requirements.", + call. = FALSE + ) } - l$noConstructs <- nc # no of constructs - l$noElements <- ne # no of elements - l$minValue <- rmin # minimum value for Likert scale - l$maxValue <- rmax # maximum value for Likert scale - l + rmin <- df[["rmin"]] %>% unique() + rmax <- df[["rmax"]] %>% unique() + + # convert to wide, simple approach, as we already have an importer for a wide grid + df_wide <- df %>% + tidyr::pivot_wider(id_cols = c("left_pole", "right_pole"), names_from = "element", values_from = "rating") %>% + dplyr::relocate(right_pole, .after = last_col()) + df_pref <- df %>% + dplyr::count(left_pole, preferred_pole) %>% + select(-n) + df_wide <- df_wide %>% left_join(df_pref, by = join_by(left_pole)) + + if (!is.null(rmin) && !is.null(rmax)) { + jj_poles <- c(1L, ncol(df_wide) - 1) + names(df_wide)[jj_poles] <- c(rmin, rmax) + } + df_wide } -#' Import grid data from an Excel file. +#' Transpose grid dataframe +#' Covers the case if elements come in rows instead of columns. +#' @param x A dataframe. Required format: Elements in first column, constructs as columns names. +#' @param pole_sep Seperator for construct poles (default is a colon). +#' @noRd +#' @return A dataframe in standard dataframe format. +#' +df_construct_cols_to_wide <- function(x, pole_sep = ":") { + x_raw <- x + if (!all(grepl("[a-zA-Z]", x_raw[[1]]))) { + warning("The first column must contain the element names") + } + constructs <- names(x_raw)[-1] + x <- as.data.frame(t(x_raw)) + rownames(x) <- NULL + names(x) <- x[1L, ] + x <- x[-1L, ] # elements only + + list_poles <- stringr::str_split(constructs, pole_sep) # split left poles: right pole + list_poles <- lapply(list_poles, stringr::str_trim) + list_poles <- lapply(list_poles, rev) # put right poles first for easier selection + right_poles <- sapply(list_poles, "[", 1L) # by default right pole + left_poles <- sapply(list_poles, "[", 2L) # if exist, else NA + cbind(left = left_poles, x, right = right_poles) +} + + +#' Convert a dataframe into a repgrid object. +#' +#' There are three different dataframe formats from which a `repgrid` object can be created: +#' Columns are a) `element_columns`, b) `construct_columns`, c) `long`. +#' Three corresponding sample dataframes, ([df_element_columns], [df_construct_columns], and [df_long]) are included +#' in the package (see examples). See Detail section below for more info. +#' #' -#' You can define a grid using Microsoft Excel and by saving it as a -#' `.xlsx` file. The `.xlsx` file has to be in a specified fixed -#' format (see section Details). +#' @section Format `element_columns`: #' -#' Excel file structure: The first row contains the minimum of the rating scale, -#' the names of the elements and the maximum of the rating scale. Below every -#' row contains the left construct pole, the ratings and the right construct -#' pole. +#' In this format, each element has a separate column, and each row contains the ratings for one construct. +#' It is a common way to represent grid data and looks like this. #' -#' \tabular{lccccr}{ -#' `1` \tab `E1` \tab `E2` \tab `E3` \tab `E4` \tab `5` \cr -#' `left pole 1` \tab `1` \tab `5` \tab `3` \tab `4` \tab `right pole 1` \cr -#' `left pole 2` \tab `3` \tab `1` \tab `1` \tab `3` \tab `right pole 2` \cr -#' `left pole 3` \tab `4` \tab `2` \tab `5` \tab `1` \tab `right pole 3` \cr +#' \tabular{lccccrr}{ +#' `1` \tab `element_1` \tab `element_2` \tab `element_3` \tab `element_4` \tab `5` \tab `preferred` \cr +#' `left_pole_1` \tab `1` \tab `5` \tab `3` \tab `4` \tab `right_pole_1` \tab `left` \cr +#' `left_pole_2` \tab `3` \tab `1` \tab `1` \tab `3` \tab `right_pole_2` \tab `right` \cr +#' `left_pole_3` \tab `4` \tab `2` \tab `5` \tab `1` \tab `right_pole_3` \tab `NA` \cr #' } #' -#' Note that the maximum and minimum value has to be defined using the -#' `min` and `max` arguments if no values are supplied at the -#' beginning and end of the first row. Otherwise the scaling range is inferred -#' from the available data and a warning is issued as the range may be -#' erroneous. This may effect other functions that depend on knowing the correct -#' range and it is thus strongly recommended to set the scale range correctly. +#' The columns names contains the minimum of the rating scale (`1`), the names of the elements (`element_1` to +#' `element_4`), the maximum of the rating scale (`5`), and optionally the column `preferred`, indicating the preferred +#' pole. Each row contains the constructs entries (left pole, ratings, right pole, preferred pole). The preferred pole +#' must be one of `left`, `right`, `none`, `NA` (see [preferredPoles()]). See sample dataframe [df_element_columns]. #' -#' @param file A vector of filenames including the full path if file is not in current working -#' directory. The file suffix has to be `.xlsx` (used since Excel 2007). -#' @param dir Alternative way to supply the directory where the file is located -#' (default `NULL`). -#' @param sheet Name or index of Excel sheet containing the grid. -#' @param min Optional argument (`numeric`, default `NULL`) -#' for minimum rating value in grid. -#' @param max Optional argument (`numeric`, default `NULL`) -#' for maximum rating value in grid. -#' @return A single `repgrid` object in case one file and -#' a list of `repgrid` objects in case multiple files are imported. +#' +#' @section Format `construct_columns`: +#' +#' In this format, each construct has a separate column, and each row contains represents element. This format often +#' results when summarising data (see examples). It looks like this: +#' +#' The first column is named `elements` followed by the constructs. The construct poles are separated by a colon by +#' default (see arg `pole_sep`). The rows below contain the elements' entries (element name, ratings). The min and max +#' of the rating scale should be passed explicitly via the args `rmin` and `rmax`. See sample dataframe +#' [df_construct_columns]. +#' +#' \tabular{lrrr}{ +#' `elements` \tab `left_pole_1:right_pole_1` \tab `left_pole_2:right_pole_2` \tab `left_pole_3:right_pole_3` \cr +#' `element_1` \tab `1` \tab `5` \tab `3` \cr +#' `element_2` \tab `3` \tab `1` \tab `1` \cr +#' `element_3` \tab `4` \tab `2` \tab `5` \cr +#' } +#' +#' +#' @section Format `long`: +#' +#' The `long` format gets its name from the fact, that it has less columns, but many more rows. It is a common format +#' in data analytics. Here, each row contains a different element-construct combination and the corresponding rating +#' value. The format looks like this: +#' +#' \tabular{lllrlrr}{ +#' `element` \tab `left_pole` \tab `right_pole` \tab `rating` \tab `preferred_pole` \tab `rmin` \tab `rmax` \cr +#' `element 1` \tab `left pole 1` \tab `right pole 1` \tab `1` \tab `left` \tab `1` \tab `5` \cr +#' `element_2` \tab `left pole 1` \tab `right pole 1` \tab `5` \tab `left` \tab `1` \tab `5` \cr +#' `element_3` \tab `left pole 1` \tab `right pole 1` \tab `4` \tab `left` \tab `1` \tab `5` \cr +#' } +#' +#' The columns `element`, `left_pole`, `right_pole`, and `rating` are mandatory, the columns `preferred_pole`, `rmin`, +#' and `rmax` are optional. `rmin` and `rmax` contain the min and max of the rating scale. Alternatively, you may +#' pass `rmin` and `rmax` as arguments in the function call. See sample dataframe [df_long]. +#' +#' +#' @param x A dataframe. See Detail section and examples for required format. +#' @param format One of `element_columns` (default), `construct_columns`, or `long`. See corresponding sections below. +#' @param rmin,rmax Min and max of rating scale. +#' @param pole_sep Character(s) to seperate the constructs poles (defaults to a colon) for format `construct_columns`. +#' Without a separator, constructs are used as right poles, all left poles will be `NA`. +#' @return A `repgrid`` object. +#' @family import #' @export -#' @seealso [importGridcor()], -#' [importGridstat()], -#' [importScivesco()], -#' [importGridsuite()], -#' [importTxt()] +#' @examples +#' # dataframe with elements as columns (preferred way) +#' importDataframe(df_element_columns) #' -#' @examples \dontrun{ +#' # dataframe with constructs as columns +#' importDataframe(df_construct_columns, format = "construct_columns", rmin = 1, rmax = 5) +#' +#' # dataframe with long format +#' importDataframe(df_long, format = "long", rmin = 1, rmax = 5) +importDataframe <- function(x, format = "element_columns", rmin = NULL, rmax = NULL, pole_sep = ":") { + if (!is.data.frame(x)) { + stop("'x' must be a dataframe. Got <", class(x)[1], "> instead.") + } + format <- match.arg(tolower(format), choices = c("element_columns", "construct_columns", "long")) + if (format == "construct_columns") { + x <- df_construct_cols_to_wide(x, pole_sep = pole_sep) + } else if (format == "long") { + x <- df_long_to_wide(x, rmin = rmin, rmax = rmax) + } + df_wide_to_grid(x, rmin = rmin, rmax = rmax) +} + + +## EXCEL ------------------------------------------------------------------------------------ + +#' Import grid data from an Excel file. +#' +#' You can define a grid in a Microsoft Excel file (suffix `.xlsx`). The file must have one of +#' two formats (`wide` or `long`, see format sections below). +#' +#' @section Format `wide`: +#' +#' In the `wide` format, each element has a separate column, and each row contains the ratzings for one construct. +#' It is a common way to represent grid data and looks like this: +#' +#' \tabular{lccccrr}{ +#' `1` \tab `element_1` \tab `element_2` \tab `element_3` \tab `element_4` \tab `5` \tab `preferred` \cr +#' `left_pole_1` \tab `1` \tab `5` \tab `3` \tab `4` \tab `right_pole_1` \tab `left` \cr +#' `left_pole_2` \tab `3` \tab `1` \tab `1` \tab `3` \tab `right_pole_2` \tab `right` \cr +#' `left_pole_3` \tab `4` \tab `2` \tab `5` \tab `1` \tab `right_pole_3` \tab `NA` \cr +#' } #' -#' # Open Excel file delivered along with the package -#' file <- system.file("extdata", "grid_01.xlsx", package = "OpenRepGrid") -#' rg <- importExcel(file) +#' The header row contains the minimum of the rating scale (`1`), the names of the elements (`element_1` to `element_4`), +#' the maximum of the rating scale (`5`), and optionally the column `preferred`, indicating the preferred pole. +#' Each row contains the constructs entries (left pole, ratings, right pole, preferred pole). The preferred pole +#' must be one of `left`, `right`, `none`, `NA` (see [preferredPoles()]). #' -#' # To see the structure of the Excel file try to open it as follows. -#' # Requires Excel to be installed. -#' system2("open", file) #' -#' # Import more than one Excel file -#' files <- system.file("extdata", c("grid_01.xlsx", "grid_02.xlsx"), package = "OpenRepGrid") -#' rg <- importExcel(files) +#' @section Format `long`: +#' +#' The `long` format has this name because it has few columns and many rows. It is a common format +#' in data analytics. Here, each row contains a different element-construct combination and the corresponding rating +#' value. The format looks like this: +#' +#' \tabular{lllrlrr}{ +#' `element` \tab `left_pole` \tab `right_pole` \tab `rating` \tab `preferred_pole` \tab `rmin` \tab `rmax` \cr +#' `element 1` \tab `left pole 1` \tab `right pole 1` \tab `1` \tab `left` \tab `1` \tab `5` \cr +#' `element_2` \tab `left pole 1` \tab `right pole 1` \tab `5` \tab `left` \tab `1` \tab `5` \cr +#' `element_3` \tab `left pole 1` \tab `right pole 1` \tab `4` \tab `left` \tab `1` \tab `5` \cr #' } #' -importExcel <- function(file, dir = NULL, sheet = 1, min = NULL, max = NULL) { - imps <- lapply(as.list(file), importExcelInternal, # make import objects for each .txt file - dir = dir, sheet = sheet, - min = min, max = max +#' The columns `element`, `left_pole`, `right_pole`, and `rating` are mandatory, the columns `preferred_pole`, `rmin`, +#' and `rmax` are optional. `rmin` and `rmax` contain the min and max of the rating scale. Alternatively, you may +#' pass `rmin` and `rmax` as arguments in the function call. +#' +#' @param file Path(s) to Excel file(s) (suffix `.xlsx`). +#' @param sheet Names or indexes of sheet with grid data to import. +#' @param format Two formats are supported. `wide` (default): each column represents one element, each row represent +#' one constructs. `long`: each row contains one rating value for a element-construct combination. See +#' sections below and examples. +#' @param rmin,rmax Min and max of the rating scale (`numeric`, default `NULL`). +#' @return A `repgrid` object (one input file) or a named list with `repgrid` objects (several input files). List names are +#' filename + sheet. +#' @export +#' @family import +#' @example inst/examples/example-importExcel.R +#' +importExcel <- function(file, sheet = 1, format = "wide", rmin = NULL, rmax = NULL) { + format <- match.arg(tolower(format), c("wide", "long")) + import_fun <- ifelse(format == "wide", import_excel_wide, import_excel_long) + df_import <- expand.grid(file = file, sheet = sheet, stringsAsFactors = FALSE) # read all file-sheet combinations + rgs <- mapply(import_fun, + file = df_import$file, sheet = df_import$sheet, + MoreArgs = list(rmin = rmin, rmax = rmax) ) - rgs <- lapply(imps, convertImportObjectToRepGridObject) # make repgrid object from import object - if (length(file) == 1) { - return(rgs[[1]]) # return a single repgrid opbject if a single file is prompted + filenames <- file_path_sans_ext(basename(df_import$file)) + names(rgs) <- paste0(filenames, "-", df_import$sheet) + if (length(rgs) == 1) { + return(rgs[[1]]) # no list, just single repgrid object } else { - return(rgs) # return a list of repgrid objects + return(rgs) # list of repgrid objects } } +import_excel_wide <- function(file, sheet = 1, rmin = NULL, rmax = NULL) { + x <- openxlsx::read.xlsx(file, sheet = sheet, colNames = FALSE) # colNames = FALSE as spaces are treated incorrectly + names(x) <- x[1L, ] + x <- x[-1L, ] + importDataframe(x, format = "element_columns", rmin = rmin, rmax = rmax) +} + + +import_excel_long <- function(file, sheet = 1, rmin = NULL, rmax = NULL) { + x <- openxlsx::read.xlsx(file, sheet = sheet, colNames = TRUE) + importDataframe(x, format = "long", rmin = rmin, rmax = rmax) +} + -############################# IMPORTING ################################### +# HELPERS -------------------------------------------------------------------------------- guessDataSource <- function(file) { diff --git a/R/measures.r b/R/measures.r index 84f11a6d..d88061b7 100644 --- a/R/measures.r +++ b/R/measures.r @@ -397,7 +397,6 @@ indexPvaff <- function(x, method = 1) { #' @example inst/examples/example-indexBieri.R #' @export #' -#' indexBieri <- function(x, deviation = 0) { stop_if_not_is_repgrid(x) diff --git a/R/openrepgrid.r b/R/openrepgrid.r index e07d5ea4..5d08d785 100644 --- a/R/openrepgrid.r +++ b/R/openrepgrid.r @@ -248,12 +248,6 @@ #' [doubleEntry()] \tab Join the constructs of a grid with the same reversed constructs. \cr #' } #' -#' **Other internal functions** \cr -#' -#' \tabular{ll}{ -#' [importTxtInternal()] \tab \cr -#' } -#' #' @author Current members of the \pkg{OpenRepGrid} development team: Mark Heckmann. #' Everyone who is interested in developing the package is invited to join. #' diff --git a/R/preferred_poles.R b/R/preferred_poles.R index 01ac437a..9370d00c 100644 --- a/R/preferred_poles.R +++ b/R/preferred_poles.R @@ -28,6 +28,7 @@ preferredPoles <- function(x) { `preferredPoles<-` <- function(x, value) { stop_if_not_is_repgrid(x) nc <- nrow(x) + value <- value %||% NA # replace NULL with NA value <- rep_len(value, length.out = nc) value <- as.character(value) # all NA case value <- match.arg2(value, c("left", "right", "none", "both", NA_character_), several.ok = TRUE) diff --git a/R/repgrid-basicops.r b/R/repgrid-basicops.r index a7a42622..653a36c7 100644 --- a/R/repgrid-basicops.r +++ b/R/repgrid-basicops.r @@ -96,6 +96,13 @@ stop_if_not_integerish <- function(x, arg = NULL) { } +stop_if_not_inherits <- function(x, what, argname = "x") { + if (!inherits(x, what)) { + stop("`", argname, "` must have class <", what, "> not <", class(x)[1], ">", call. = FALSE) + } +} + + ############################# EXTRACT AND SET ################################# ## S4 methods @@ -510,9 +517,9 @@ setScale <- function(x, min, max, step, ...) { # ... needes for makeRepgrid call } x@scale$max <- max } - if (!missing(step)) { - x@scale$step <- step - } + # if (!missing(step)) { + # x@scale$step <- step + # } x } # setScale(x, min=1, max=5, step=1) @@ -1451,6 +1458,7 @@ makeRepgrid <- function(args) { x <- do.call(rg.setCoupled, l) # if no coupled argument then coupled=TRUE l <- c(list(x = x), args) # make a new repgrid object x <- do.call(setScale, l) # set scale if min and max arg is provided + preferredPoles(x) <- l$preferred_pole x } # args <- list( name=c("element_1", "element_2", "element_3", "element_4"), diff --git a/R/repgrid-plots.r b/R/repgrid-plots.r index 2dd45d02..84e517ca 100644 --- a/R/repgrid-plots.r +++ b/R/repgrid-plots.r @@ -1486,9 +1486,9 @@ addVarianceExplainedToBiplot2d <- function(x, dim = c(1, 2, 3), var.cex = .7, #' - Interactive 3D biplots: [biplot3d()], [biplotEsa3d()], [biplotSlater3d()]; #' - Function to set view in 3D: [home()] #' -#' @examples \dontrun{ -#' +#' @examples #' biplot2d(boeker) # biplot of boeker data +#' \dontrun{ #' biplot2d(boeker, c.lines = T) # add construct lines #' biplot2d(boeker, center = 2) # with column centering #' biplot2d(boeker, center = 4) # midpoint centering diff --git a/R/settings.r b/R/settings.r index 55a9865b..bba39011 100644 --- a/R/settings.r +++ b/R/settings.r @@ -5,7 +5,7 @@ generateDefaultSettings <- function() { # print grid to console l$show.trim <- 30 type$show.trim <- "numeric" - l$show.cut <- 20 + l$show.cut <- 25 type$show.cut <- "numeric" l$show.scale <- TRUE type$show.scale <- "logical" diff --git a/R/utils.r b/R/utils.r index 1851bfd4..5317e1f4 100644 --- a/R/utils.r +++ b/R/utils.r @@ -1021,3 +1021,32 @@ list_to_dataframe <- function(l) { # plyr:::list_to_dataframe(l) do.call(rbind.data.frame, l) } + + +`%||%` <- function(a, b) { + if (!is.null(a)) { + a + } else { + b + } +} + + +# Get list names +# returns vector with same length as list. NA if list entry has no name. +get_names_na <- function(x) { + nm <- names(x) + if (is.null(nm)) { + rep(NA_character_, length(x)) + } else { + ifelse(nzchar(nm), nm, NA_character_) + } +} + +# from tools::file_path_sans_ext +file_path_sans_ext <- function(x, compression = FALSE) { + if (compression) { + x <- sub("[.](gz|bz2|xz)$", "", x) + } + sub("([^.]+)\\.[[:alnum:]]+$", "\\1", x) +} diff --git a/README.Rmd b/README.Rmd index b9a2b9e2..8ed477c5 100644 --- a/README.Rmd +++ b/README.Rmd @@ -49,10 +49,10 @@ Install the latest release version from [CRAN](https://cran.r-project.org/web/pa install.packages("OpenRepGrid", dep = TRUE) -Install a development version from github by referencing a the dev branch (e.g., `0.1.18`): +Install a development version from github by referencing a the dev branch (e.g., `0.1.19`): library(devtools) - install_github("markheckmann/OpenRepGrid@01.1.18") + install_github("markheckmann/OpenRepGrid@01.1.19") To load the OpenRepGrid package after installation type diff --git a/README.md b/README.md index 5fb8feef..1f0f54a4 100644 --- a/README.md +++ b/README.md @@ -59,10 +59,10 @@ Install the latest release version from install.packages("OpenRepGrid", dep = TRUE) Install a development version from github by referencing a the dev -branch (e.g., `0.1.18`): +branch (e.g., `0.1.19`): library(devtools) - install_github("markheckmann/OpenRepGrid@01.1.18") + install_github("markheckmann/OpenRepGrid@01.1.19") To load the OpenRepGrid package after installation type diff --git a/_pkgdown.yml b/_pkgdown.yml index d9394c5c..29eb6a65 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -67,6 +67,7 @@ reference: - constructRmsCor - constructs - preferredPoles + - preferredPolesByIdeal - alignByIdeal - alignByLoadings - alignByPreferredPole @@ -111,6 +112,9 @@ reference: - data-raeithel - data-slater1977a - data-slater1977b + - df_element_columns + - df_construct_columns + - df_long - title: Settings contents: @@ -122,11 +126,13 @@ reference: contents: - importExcel - importTxt + - importDataframe - importGridcor - importGridstat - importGridsuite - importScivesco - saveAsExcel + - saveAsWorksheet - saveAsTxt - title: Plots @@ -172,4 +178,3 @@ reference: - "[,repgrid-method" - "[<-,repgrid-method" - cbind.repgrid - diff --git a/cran-comments.md b/cran-comments.md index 8550a501..cd608ad5 100644 --- a/cran-comments.md +++ b/cran-comments.md @@ -1,8 +1,8 @@ ## Test environments -* MacOS 14.7.2, R 4.4.3 -* Microsoft Windows Server 2022, R 4.4.3 -* Ubuntu 22.04.2 LTS, R 4.4.3 +* MacOS 14.7.6, R 4.5.1 +* Microsoft Windows Server 2022, R 4.5.1 +* Ubuntu 24.04.2 LTS, R 4.5.1 ## R CMD check results diff --git a/data/df_construct_columns.RData b/data/df_construct_columns.RData new file mode 100644 index 00000000..e0dedbe0 Binary files /dev/null and b/data/df_construct_columns.RData differ diff --git a/data/df_element_columns.RData b/data/df_element_columns.RData new file mode 100644 index 00000000..b10e7864 Binary files /dev/null and b/data/df_element_columns.RData differ diff --git a/data/df_long.RData b/data/df_long.RData new file mode 100644 index 00000000..af591c10 Binary files /dev/null and b/data/df_long.RData differ diff --git a/inst/examples/example-importExcel.R b/inst/examples/example-importExcel.R new file mode 100644 index 00000000..5993f1d3 --- /dev/null +++ b/inst/examples/example-importExcel.R @@ -0,0 +1,16 @@ +file <- system.file("extdata", "grid_01.xlsx", package = "OpenRepGrid") +rg_1 <- importExcel(file, sheet = "wide") +rg_2 <- importExcel(file, sheet = "long", format = "long") + +# Open sample file to inspect it (requires Excel to be installed). +\dontrun{ +browseURL(file) # may not work on all systems } + +# Import more than one Excel file +files <- system.file("extdata", c("grid_01.xlsx", "grid_02.xlsx"), package = "OpenRepGrid") +rgs <- importExcel(files) # returns a list of grids + +# Impoort from several sheets at once (all must have same format) +file <- system.file("extdata", "grid_03.xlsx", package = "OpenRepGrid") +rgs <- importExcel(file, sheet = 1:3) # by index +rgs <- importExcel(file, sheet = c("grid 1", "grid 2", "grid 3")) # or by name diff --git a/inst/examples/example-save-as-excel.R b/inst/examples/example-save-as-excel.R new file mode 100644 index 00000000..c2b31b2e --- /dev/null +++ b/inst/examples/example-save-as-excel.R @@ -0,0 +1,29 @@ +# save one grid in wide format (default) +file <- tempfile(fileext = ".xlsx") +saveAsExcel(boeker, file) +\dontrun{ +browseURL(file) # open file, requires Excel, may not work on all system +} + +# save one grid in log format +file <- tempfile(fileext = ".xlsx") +saveAsExcel(boeker, file, format = "long") +\dontrun{ +browseURL(file) +} + +# save a list of grids +file <- tempfile(fileext = ".xlsx") +l <- list(boeker, feixas2004, bell2010) +saveAsExcel(l, file) +\dontrun{ + browseURL(file) +} + +# pass some sheet names (2nd with named sheet) +file <- tempfile(fileext = ".xlsx") +l <- list(boeker, "feixas' grid" = feixas2004) +saveAsExcel(l, file) +\dontrun{ + browseURL(file) +} diff --git a/inst/examples/example-save-as-worksheet.R b/inst/examples/example-save-as-worksheet.R new file mode 100644 index 00000000..a5b3d009 --- /dev/null +++ b/inst/examples/example-save-as-worksheet.R @@ -0,0 +1,22 @@ +library(openxlsx) + +wb <- createWorkbook() + +# add grid to worksheet +saveAsWorksheet(boeker, wb, sheet = "boeker") + +# add several grids with explicit sheet names +l <- list(bell2010, feixas2004) +saveAsWorksheet(l, wb, sheet = c("Bell 2010", "Feixas 2004")) + +# list names are used as sheet names. Without name, the default applies. +l <- list(boeker, "Fransella et al. 2003" = fbb2003) +saveAsWorksheet(l, wb) + + +# save as Excel file +file <- tempfile(fileext = ".xlsx") +saveWorkbook(wb, file) +\dontrun{ + browseURL(file) # may not work on all systems +} diff --git a/inst/extdata/grid_01.xlsx b/inst/extdata/grid_01.xlsx index 5e1f4ab9..7d0b6899 100644 Binary files a/inst/extdata/grid_01.xlsx and b/inst/extdata/grid_01.xlsx differ diff --git a/inst/extdata/grid_02.xlsx b/inst/extdata/grid_02.xlsx index 9be749eb..5229bae6 100644 Binary files a/inst/extdata/grid_02.xlsx and b/inst/extdata/grid_02.xlsx differ diff --git a/inst/extdata/grid_03.xlsx b/inst/extdata/grid_03.xlsx new file mode 100644 index 00000000..ccca704a Binary files /dev/null and b/inst/extdata/grid_03.xlsx differ diff --git a/man/OpenRepGrid-overview.Rd b/man/OpenRepGrid-overview.Rd index af0375a0..4acff509 100644 --- a/man/OpenRepGrid-overview.Rd +++ b/man/OpenRepGrid-overview.Rd @@ -212,12 +212,6 @@ functions for these purposes. \code{\link[=bindConstructs]{bindConstructs()}} \tab Concatenate the constructs of two grids. \cr \code{\link[=doubleEntry]{doubleEntry()}} \tab Join the constructs of a grid with the same reversed constructs. \cr } - -\strong{Other internal functions} \cr - -\tabular{ll}{ -\code{\link[=importTxtInternal]{importTxtInternal()}} \tab \cr -} } \seealso{ diff --git a/man/biplot2d.Rd b/man/biplot2d.Rd index 09c3b853..c3f610c5 100644 --- a/man/biplot2d.Rd +++ b/man/biplot2d.Rd @@ -282,9 +282,8 @@ Note that the grid matrix values are only recovered and the projection property is only given if \eqn{g + h = 1}{g + h = 1} } \examples{ -\dontrun{ - biplot2d(boeker) # biplot of boeker data +\dontrun{ biplot2d(boeker, c.lines = T) # add construct lines biplot2d(boeker, center = 2) # with column centering biplot2d(boeker, center = 4) # midpoint centering diff --git a/man/df_construct_columns.Rd b/man/df_construct_columns.Rd new file mode 100644 index 00000000..9bc8101c --- /dev/null +++ b/man/df_construct_columns.Rd @@ -0,0 +1,35 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/data-openrepgrid.r +\docType{data} +\name{df_construct_columns} +\alias{df_construct_columns} +\title{Sample dataframe with grid data (constructs are columns)} +\description{ +This dataframe can be converted into a \code{repgrid} object via \code{\link[=importDataframe]{importDataframe()}}. The columns names are \code{elements} +followed by the constructs (\code{left_pole_1:right_pole_1} to \code{left_pole_3:right_pole_3}). The poles are separated by a +colon by default (change via arg \code{pole_sep}). The rows contain the elements' entries (element name and ratings). The +min and max of the rating scale should be passed explicitly via the args \code{rmin} and \code{rmax}. See sample data +\link{df_construct_columns}. +} +\details{ +\tabular{lrrrr}{ +\code{elements} \tab \code{left_pole_1:right_pole_1} \tab \code{left_pole_2:right_pole_2} \tab \code{left_pole_3:right_pole_3} \cr +\code{element_1} \tab \code{5} \tab \code{3} \tab \code{2} \cr +\code{element_2} \tab \code{3} \tab \code{3} \tab \code{4} \cr +\code{element_3} \tab \code{1} \tab \code{5} \tab \code{2} \cr +\code{element_4} \tab \code{4} \tab \code{3} \tab \code{3} \cr +} +} +\examples{ +df_construct_columns +importDataframe(df_construct_columns, format = "construct_columns", rmin = 1, rmax = 5) +} +\seealso{ +\code{\link[=importDataframe]{importDataframe()}} + +Other grid dataframes: +\code{\link{df_element_columns}}, +\code{\link{df_long}} +} +\concept{grid_dataframe} +\keyword{data} diff --git a/man/df_element_columns.Rd b/man/df_element_columns.Rd new file mode 100644 index 00000000..9ffb8272 --- /dev/null +++ b/man/df_element_columns.Rd @@ -0,0 +1,34 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/data-openrepgrid.r +\docType{data} +\name{df_element_columns} +\alias{df_element_columns} +\title{Sample dataframe with grid data (elements are columns)} +\description{ +This dataframe can be converted into a \code{repgrid} object via \code{\link[=importDataframe]{importDataframe()}}. The dataframe column names are the +minimum of the rating scale (\code{1}), the element names (\code{element_1} to \code{element_4}), the maximum of the rating scale +(\code{5}), and optionally a column indicating the \code{preferred} pole. Each row contains the constructs' entries (left +pole, ratings, right pole, preferred pole). The preferred pole must be one of \code{left}, \code{right}, \code{none}, \code{NA} (see +\code{\link[=preferredPoles]{preferredPoles()}}). See sample data \link{df_element_columns}. +} +\details{ +\tabular{lccccrr}{ +\code{1} \tab \code{element_1} \tab \code{element_2} \tab \code{element_3} \tab \code{element_4} \tab \code{5} \tab \code{preferred} \cr +\code{left_pole_1} \tab \code{1} \tab \code{5} \tab \code{3} \tab \code{4} \tab \code{right_pole_1} \tab \code{left} \cr +\code{left_pole_2} \tab \code{3} \tab \code{1} \tab \code{1} \tab \code{3} \tab \code{right_pole_2} \tab \code{right} \cr +\code{left_pole_3} \tab \code{4} \tab \code{2} \tab \code{5} \tab \code{1} \tab \code{right_pole_3} \tab \code{none} \cr +} +} +\examples{ +df_element_columns +importDataframe(df_element_columns) +} +\seealso{ +\code{\link[=importDataframe]{importDataframe()}} + +Other grid dataframes: +\code{\link{df_construct_columns}}, +\code{\link{df_long}} +} +\concept{grid_dataframe} +\keyword{data} diff --git a/man/df_long.Rd b/man/df_long.Rd new file mode 100644 index 00000000..12bfcd34 --- /dev/null +++ b/man/df_long.Rd @@ -0,0 +1,37 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/data-openrepgrid.r +\docType{data} +\name{df_long} +\alias{df_long} +\title{Sample dataframe with grid data (long)} +\description{ +This dataframe can be converted into a \code{repgrid} object via \code{\link[=importDataframe]{importDataframe()}}. +The \code{long} format has this name because it has few columns and many rows. It is a common format +in data analytics. Here, each row contains a different element-construct combination and the corresponding rating +value. The format looks like this: +} +\details{ +\tabular{lllrlrr}{ +\code{element} \tab \code{left_pole} \tab \code{right_pole} \tab \code{rating} \tab \code{preferred_pole} \tab \code{rmin} \tab \code{rmax} \cr +\verb{element 1} \tab \verb{left pole 1} \tab \verb{right pole 1} \tab \code{5} \tab \code{left} \tab \code{1} \tab \code{5} \cr +\code{element_2} \tab \verb{left pole 1} \tab \verb{right pole 1} \tab \code{3} \tab \code{left} \tab \code{1} \tab \code{5} \cr +\code{element_3} \tab \verb{left pole 1} \tab \verb{right pole 1} \tab \code{1} \tab \code{left} \tab \code{1} \tab \code{5} \cr +} + +The columns \code{element}, \code{left_pole}, \code{right_pole}, and \code{rating} are mandatory, the columns \code{preferred_pole}, \code{rmin}, +and \code{rmax} are optional. \code{rmin} and \code{rmax} contain the min and max of the rating scale. Alternatively, you may +pass \code{rmin} and \code{rmax} as arguments in the function call. +} +\examples{ +df_long +importDataframe(df_long, format = "long") +} +\seealso{ +\code{\link[=importDataframe]{importDataframe()}} + +Other grid dataframes: +\code{\link{df_construct_columns}}, +\code{\link{df_element_columns}} +} +\concept{grid_dataframe} +\keyword{data} diff --git a/man/grid_to_df_long.Rd b/man/grid_to_df_long.Rd new file mode 100644 index 00000000..884d5e3a --- /dev/null +++ b/man/grid_to_df_long.Rd @@ -0,0 +1,15 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/export.r +\name{grid_to_df_long} +\alias{grid_to_df_long} +\title{Export a grid to dataframe with long format} +\usage{ +grid_to_df_long(x) +} +\arguments{ +\item{x}{A \code{repgrid} object.} +} +\description{ +Export a grid to dataframe with long format +} +\keyword{internal} diff --git a/man/grid_to_df_wide.Rd b/man/grid_to_df_wide.Rd new file mode 100644 index 00000000..94aa4af8 --- /dev/null +++ b/man/grid_to_df_wide.Rd @@ -0,0 +1,15 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/export.r +\name{grid_to_df_wide} +\alias{grid_to_df_wide} +\title{Export a grid to dataframe with wide format} +\usage{ +grid_to_df_wide(x) +} +\arguments{ +\item{x}{A \code{repgrid} object.} +} +\description{ +Export a grid to dataframe with wide format +} +\keyword{internal} diff --git a/man/importDataframe.Rd b/man/importDataframe.Rd new file mode 100644 index 00000000..9705e468 --- /dev/null +++ b/man/importDataframe.Rd @@ -0,0 +1,110 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/import.r +\name{importDataframe} +\alias{importDataframe} +\title{Convert a dataframe into a repgrid object.} +\usage{ +importDataframe( + x, + format = "element_columns", + rmin = NULL, + rmax = NULL, + pole_sep = ":" +) +} +\arguments{ +\item{x}{A dataframe. See Detail section and examples for required format.} + +\item{format}{One of \code{element_columns} (default), \code{construct_columns}, or \code{long}. See corresponding sections below.} + +\item{rmin, rmax}{Min and max of rating scale.} + +\item{pole_sep}{Character(s) to seperate the constructs poles (defaults to a colon) for format \code{construct_columns}. +Without a separator, constructs are used as right poles, all left poles will be \code{NA}.} +} +\value{ +A `repgrid`` object. +} +\description{ +There are three different dataframe formats from which a \code{repgrid} object can be created: +Columns are a) \code{element_columns}, b) \code{construct_columns}, c) \code{long}. +Three corresponding sample dataframes, (\link{df_element_columns}, \link{df_construct_columns}, and \link{df_long}) are included +in the package (see examples). See Detail section below for more info. +} +\section{Format \code{element_columns}}{ + + +In this format, each element has a separate column, and each row contains the ratings for one construct. +It is a common way to represent grid data and looks like this. + +\tabular{lccccrr}{ +\code{1} \tab \code{element_1} \tab \code{element_2} \tab \code{element_3} \tab \code{element_4} \tab \code{5} \tab \code{preferred} \cr +\code{left_pole_1} \tab \code{1} \tab \code{5} \tab \code{3} \tab \code{4} \tab \code{right_pole_1} \tab \code{left} \cr +\code{left_pole_2} \tab \code{3} \tab \code{1} \tab \code{1} \tab \code{3} \tab \code{right_pole_2} \tab \code{right} \cr +\code{left_pole_3} \tab \code{4} \tab \code{2} \tab \code{5} \tab \code{1} \tab \code{right_pole_3} \tab \code{NA} \cr +} + +The columns names contains the minimum of the rating scale (\code{1}), the names of the elements (\code{element_1} to +\code{element_4}), the maximum of the rating scale (\code{5}), and optionally the column \code{preferred}, indicating the preferred +pole. Each row contains the constructs entries (left pole, ratings, right pole, preferred pole). The preferred pole +must be one of \code{left}, \code{right}, \code{none}, \code{NA} (see \code{\link[=preferredPoles]{preferredPoles()}}). See sample dataframe \link{df_element_columns}. +} + +\section{Format \code{construct_columns}}{ + + +In this format, each construct has a separate column, and each row contains represents element. This format often +results when summarising data (see examples). It looks like this: + +The first column is named \code{elements} followed by the constructs. The construct poles are separated by a colon by +default (see arg \code{pole_sep}). The rows below contain the elements' entries (element name, ratings). The min and max +of the rating scale should be passed explicitly via the args \code{rmin} and \code{rmax}. See sample dataframe +\link{df_construct_columns}. + +\tabular{lrrr}{ +\code{elements} \tab \code{left_pole_1:right_pole_1} \tab \code{left_pole_2:right_pole_2} \tab \code{left_pole_3:right_pole_3} \cr +\code{element_1} \tab \code{1} \tab \code{5} \tab \code{3} \cr +\code{element_2} \tab \code{3} \tab \code{1} \tab \code{1} \cr +\code{element_3} \tab \code{4} \tab \code{2} \tab \code{5} \cr +} +} + +\section{Format \code{long}}{ + + +The \code{long} format gets its name from the fact, that it has less columns, but many more rows. It is a common format +in data analytics. Here, each row contains a different element-construct combination and the corresponding rating +value. The format looks like this: + +\tabular{lllrlrr}{ +\code{element} \tab \code{left_pole} \tab \code{right_pole} \tab \code{rating} \tab \code{preferred_pole} \tab \code{rmin} \tab \code{rmax} \cr +\verb{element 1} \tab \verb{left pole 1} \tab \verb{right pole 1} \tab \code{1} \tab \code{left} \tab \code{1} \tab \code{5} \cr +\code{element_2} \tab \verb{left pole 1} \tab \verb{right pole 1} \tab \code{5} \tab \code{left} \tab \code{1} \tab \code{5} \cr +\code{element_3} \tab \verb{left pole 1} \tab \verb{right pole 1} \tab \code{4} \tab \code{left} \tab \code{1} \tab \code{5} \cr +} + +The columns \code{element}, \code{left_pole}, \code{right_pole}, and \code{rating} are mandatory, the columns \code{preferred_pole}, \code{rmin}, +and \code{rmax} are optional. \code{rmin} and \code{rmax} contain the min and max of the rating scale. Alternatively, you may +pass \code{rmin} and \code{rmax} as arguments in the function call. See sample dataframe \link{df_long}. +} + +\examples{ +# dataframe with elements as columns (preferred way) +importDataframe(df_element_columns) + +# dataframe with constructs as columns +importDataframe(df_construct_columns, format = "construct_columns", rmin = 1, rmax = 5) + +# dataframe with long format +importDataframe(df_long, format = "long", rmin = 1, rmax = 5) +} +\seealso{ +Import data +\code{\link{importExcel}()}, +\code{\link{importGridcor}()}, +\code{\link{importGridstat}()}, +\code{\link{importGridsuite}()}, +\code{\link{importScivesco}()}, +\code{\link{importTxt}()} +} +\concept{import} diff --git a/man/importExcel.Rd b/man/importExcel.Rd index 8f1a5525..8ef15ee7 100644 --- a/man/importExcel.Rd +++ b/man/importExcel.Rd @@ -4,73 +4,90 @@ \alias{importExcel} \title{Import grid data from an Excel file.} \usage{ -importExcel(file, dir = NULL, sheet = 1, min = NULL, max = NULL) +importExcel(file, sheet = 1, format = "wide", rmin = NULL, rmax = NULL) } \arguments{ -\item{file}{A vector of filenames including the full path if file is not in current working -directory. The file suffix has to be \code{.xlsx} (used since Excel 2007).} +\item{file}{Path(s) to Excel file(s) (suffix \code{.xlsx}).} -\item{dir}{Alternative way to supply the directory where the file is located -(default \code{NULL}).} +\item{sheet}{Names or indexes of sheet with grid data to import.} -\item{sheet}{Name or index of Excel sheet containing the grid.} +\item{format}{Two formats are supported. \code{wide} (default): each column represents one element, each row represent +one constructs. \code{long}: each row contains one rating value for a element-construct combination. See +sections below and examples.} -\item{min}{Optional argument (\code{numeric}, default \code{NULL}) -for minimum rating value in grid.} - -\item{max}{Optional argument (\code{numeric}, default \code{NULL}) -for maximum rating value in grid.} +\item{rmin, rmax}{Min and max of the rating scale (\code{numeric}, default \code{NULL}).} } \value{ -A single \code{repgrid} object in case one file and -a list of \code{repgrid} objects in case multiple files are imported. +A \code{repgrid} object (one input file) or a named list with \code{repgrid} objects (several input files). List names are +filename + sheet. } \description{ -You can define a grid using Microsoft Excel and by saving it as a -\code{.xlsx} file. The \code{.xlsx} file has to be in a specified fixed -format (see section Details). +You can define a grid in a Microsoft Excel file (suffix \code{.xlsx}). The file must have one of +two formats (\code{wide} or \code{long}, see format sections below). } -\details{ -Excel file structure: The first row contains the minimum of the rating scale, -the names of the elements and the maximum of the rating scale. Below every -row contains the left construct pole, the ratings and the right construct -pole. - -\tabular{lccccr}{ -\code{1} \tab \code{E1} \tab \code{E2} \tab \code{E3} \tab \code{E4} \tab \code{5} \cr -\verb{left pole 1} \tab \code{1} \tab \code{5} \tab \code{3} \tab \code{4} \tab \verb{right pole 1} \cr -\verb{left pole 2} \tab \code{3} \tab \code{1} \tab \code{1} \tab \code{3} \tab \verb{right pole 2} \cr -\verb{left pole 3} \tab \code{4} \tab \code{2} \tab \code{5} \tab \code{1} \tab \verb{right pole 3} \cr +\section{Format \code{wide}}{ + + +In the \code{wide} format, each element has a separate column, and each row contains the ratzings for one construct. +It is a common way to represent grid data and looks like this: + +\tabular{lccccrr}{ +\code{1} \tab \code{element_1} \tab \code{element_2} \tab \code{element_3} \tab \code{element_4} \tab \code{5} \tab \code{preferred} \cr +\code{left_pole_1} \tab \code{1} \tab \code{5} \tab \code{3} \tab \code{4} \tab \code{right_pole_1} \tab \code{left} \cr +\code{left_pole_2} \tab \code{3} \tab \code{1} \tab \code{1} \tab \code{3} \tab \code{right_pole_2} \tab \code{right} \cr +\code{left_pole_3} \tab \code{4} \tab \code{2} \tab \code{5} \tab \code{1} \tab \code{right_pole_3} \tab \code{NA} \cr } -Note that the maximum and minimum value has to be defined using the -\code{min} and \code{max} arguments if no values are supplied at the -beginning and end of the first row. Otherwise the scaling range is inferred -from the available data and a warning is issued as the range may be -erroneous. This may effect other functions that depend on knowing the correct -range and it is thus strongly recommended to set the scale range correctly. +The header row contains the minimum of the rating scale (\code{1}), the names of the elements (\code{element_1} to \code{element_4}), +the maximum of the rating scale (\code{5}), and optionally the column \code{preferred}, indicating the preferred pole. +Each row contains the constructs entries (left pole, ratings, right pole, preferred pole). The preferred pole +must be one of \code{left}, \code{right}, \code{none}, \code{NA} (see \code{\link[=preferredPoles]{preferredPoles()}}). } -\examples{ -\dontrun{ -# Open Excel file delivered along with the package +\section{Format \code{long}}{ + + +The \code{long} format has this name because it has few columns and many rows. It is a common format +in data analytics. Here, each row contains a different element-construct combination and the corresponding rating +value. The format looks like this: + +\tabular{lllrlrr}{ +\code{element} \tab \code{left_pole} \tab \code{right_pole} \tab \code{rating} \tab \code{preferred_pole} \tab \code{rmin} \tab \code{rmax} \cr +\verb{element 1} \tab \verb{left pole 1} \tab \verb{right pole 1} \tab \code{1} \tab \code{left} \tab \code{1} \tab \code{5} \cr +\code{element_2} \tab \verb{left pole 1} \tab \verb{right pole 1} \tab \code{5} \tab \code{left} \tab \code{1} \tab \code{5} \cr +\code{element_3} \tab \verb{left pole 1} \tab \verb{right pole 1} \tab \code{4} \tab \code{left} \tab \code{1} \tab \code{5} \cr +} + +The columns \code{element}, \code{left_pole}, \code{right_pole}, and \code{rating} are mandatory, the columns \code{preferred_pole}, \code{rmin}, +and \code{rmax} are optional. \code{rmin} and \code{rmax} contain the min and max of the rating scale. Alternatively, you may +pass \code{rmin} and \code{rmax} as arguments in the function call. +} + +\examples{ file <- system.file("extdata", "grid_01.xlsx", package = "OpenRepGrid") -rg <- importExcel(file) +rg_1 <- importExcel(file, sheet = "wide") +rg_2 <- importExcel(file, sheet = "long", format = "long") -# To see the structure of the Excel file try to open it as follows. -# Requires Excel to be installed. -system2("open", file) +# Open sample file to inspect it (requires Excel to be installed). +\dontrun{ +browseURL(file) # may not work on all systems } # Import more than one Excel file files <- system.file("extdata", c("grid_01.xlsx", "grid_02.xlsx"), package = "OpenRepGrid") -rg <- importExcel(files) -} +rgs <- importExcel(files) # returns a list of grids +# Impoort from several sheets at once (all must have same format) +file <- system.file("extdata", "grid_03.xlsx", package = "OpenRepGrid") +rgs <- importExcel(file, sheet = 1:3) # by index +rgs <- importExcel(file, sheet = c("grid 1", "grid 2", "grid 3")) # or by name } \seealso{ -\code{\link[=importGridcor]{importGridcor()}}, -\code{\link[=importGridstat]{importGridstat()}}, -\code{\link[=importScivesco]{importScivesco()}}, -\code{\link[=importGridsuite]{importGridsuite()}}, -\code{\link[=importTxt]{importTxt()}} +Import data +\code{\link{importDataframe}()}, +\code{\link{importGridcor}()}, +\code{\link{importGridstat}()}, +\code{\link{importGridsuite}()}, +\code{\link{importScivesco}()}, +\code{\link{importTxt}()} } +\concept{import} diff --git a/man/importExcelInternal.Rd b/man/importExcelInternal.Rd deleted file mode 100644 index 0c74e43c..00000000 --- a/man/importExcelInternal.Rd +++ /dev/null @@ -1,27 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/import.r -\name{importExcelInternal} -\alias{importExcelInternal} -\title{workhorse function (parser) for importExcel.} -\usage{ -importExcelInternal(file, dir = NULL, sheet = 1, min = NULL, max = NULL) -} -\arguments{ -\item{file}{A vector of filenames including the full path if file is not in current working -directory. The file suffix has to be \code{.xlsx} (used since Excel 2007).} - -\item{dir}{Alternative way to supply the directory where the file is located -(default \code{NULL}).} - -\item{sheet}{Name or index of Excel sheet containing the grid.} - -\item{min}{Optional argument (\code{numeric}, default \code{NULL}) -for minimum rating value in grid.} - -\item{max}{Optional argument (\code{numeric}, default \code{NULL}) -for maximum rating value in grid.} -} -\description{ -workhorse function (parser) for importExcel. -} -\keyword{internal} diff --git a/man/importGridcor.Rd b/man/importGridcor.Rd index 1ff23231..f0f464c2 100644 --- a/man/importGridcor.Rd +++ b/man/importGridcor.Rd @@ -50,10 +50,12 @@ for Grid Data (version 4.0). Barcelona: Centro de Terapia Cognitiva. Retrieved from \url{https://repertorygrid.net/en/}. } \seealso{ -\code{\link[=importGridcor]{importGridcor()}}, -\code{\link[=importGridstat]{importGridstat()}}, -\code{\link[=importScivesco]{importScivesco()}}, -\code{\link[=importGridsuite]{importGridsuite()}}, -\code{\link[=importTxt]{importTxt()}}, -\code{\link[=importExcel]{importExcel()}} -} +Import data +\code{\link{importDataframe}()}, +\code{\link{importExcel}()}, +\code{\link{importGridstat}()}, +\code{\link{importGridsuite}()}, +\code{\link{importScivesco}()}, +\code{\link{importTxt}()} +} +\concept{import} diff --git a/man/importGridstat.Rd b/man/importGridstat.Rd index ec84cd4a..4aa96bdf 100644 --- a/man/importGridstat.Rd +++ b/man/importGridstat.Rd @@ -69,6 +69,12 @@ rg <- importGridstat(file, dir, min = 1, max = 6) Bell, R. C. (1998) GRIDSTAT: A program for analyzing the data of a repertory grid. Melbourne: Author. } \seealso{ -\code{\link[=importGridcor]{importGridcor()}}, \code{\link[=importGridstat]{importGridstat()}}, \code{\link[=importScivesco]{importScivesco()}}, \code{\link[=importGridsuite]{importGridsuite()}}, \code{\link[=importTxt]{importTxt()}}, -\code{\link[=importExcel]{importExcel()}} +Import data +\code{\link{importDataframe}()}, +\code{\link{importExcel}()}, +\code{\link{importGridcor}()}, +\code{\link{importGridsuite}()}, +\code{\link{importScivesco}()}, +\code{\link{importTxt}()} } +\concept{import} diff --git a/man/importGridsuite.Rd b/man/importGridsuite.Rd index 946900d9..b2c7d4a6 100644 --- a/man/importGridsuite.Rd +++ b/man/importGridsuite.Rd @@ -51,6 +51,12 @@ Walter, O. B., Bacher, A., & Fromm, M. (2004). A proposal for a common data exc data.\emph{Journal of Constructivist Psychology, 17}(3), 247. \doi{doi:10.1080/10720530490447167} } \seealso{ -\code{\link[=importGridcor]{importGridcor()}}, \code{\link[=importGridstat]{importGridstat()}}, \code{\link[=importScivesco]{importScivesco()}}, \code{\link[=importGridsuite]{importGridsuite()}}, \code{\link[=importTxt]{importTxt()}}, -\code{\link[=importExcel]{importExcel()}} -} +Import data +\code{\link{importDataframe}()}, +\code{\link{importExcel}()}, +\code{\link{importGridcor}()}, +\code{\link{importGridstat}()}, +\code{\link{importScivesco}()}, +\code{\link{importTxt}()} +} +\concept{import} diff --git a/man/importScivesco.Rd b/man/importScivesco.Rd index 781cec1e..9e1d4b4d 100644 --- a/man/importScivesco.Rd +++ b/man/importScivesco.Rd @@ -59,6 +59,12 @@ Menzel, F., Rosenberger, M., Buve, J. (2007). Emotionale, intuitive und rationale Konstrukte verstehen. \emph{Personalfuehrung, 4}(7), 91-99. } \seealso{ -\code{\link[=importGridcor]{importGridcor()}}, \code{\link[=importGridstat]{importGridstat()}}, \code{\link[=importScivesco]{importScivesco()}}, \code{\link[=importGridsuite]{importGridsuite()}}, \code{\link[=importTxt]{importTxt()}}, -\code{\link[=importExcel]{importExcel()}} +Import data +\code{\link{importDataframe}()}, +\code{\link{importExcel}()}, +\code{\link{importGridcor}()}, +\code{\link{importGridstat}()}, +\code{\link{importGridsuite}()}, +\code{\link{importTxt}()} } +\concept{import} diff --git a/man/importTxt.Rd b/man/importTxt.Rd index 22d67ba1..8fc6ff29 100644 --- a/man/importTxt.Rd +++ b/man/importTxt.Rd @@ -90,17 +90,24 @@ thus strongly recommended to set the scale range correctly. file <- system.file("extdata", "grid_01.txt", package = "OpenRepGrid") rg <- importTxt(file) -\dontrun{ # To see the structure of the file, try opening it as follows. # (may not work on all systems) +\dontrun{ file.show(file) } # Import more than one .txt file files <- system.file("extdata", c("grid_01.txt", "grid_02.txt"), package = "OpenRepGrid") rgs <- importTxt(files) + } \seealso{ -\code{\link[=importGridcor]{importGridcor()}}, \code{\link[=importGridstat]{importGridstat()}}, \code{\link[=importScivesco]{importScivesco()}}, \code{\link[=importGridsuite]{importGridsuite()}}, \code{\link[=importTxt]{importTxt()}}, -\code{\link[=importExcel]{importExcel()}} +Import data +\code{\link{importDataframe}()}, +\code{\link{importExcel}()}, +\code{\link{importGridcor}()}, +\code{\link{importGridstat}()}, +\code{\link{importGridsuite}()}, +\code{\link{importScivesco}()} } +\concept{import} diff --git a/man/importTxtInternal.Rd b/man/importTxtInternal.Rd deleted file mode 100644 index 317a21b7..00000000 --- a/man/importTxtInternal.Rd +++ /dev/null @@ -1,92 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/import.r -\name{importTxtInternal} -\alias{importTxtInternal} -\title{ImportTxtInternal is the parser for importTxt.} -\usage{ -importTxtInternal(file, dir = NULL, min = NULL, max = NULL) -} -\arguments{ -\item{file}{Filename including path if file is not in current working -directory. File can also be a complete URL. The fileformat -is \code{.txt}.} - -\item{dir}{Alternative way to supply the directory where the file is located -(default \code{NULL}).} - -\item{min}{Optional argument (\code{numeric}, default \code{NULL}) -for minimum rating value in grid.} - -\item{max}{Optional argument (\code{numeric}, default \code{NULL}) -for maximum rating value in grid.} -} -\value{ -List of relevant data. -} -\description{ -ImportTxtInternal is the parser for importTxt that constructs an import object. The \code{.txt} file has to be in a fixed -format. There are three mandatory blocks each starting and ending with a predefined tag in uppercase letters. The -first block starts with \code{ELEMENTS} and ends with \verb{END ELEMENTS} and contains one element in each line. The other -mandatory blocks contain the constructs and ratings (see below). In the block containing the constructs the left and -right pole are separated by a colon (:). To define missing values use \code{NA} like in the example below. One optional -block contains the range of the rating scale used defined by two numbers. The order of the blocks is arbitrary. All -text not contained within the blocks is discarded and can thus be used for comments. -} -\details{ -\if{html}{\out{
}}\preformatted{---------------- sample .txt file ------------------- - - Note: anything outside the tag pairs is discarded - -ELEMENTS -element 1 -element 2 -element 3 -END ELEMENTS - -CONSTRUCTS -left pole 1 : right pole 1 -left pole 2 : right pole 2 -left pole 3 : right pole 3 -left pole 4 : right pole 4 -END CONSTRUCTS - -RATINGS -1 3 2 -4 1 1 -1 4 4 -3 1 1 -END RATINGS - -RANGE -1 4 -END RANGE - ------------------- end of file ------------------ -}\if{html}{\out{
}} - -Note that the maximum and minimum value has to be defined using the \code{min} and -\code{max} arguments if no \code{RANGE} block is contained in the data file. -Otherwise the scaling range is inferred from the available data and a warning -is issued as the range may be erroneous. This may effect other functions that -depend on knowing the correct range and it is thus strongly recommended to -set the scale range correctly. - -Question marks (?) in the ratings are treated as missing data. -} -\examples{ -\dontrun{ - -# supposing that the data file sample.txt is in the current directory -file <- "sample.txt" -imp <- importTxtInternal(file) - -# specifying a directory (arbitrary example directory) -dir <- "/Users/markheckmann/data" -imp <- importTxtInternal(file, dir) - -# using a full path -imp <- importTxtInternal("/Users/markheckmann/data/sample.txt") -} - -} -\keyword{internal} diff --git a/man/randomGrid.Rd b/man/randomGrid.Rd index 1549283d..28ac47fd 100644 --- a/man/randomGrid.Rd +++ b/man/randomGrid.Rd @@ -11,7 +11,8 @@ randomGrid( nwe = 5, range = c(1, 5), prob = NULL, - options = 1 + options = 1, + preferred = TRUE ) } \arguments{ @@ -31,6 +32,8 @@ If \code{NULL} (default) the distribution is uniform.} \item{options}{Use random sentences as constructs and elements (1) or not (0). If not, the elements and constructs are given default names and are numbered.} + +\item{preferred}{Add preferred pole info? (default \code{TRUE})} } \value{ \code{repgrid} object. @@ -41,10 +44,9 @@ exploring distributions of indexes etc. } \examples{ \dontrun{ - x <- randomGrid() x -x <- randomGrid(10, 25) +x <- randomGrid(10, 25, preferred = FALSE) x x <- randomGrid(10, 25, options = 0) x diff --git a/man/roxygen/meta.R b/man/roxygen/meta.R index 44900ab4..4eef351f 100644 --- a/man/roxygen/meta.R +++ b/man/roxygen/meta.R @@ -1,3 +1,3 @@ list( - rd_family_title = list(align_constructs = "Aligning constructs") + rd_family_title = list(align_constructs = "Aligning constructs", import = "Import data", grid_dataframe = "Other grid dataframes: ") ) diff --git a/man/saveAsExcel.Rd b/man/saveAsExcel.Rd index 39b7b19a..e3dff7a2 100644 --- a/man/saveAsExcel.Rd +++ b/man/saveAsExcel.Rd @@ -2,33 +2,62 @@ % Please edit documentation in R/export.r \name{saveAsExcel} \alias{saveAsExcel} -\title{Save grid in a Microsoft Excel file (.xlsx)} +\title{Save grids as Microsoft Excel file (.xlsx)} \usage{ -saveAsExcel(x, file, sheet = 1) +saveAsExcel(x, file, format = "wide", sheet = NULL, default_sheet = "grid") } \arguments{ -\item{x}{A \code{repgrid} object.} +\item{x}{A \code{repgrid} object or a list of grids.} -\item{file}{Filename to save the grid to. The name should have -the suffix \code{.xlsx}.} +\item{file}{File path. Suffix must be \code{.xlsx}.} -\item{sheet}{Index of the sheet to write to.} +\item{format}{Two output formats are supported: \code{wide} (default) where each column represents one element, each row +represent one constructs (a common grid representation), and \code{long} where each row contains an element-construct +combination and the corresponding rating value. See \code{\link[=importExcel]{importExcel()}} for details and examples.} + +\item{sheet}{Vector of sheet names with same length as \code{x}. If \code{NULL} (default), \code{default_sheet} is used. If \code{x} +is a list if grids, a sequential index is appended. For named list entries (if \code{x} is a list of grids), the name +overwrites the default sheet name.} + +\item{default_sheet}{Default sheet name to use if not supplied in \code{sheet} or via list names of \code{x}.} } \value{ -Invisibly returns the name of the file. +Invisibly returns file path. } \description{ -\code{saveAsExcel} will save the grid as a Microsoft Excel file -(\code{.xlsx}). +\code{saveAsExcel} will save one or more grids in an Excel file (\code{.xlsx}). } \examples{ +# save one grid in wide format (default) +file <- tempfile(fileext = ".xlsx") +saveAsExcel(boeker, file) \dontrun{ +browseURL(file) # open file, requires Excel, may not work on all system +} -x <- randomGrid(options = 0) -saveAsExcel(x, "grid.xlsx") +# save one grid in log format +file <- tempfile(fileext = ".xlsx") +saveAsExcel(boeker, file, format = "long") +\dontrun{ +browseURL(file) } +# save a list of grids +file <- tempfile(fileext = ".xlsx") +l <- list(boeker, feixas2004, bell2010) +saveAsExcel(l, file) +\dontrun{ + browseURL(file) +} + +# pass some sheet names (2nd with named sheet) +file <- tempfile(fileext = ".xlsx") +l <- list(boeker, "feixas' grid" = feixas2004) +saveAsExcel(l, file) +\dontrun{ + browseURL(file) +} } \seealso{ -\code{\link[=importExcel]{importExcel()}} +\code{\link[=importExcel]{importExcel()}}, \code{\link[=saveAsWorksheet]{saveAsWorksheet()}} } diff --git a/man/saveAsWorksheet.Rd b/man/saveAsWorksheet.Rd new file mode 100644 index 00000000..1d938f4b --- /dev/null +++ b/man/saveAsWorksheet.Rd @@ -0,0 +1,57 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/export.r +\name{saveAsWorksheet} +\alias{saveAsWorksheet} +\title{Add grids as sheets to an openxlsx Workbook} +\usage{ +saveAsWorksheet(x, wb, format = "wide", sheet = NULL, default_sheet = "grid") +} +\arguments{ +\item{x}{A \code{repgrid} object or a list of grids.} + +\item{wb}{A \href{https://CRAN.R-project.org/package=openxlsx}{openxlsx} \code{Workbook} object.} + +\item{format}{Two output formats are supported: \code{wide} (default) where each column represents one element, each row +represent one constructs (a common grid representation), and \code{long} where each row contains an element-construct +combination and the corresponding rating value. See \code{\link[=importExcel]{importExcel()}} for details and examples.} + +\item{sheet}{Vector of sheet names with same length as \code{x}. If \code{NULL} (default), \code{default_sheet} is used. If \code{x} +is a list if grids, a sequential index is appended. For named list entries (if \code{x} is a list of grids), the name +overwrites the default sheet name.} + +\item{default_sheet}{Default sheet name to use if not supplied in \code{sheet} or via list names of \code{x}.} +} +\value{ +Invisibly returns Workbook object. +} +\description{ +\code{saveAsWorksheet} will add one or more grids to an a \href{https://CRAN.R-project.org/package=openxlsx}{openxlsx} +\code{Workbook} object. +} +\examples{ +library(openxlsx) + +wb <- createWorkbook() + +# add grid to worksheet +saveAsWorksheet(boeker, wb, sheet = "boeker") + +# add several grids with explicit sheet names +l <- list(bell2010, feixas2004) +saveAsWorksheet(l, wb, sheet = c("Bell 2010", "Feixas 2004")) + +# list names are used as sheet names. Without name, the default applies. +l <- list(boeker, "Fransella et al. 2003" = fbb2003) +saveAsWorksheet(l, wb) + + +# save as Excel file +file <- tempfile(fileext = ".xlsx") +saveWorkbook(wb, file) +\dontrun{ + browseURL(file) # may not work on all systems +} +} +\seealso{ +\code{\link[=saveAsExcel]{saveAsExcel()}} +} diff --git a/tests/testthat/test-gridlist.R b/tests/testthat/test-gridlist.R index 2a168614..91a31f06 100644 --- a/tests/testthat/test-gridlist.R +++ b/tests/testthat/test-gridlist.R @@ -1,5 +1,11 @@ test_that("gridlist works correctly", { + l <- list(boeker, feixas2004) + expect_true(is_list_of_repgrids(l)) + l2 <- append(l, "hello") + expect_false(is_list_of_repgrids(l2)) + gl <- gridlist(boeker, feixas2004) + expect_true(is_list_of_repgrids(gl)) expect_s3_class(gl, "gridlist") expect_length(gl, 2) diff --git a/tests/testthat/test-import.R b/tests/testthat/test-import-export.R similarity index 51% rename from tests/testthat/test-import.R rename to tests/testthat/test-import-export.R index 64a4b040..90f0da59 100644 --- a/tests/testthat/test-import.R +++ b/tests/testthat/test-import-export.R @@ -31,6 +31,36 @@ test_that("importTxt - RATINGS", { # EXCEL -------------------------------------------- +test_that("export-import - roundtrip", { + g_orig <- boeker + + # one grid + file_wide <- saveAsExcel(g_orig, file = tempfile(fileext = ".xlsx"), format = "wide") + g_wide <- importExcel(file_wide, format = "wide") + expect_identical(g_orig, g_wide) + + file_long <- saveAsExcel(g_orig, file = tempfile(fileext = ".xlsx"), format = "long") + g_long <- importExcel(file_long, format = "long") + expect_identical(g_orig, g_long) + + # several grids / sheets + g_orig <- randomGrids(options = 0) + file_several <- saveAsExcel(g_orig, tempfile(fileext = ".xlsx")) + + sheets <- seq_along(g_orig) + g_many <- importExcel(file_several, sheet = sheets) + filename <- file_path_sans_ext(basename(file_several)) + expect_equal(names(g_many), paste0(filename, "-", sheets)) # names contain file + sheet index + expect_equal(g_orig, unname(g_many)) # somewhat unclear why not identical + + sheets <- paste("grid", seq_along(g_orig)) + g_many <- importExcel(file_several, sheet = sheets) + filename <- file_path_sans_ext(basename(file_several)) + expect_equal(names(g_many), paste0(filename, "-", sheets)) # names contain file + sheet name + expect_equal(g_orig, unname(g_many)) # somewhat unclear why not identical +}) + + test_that("importExcel - PREFERRED", { path <- test_path("testdata/grids.xlsx") @@ -48,3 +78,17 @@ test_that("importExcel - PREFERRED", { importExcel(path, sheet = "preferred incorrect 1") ) }) + + +# DATAFRAME -------------------------------------------- + +test_that("importDataframe", { + # sample dataframes yield same results + g1 <- importDataframe(df_element_columns) + g2 <- importDataframe(df_construct_columns, format = "c", rmin = 1, rmax = 5) + preferredPoles(g2) <- c("l", "r", "n") + g3 <- importDataframe(df_long, format = "long") + + expect_identical(g1, g2) + expect_identical(g1, g3) +}) diff --git a/tests/testthat/test-save.R b/tests/testthat/test-save.R new file mode 100644 index 00000000..195eacfd --- /dev/null +++ b/tests/testthat/test-save.R @@ -0,0 +1,43 @@ +require(openxlsx) + + +test_that("saveAsExcel", { + file <- saveAsExcel(boeker, tempfile(fileext = ".xlsx")) + expect_equal(getSheetNames(file), "grid") + + rgs <- randomGrids(nc = 3) + file <- tempfile(fileext = ".xlsx") + saveAsExcel(rgs, file) + expect_equal(getSheetNames(file), paste("grid", 1:3)) + + rgs <- randomGrids(nc = 3) + file <- tempfile(fileext = ".xlsx") + saveAsExcel(rgs, file, default_sheet = "xxxx") + expect_equal(getSheetNames(file), paste("xxxx", 1:3)) + + names(rgs) <- c("my grid", NA, NA) + file <- tempfile(fileext = ".xlsx") + saveAsExcel(rgs, file) + expect_equal(getSheetNames(file), c("my grid", "grid 2", "grid 3")) +}) + + +test_that("saveAsWorkbook", { + wb <- createWorkbook() + saveAsWorksheet(boeker, wb) + expect_equal(names(wb), "grid") + + wb <- createWorkbook() + rgs <- randomGrids(nc = 3) + saveAsWorksheet(rgs, wb) + expect_equal(names(wb), paste("grid", 1:3)) + + wb <- createWorkbook() + names(rgs) <- c("my grid", NA, NA) + saveAsWorksheet(rgs, wb, default_sheet = "xxxx") + expect_equal(names(wb), c("my grid", "xxxx 2", "xxxx 3")) + + wb <- createWorkbook() + saveAsWorksheet(boeker, wb) + expect_error(saveAsWorksheet(boeker, wb), "Worksheet ['\"]grid['\"] already exists") # windows renders \" +}) diff --git a/tests/testthat/test-utils.R b/tests/testthat/test-utils.R index d511ba47..428629e7 100644 --- a/tests/testthat/test-utils.R +++ b/tests/testthat/test-utils.R @@ -27,3 +27,15 @@ test_that("fortify_element_*", { expect_error(fortify_element_id(x, -1)) expect_error(fortify_element_name(x, "xxx")) }) + + +test_that("get_names_na*", { + l1 <- as.list(1:3) + expect_equal(get_names_na(l1), rep(NA_character_, 3)) + + l2 <- list(a = 1, b = 2, 3) + expect_equal(get_names_na(l2), c("a", "b", NA)) + + l3 <- setNames(list(1, 2, 3), c("x", "", "z")) + expect_equal(get_names_na(l3), c("x", NA, "z")) +}) diff --git a/vignettes/web/datasets.Rmd b/vignettes/web/datasets.Rmd index 2b15eb34..7cfb0ab2 100644 --- a/vignettes/web/datasets.Rmd +++ b/vignettes/web/datasets.Rmd @@ -32,6 +32,8 @@ data set name | description and source `slater1977a` | drug addict’s grid dataset from (Slater, 1977, p. 32). `slater1977b` | grid dataset (ranked) from a seventeen year old female psychiatric patient (Slater, 1977, p. 110) showing depression, anxiety and self-mutilation. The data was originally reported by Watson (1970). +You can also get an overview by typing `data(package = "OpenRepGrid")` into the console. + ### R-Code To display one of the grid just type the grid's name into the R console. diff --git a/vignettes/web/images/excel.png b/vignettes/web/images/excel.png deleted file mode 100644 index 3e4dc373..00000000 Binary files a/vignettes/web/images/excel.png and /dev/null differ diff --git a/vignettes/web/images/excel2.png b/vignettes/web/images/excel2.png deleted file mode 100644 index 03557f99..00000000 Binary files a/vignettes/web/images/excel2.png and /dev/null differ diff --git a/vignettes/web/images/excel3.png b/vignettes/web/images/excel3.png new file mode 100644 index 00000000..24e1053c Binary files /dev/null and b/vignettes/web/images/excel3.png differ diff --git a/vignettes/web/images/sample.xlsx b/vignettes/web/images/sample.xlsx new file mode 100644 index 00000000..5e4643d8 Binary files /dev/null and b/vignettes/web/images/sample.xlsx differ diff --git a/vignettes/web/loading.Rmd b/vignettes/web/loading.Rmd index 520cd21d..60e06ea3 100644 --- a/vignettes/web/loading.Rmd +++ b/vignettes/web/loading.Rmd @@ -4,6 +4,7 @@ output: rmarkdown::html_vignette: toc: true toc_depth: 3 + fig_width: 4 vignette: > %\VignetteEngine{knitr::rmarkdown} %\VignetteIndexEntry{Loading} @@ -19,40 +20,51 @@ settings(show.scale = FALSE, show.meta = FALSE) The `OpenRepGrid` R package is able to read files from different other grid programs as well as standard formats (i. e. `.txt`, `.xlsx`). All import functions follow the same naming scheme. They start with the word `import` followed by the program the file is imported from, e.g. `Gridstat`. Hence the function to import a Gridstat file is called `importGridstat`. - ### Loading OpenRepGrid files - #### Microsoft Excel files -You can define a grid file using Microsoft Excel. The `.xlsx` file has to be in a fixed format. See an example of a correct file below. The first row contains the minimum of the rating scale (red), the names of the elements (green) and the maximum of the rating scale (red). Below, every row contains the left construct pole (blue), the ratings (black) and the right construct pole (blue). +You can define a grid file using Excel. The `.xlsx` file has to be in a fixed format. See an example of a correct file below. The first row contains the minimum of the rating scale (red), the names of the elements (green) and the maximum of the rating scale (red). Below, every row contains the left construct pole (blue), the ratings (black) and the right construct pole (blue). The rightmost columns (purple) is optional and contains the preferred pole. Allowed values are +`left`, `right`, `none` or an empty cell. -![](images/excel2.png) +reference diagram - -To load an `.xlsx` file and save it into the object `x` type the following code to the R console (assuming you have a file called `sample.xlsx` exists). +The `OpenRepGrid` package comes with several sample Excel files. If you have Excel installed, you can try opening the sample file `grid_01.xlsx` as follows. ```{r eval=FALSE} -x <- importExcel("sample.xlsx") +file <- system.file("extdata", "grid_01.xlsx", package = "OpenRepGrid") # path to sample file +browseURL(file) # may not work on all systems ``` -The `OpenRepGrid` package comes with an example Excel file. If you have Excel installed, you should be able to open it by typing +You can import the sample file as follows: ```{r eval=FALSE} -file <- system.file("extdata", "grid_01.xlsx", package = "OpenRepGrid") -file.show(file) # may not work on all systems +x <- importExcel(file) ``` +If ax Excel file contains mutliple sheet with grid data (`grid_03.xlsx` has three sheets), you can import them like so. +```{r eval=FALSE} +file <- system.file("extdata", "grid_03.xlsx", package = "OpenRepGrid") # path to sample file +x <- importExcel(file, sheet = 1:3) # indexes or sheet names to import +``` #### .txt files -If you do not have a grid program at hand you can define a grid using a standard text editor and by saving it as a `.txt` file. The `.txt` file has to be in a fixed format. There are three mandatory blocks each starting and ending with a predefined tag in uppercase letters. The first block starts with `ELEMENTS` and ends with `END ELEMENTS` and contains one element in each line. The other mandatory blocks contain the constructs and ratings (see below). In the block containing the constructs the left and right pole are separated by a colon (`:`). The order of the blocks is arbitrary. All text not contained within the blocks is discarded and can thus be used for comments. +If you do not have Excel installed, you can define a grid using a text editor and by saving it as a +`.txt` file. The `.txt` file has to be in a fixed format. There are three mandatory blocks each starting and ending +with a predefined tag in uppercase letters. The first block starts with `ELEMENTS` and ends with` ⁠END ELEMENTS`⁠. It +contains one element per line. The other mandatory blocks are `CONSTRUCTS` and `RATINGS` (see below). In the block +containing the constructs the left and right pole are separated by a colon (:). To define missing values use NA. The +block `PREFERRED` is optional. Each line indicated the preferred construct pole. Allowed values are left, right, none (no +pole preferred), and NA (unknown). The block RANGE is optional but recommended. It gives the rating scale range defined +by two numbers. The order of the blocks is arbitrary. All text outside the blocks is discarded and can be used for +comments. + + ---------------- sample .txt file ------------------- + + Note: anything outside the tag pairs is discarded - ------------ example.txt file --------------- - - anything not contained within the tags will be discarded - ELEMENTS element 1 element 2 @@ -66,6 +78,13 @@ If you do not have a grid program at hand you can define a grid using a standard left pole 4 : right pole 4 END CONSTRUCTS + PREFERRED + left + left + right + none + END PREFERRED + RATINGS 1 3 2 4 1 1 @@ -76,7 +95,8 @@ If you do not have a grid program at hand you can define a grid using a standard RANGE 1 4 END RANGE - ---------------- end of file ---------------- + + ------------------ end of file ------------------ To load the `.txt` file and save it into the object `x` type the following code to the R console. @@ -84,89 +104,94 @@ To load the `.txt` file and save it into the object `x` type the following code x <- importTxt("example.txt") ``` -You have to make sure, that the file exists in the current working directory. If not you either have to specify the whole path to the file or you must change the R working directory. +You have to make sure, that the file exists in the current working directory. If not you either have to specify the whole path to the file or you must change the R working directory. A sample `.txt` file is also contained in the package. The `OpenRepGrid` package comes with an sample `.txt` file. You can load it as follows. ```{r eval=FALSE} -x <- importTxt("my_folder/example.txt") # whole path to file or -getwd() # show current working directory -setwd("my_folder") # change working directory to the folder markheckmann/data -x <- importTxt("example.txt") # load file that is in the current working directory +file <- system.file("extdata", "grid_01.txt", package = "OpenRepGrid") +x <- importTxt(file) ``` -The `OpenRepGrid` package comes with an sample `.txt` file. You can load it as follows. +To open the sample `.txt` file try: ```{r eval=FALSE} -file <- system.file("extdata", "grid_01.txt", package = "OpenRepGrid") -x <- importTxt(file) +browseURL(file) # may not work on all systems ``` -To open the sample `.txt` file try: +#### Convert a dataframe into a grid + +Sometimes, you may want to convert data you loaded elsewhere into a repgrid. A dataframe is a central R data structure and +can easily be converted into a `repgrid` object using `importDataframe`. Please have a look at the docs for details (`?importDataframe`). The +package comes with several sample dataframes, for example, `df_element_columns`. You can import it as follows. ```{r eval=FALSE} -file.show(file) # may not work on all systems +importDataframe(df_element_columns) ``` ### Import files from other grid programs -To import from other grid programs works the same as importing a `.txt` file. Either you specify the file name if it resides in the current R working directory, you supply the whole file path if it is not in the current directory or you do not supply any argumnets and and interactive file selection dialog window will open. +To import from other grid programs works the same as importing a `.txt` file. Either you specify the file name if it resides in the current R working directory, you supply the whole file path if it is not in the current directory. #### Gridcor ```{r eval=FALSE} -x <- importGridcor("gridcor.dat") # file in current R working directory or -x <- importGridcor("markheckmann/data/gridcor.dat") # whole file path or -x <- importGridcor() # open file selection dialog +x <- importGridcor("gridcor.dat") # file in current R working directory ``` #### Gridstat ```{r eval=FALSE} -x <- importGridstat("gridstat.dat") # file in current R working directory or -x <- importGridstat("markheckmann/data/gridstat.dat") # whole file path or -x <- importGridstat() # open file selection dialog +x <- importGridstat("gridstat.dat") # file in current R working directory ``` #### GridSuite ```{r eval=FALSE} -x <- importGridsuite("gridsuite.xml") # file in current R working directory or -x <- importGridsuite("markheckmann/data/gridsuite.xml") # whole file path or -x <- importGridsuite() # open file selection dialog +x <- importGridsuite("gridsuite.xml") # file in current R working directory ``` #### sci:vesco ```{r eval=FALSE} -x <- importScivesco("scivesco.scires") # file in current R working directory or -x <- importScivesco("markheckmann/data/scivesco.scires") # whole file path or -x <- importScivesco() # open file selection dialog +x <- importScivesco("scivesco.scires") # file in current R working directory ``` ### Saving grids -`OpenRepGrid` can currently save grids in two formats. Either as a `.txt` file or as an R data object. +`OpenRepGrid` can currently save grids in several formats. Either as a `.txt` file or as an R data object. + +#### Excel file + +The most convenient format is probably an Excel file. You can save one or more grids to Excel using `saveAsExcel`. + +```{r eval=FALSE} +saveAsExcel(boeker, file = "boeker.xlsx") # save it to the file "boeker.xlsx" +``` + +You can save a list of grids to several sheets as follows. + +```{r eval=FALSE} +l <- list(boeker, bell2010) +saveAsExcel(l, file = "grids.xlsx") # save it to the file "boeker.xlsx" +``` #### .txt file -To save a grid as a `.txt` file use the function `saveAsTxt`. It will save the grid as a .txt file in format used by `OpenRepGrid`. This file format can also easily be edited by hand (see `importTxt` for a description). The function will open an interactive dialog box to let the user enter a filename if no file argument is supplied in the function call. Let's suppose we want to strore the `boeker` grid. +To save a grid as a `.txt` file use the function `saveAsTxt`. It will save the grid as a .txt file in format used by `OpenRepGrid`. This file format can also easily be edited by hand (see `importTxt` for a description). ```{r eval=FALSE} saveAsTxt(boeker, "boeker.txt") # save it to the file "boeker.txt" -saveAsTxt(boeker) # open a dialog box to enter the file name interactively ``` #### R data object -Another option is to save the grid as an `RData` object. This is done by using the function save. +Another option is to save the grid as an `RData` object. This is done by using the function `save`. ```{r eval=FALSE} save(boeker, file = "boeker.RData") # save it to the file "boeker.RData" ``` - -In future versions of OpenRepGrid will also support the `.xml` format once a community standard has been agreed upon.