I have a list a
that I need to transform to a data frame with 17 rows and 2 columns.
a <- list("01-step" = list("41 - 41" = c(41, 41), "7 - 7" = c(7, 7), "10 - 10" = c(10, 10)), "02-step" = list("41 - 58 - 41" = c(41, 58, 41), "78 - 41 - 78" = c(78, 41, 78), "102 - 23 - 102" = c(102, 23, 102)))
I created a function to transform a
to the "transposed" version of this data frame target:
Vector_LabelLengthAndCircuit <- lapply(X = names(a), FUN = function(LabelLength){
list(list(list(list(c(LabelLength, "")))), lapply(X = names(a[[LabelLength]]), FUN = function(LabelCircuit){
VectorCircuit <- a[[LabelLength]][[LabelCircuit]]
CircuitAsPairs <- VectorCircuit
VectorCircuit <- c(VectorCircuit[1], rep(VectorCircuit[-length(VectorCircuit)][-1], each = 2), VectorCircuit[length(VectorCircuit)])
CircuitAsPairs <- unname(split(VectorCircuit, ceiling(seq_along(VectorCircuit) / 2)))
list(list(c(LabelCircuit, "")), CircuitAsPairs)
}))
})
Vector_LabelLengthAndCircuit <- unlist(unlist(unlist(unlist(Vector_LabelLengthAndCircuit, recursive = FALSE), recursive = FALSE), recursive = FALSE), recursive = FALSE)
Vector_LabelLengthAndCircuit <- data.table::rbindlist(list(Vector_LabelLengthAndCircuit))
I first get (transformed list):
Vector_LabelLengthAndCircuit <- unlist(unlist(unlist(unlist(Vector_LabelLengthAndCircuit, recursive = FALSE), recursive = FALSE), recursive = FALSE), recursive = FALSE)
Vector_LabelLengthAndCircuit
[[1]]
[1] "01-step" ""
[[2]]
[1] "41 - 41" ""
[[3]]
[1] 41 41
[[4]]
[1] "7 - 7" ""
[[5]]
[1] 7 7
[[6]]
[1] "10 - 10" ""
[[7]]
[1] 10 10
[[8]]
[1] "02-step" ""
[[9]]
[1] "41 - 58 - 41" ""
[[10]]
[1] 41 58
[[11]]
[1] 58 41
[[12]]
[1] "78 - 41 - 78" ""
[[13]]
[1] 78 41
[[14]]
[1] 41 78
[[15]]
[1] "102 - 23 - 102" ""
[[16]]
[1] 102 23
[[17]]
[1] 23 102
And then I get my "transposed" data frame target:
Vector_LabelLengthAndCircuit <- data.table::rbindlist(list(Vector_LabelLengthAndCircuit))
Vector_LabelLengthAndCircuit
V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 V13 V14 V15 V16 V17
1: 01-step 41 - 41 41 7 - 7 7 10 - 10 10 02-step 41 - 58 - 41 41 58 78 - 41 - 78 78 41 102 - 23 - 102 102 23
2: 41 7 10 58 41 41 78 23 102
Data types are preserved, everything's fine:
str(Vector_LabelLengthAndCircuit)
Classes ‘data.table’ and 'data.frame': 2 obs. of 17 variables:
$ V1 : chr "01-step" ""
$ V2 : chr "41 - 41" ""
$ V3 : num 41 41
$ V4 : chr "7 - 7" ""
$ V5 : num 7 7
$ V6 : chr "10 - 10" ""
$ V7 : num 10 10
$ V8 : chr "02-step" ""
$ V9 : chr "41 - 58 - 41" ""
$ V10: num 41 58
$ V11: num 58 41
$ V12: chr "78 - 41 - 78" ""
$ V13: num 78 41
$ V14: num 41 78
$ V15: chr "102 - 23 - 102" ""
$ V16: num 102 23
$ V17: num 23 102
- attr(*, ".internal.selfref")=<externalptr>
Within a data frame, each column only accepts one single data type, and not a mix of data types (e.g. character and numeric values), so if I transpose the previous data frame, numeric values will be automatically converted to character values, which I don't want.
Hence my initial question: Is there a specific kind of data frame object that could contain mixed data types within one column across different rows?
Ultimately, why do I need in the first place to transform the list a
to a data frame with 17 rows and 2 columns? Because I want to write this 'data frame' to an Excel file in 2 columns across 17 rows with the function writeData
of the package openxlsx
that is (apparently) not able to write the first transformed list (only objects of types vector, matrix and data frame).
The "solution" I posted some months ago to write plain numbers as formulas with the Excel formula =VALUE([numeric data])
was really ugly.
In the meantime I found it's possible to write plain numbers as formulas in a clean way and simply via writeData
by specifying the class formula
.
A related openxlsx2
's Github discussion can be found here (it's related to openxlsx2
but it works the same for the two sister packages openxlsx
and openxlsx2
): https://github.com/JanMarvin/openxlsx2/discussions/1274
Full code:
Vector_LabelLengthAndCircuit <- unlist(lapply(X = names(AllCircuits[[Transaction.Type]][["Circuits"]]), FUN = function(LabelLength){
c(paste0('"', LabelLength, '"'), '', unlist(lapply(X = names(AllCircuits[[Transaction.Type]][["Circuits"]][[LabelLength]]), FUN = function(LabelCircuit){
VectorCircuit <- AllCircuits[[Transaction.Type]][["Circuits"]][[LabelLength]][[LabelCircuit]]
VectorCircuit <- rep(VectorCircuit, each = 2)
VectorCircuit <- VectorCircuit[-1]
VectorCircuit <- VectorCircuit[-length(VectorCircuit)]
c(paste0('"', LabelCircuit, '"'), '', VectorCircuit)
})))
}))
Matrix_LabelLengthAndCircuit <- as.data.frame(matrix(data = Vector_LabelLengthAndCircuit, ncol = 2, byrow = TRUE))
lapply(X = seq_along(colnames(Matrix_LabelLengthAndCircuit)), function(col){class(Matrix_LabelLengthAndCircuit[, col]) <<- c(class(Matrix_LabelLengthAndCircuit[, col]), "formula")})
writeData(wb = Workbook_Individual, sheet = sheetName_Temp, x = Matrix_LabelLengthAndCircuit, startRow = StartingRow, startCol = StartingColumn, colNames = FALSE)