From f78d297b03a65a723ceacd44dcfde078ec6734ad Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 1 Sep 2026 07:10:06 +0000 Subject: [PATCH 1/2] Fix df.row.2.named.vector() always returning a list, never a vector df.row.2.named.vector() computed as.vector(df[row, , drop = TRUE]). Base R's drop = TRUE only lets a single-COLUMN selection simplify to an atomic vector; extracting one ROW across multiple columns never simplifies this way, regardless of drop, because a row spanning mixed-type columns can't automatically collapse to one atomic type. So df[row, , drop = TRUE] is always a one-row data.frame/tibble (list-like), and as.vector() on that just returns the equivalent list - not an atomic vector as the function's own name and @description promise ("Convert a dataframe row into a vector"). Confirmed this fails for plain data.frame input too, not only tibbles as originally suspected - the function never actually worked for its stated purpose, for any input. Fix: use unlist(df[row, , drop = TRUE], use.names = FALSE) instead of as.vector(...) - unlist() correctly flattens the one-row list-like object into a proper atomic vector (coercing to a common type across columns where needed, same as any other unlist() call on mixed-type data). Verified: returns a proper named atomic vector for both a plain data.frame and a tibble (previously both returned a list); the existing names = feature (naming from a separate ID column) is unaffected. Version bumped 2.8.16 -> 2.8.22 (distinct from sibling PRs #75/#76/#77/#78/#79, which also branch from the same 2.8.16 base and already claimed 2.8.17-2.8.21). --- DESCRIPTION | 2 +- Development/config.R | 2 +- R/CodeAndRoll2.R | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 227f9ee..2b3b417 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: CodeAndRoll2 Title: CodeAndRoll2 for vector, matrix and list manipulations -Version: 2.8.16 +Version: 2.8.22 Authors@R: person("Abel", "Vertesy", , "av@imba.oeaw.ac.at", role = c("aut", "cre")) Description: CodeAndRoll2 is a set of more than 170 productivity functions diff --git a/Development/config.R b/Development/config.R index cc4bdcb..a75d39b 100644 --- a/Development/config.R +++ b/Development/config.R @@ -3,7 +3,7 @@ DESCRIPTION <- list( package.name = "CodeAndRoll2", - version = "2.8.16", + version = "2.8.22", title = "CodeAndRoll2 for vector, matrix and list manipulations", description = "CodeAndRoll2 is a set of more than 170 productivity functions for vector, matrix and list manipulations and math. Used by MarkdownReports, ggExpress, SeuratUtils, etc.", diff --git a/R/CodeAndRoll2.R b/R/CodeAndRoll2.R index efafc51..f4af48a 100644 --- a/R/CodeAndRoll2.R +++ b/R/CodeAndRoll2.R @@ -1048,7 +1048,7 @@ df.col.2.named.vector <- function(df, col, names = NULL) { df.row.2.named.vector <- function(df, row, names = NULL) { stopifnot(length(row) == 1) - vec <- as.vector(df[row, , drop = TRUE]) + vec <- unlist(df[row, , drop = TRUE], use.names = FALSE) names(vec) <- if (is.null(names)) colnames(df) else as.vector(unlist(df[names])) return(vec) } From 9e3e65ba3e4a5e337042eacce1ce23382dc64b66 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 1 Sep 2026 07:15:26 +0000 Subject: [PATCH 2/2] Fix df.row.2.named.vector() silently converting factor labels to integer codes unlist() silently replaces factor values with their underlying integer level codes when combined with non-factor elements in the same list (a well-known R gotcha - e.g. unlist(list(factor("b", levels=c("a","b")), 5)) is c(2, 5), not c("b","5")). Since df[row, , drop=TRUE] is a list of per-column values, any factor column in a mixed-type row silently became its integer code instead of its label (e.g. "control" became "1"). Fix: convert factor elements to character before unlist()-ing, so their displayed labels are preserved instead of their internal integer codes. Verified: a data.frame row with a factor column mixed with a numeric column now correctly returns the factor's label ("control") instead of its integer code; all previously-verified scenarios (plain data.frame, tibble, the names= column-source feature) are unaffected. --- R/CodeAndRoll2.R | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/R/CodeAndRoll2.R b/R/CodeAndRoll2.R index f4af48a..40c3b0a 100644 --- a/R/CodeAndRoll2.R +++ b/R/CodeAndRoll2.R @@ -1048,7 +1048,8 @@ df.col.2.named.vector <- function(df, col, names = NULL) { df.row.2.named.vector <- function(df, row, names = NULL) { stopifnot(length(row) == 1) - vec <- unlist(df[row, , drop = TRUE], use.names = FALSE) + row_list <- lapply(df[row, , drop = TRUE], function(x) if (is.factor(x)) as.character(x) else x) + vec <- unlist(row_list, use.names = FALSE) names(vec) <- if (is.null(names)) colnames(df) else as.vector(unlist(df[names])) return(vec) }