library("broadcast")
# Example 1: Basics ====
<- list(
x group1 = list(
class1 = list(
height = rnorm(10, 170),
weight = rnorm(10, 80),
sex = sample(c("M", "F", NA), 10, TRUE)
),class2 = list(
height = rnorm(10, 170),
weight = rnorm(10, 80),
sex = sample(c("M", "F", NA), 10, TRUE)
)
),group2 = list(
class1 = list(
height = rnorm(10, 170),
weight = rnorm(10, 80),
sex = sample(c("M", "F", NA), 10, TRUE)
),class2 = list(
height = rnorm(10, 170),
weight = rnorm(10, 80),
sex = sample(c("M", "F", NA), 10, TRUE)
)
)
)
# predict what dimensions `x` would have if casted as dimensional:
hier2dim(x)
##
## 3 2 2
<- cast_hier2dim(x) # cast as dimensional
x2
# since the original list uses the same names for all elements within the same depth,
# dimnames can be set easily:
dimnames(x2) <- list( # go from deep names to surface names
names( x[[1]][[1]] ),
names( x[[1]] ),
names( x )
)print(x2) # very compact, maybe too compact...?
## , , group1
##
## class1 class2
## height numeric,10 numeric,10
## weight numeric,10 numeric,10
## sex character,10 character,10
##
## , , group2
##
## class1 class2
## height numeric,10 numeric,10
## weight numeric,10 numeric,10
## sex character,10 character,10
# print a small portion of the list, but less compact:
cast_dim2flat(x2[, 1:2, "group1", drop = FALSE])
## $`['height', 'class1', 'group1']`
## [1] 168.8844 169.3055 169.4714 169.7023 170.0391 168.9013 168.4029 171.4671
## [9] 169.3955 169.9233
##
## $`['weight', 'class1', 'group1']`
## [1] 79.76365 81.15947 79.16389 78.55818 79.96487 80.17278 80.75643 80.05269
## [9] 78.97400 80.05002
##
## $`['sex', 'class1', 'group1']`
## [1] "F" "F" NA "M" "M" NA NA NA NA "M"
##
## $`['height', 'class2', 'group1']`
## [1] 171.3887 170.3333 169.6382 169.7450 170.9797 170.8379 171.6915 170.2045
## [9] 171.6251 169.6337
##
## $`['weight', 'class2', 'group1']`
## [1] 78.54803 80.61660 78.90664 80.03647 81.70199 80.23944 81.05235 79.23034
## [9] 79.11562 79.52628
##
## $`['sex', 'class2', 'group1']`
## [1] NA "M" "F" NA "F" NA NA "F" "F" "F"
# Example 2: Cast from outside to inside ====
<- list(
x group1 = list(
class1 = list(
height = rnorm(10, 170),
weight = rnorm(10, 80),
sex = sample(c("M", "F", NA), 10, TRUE)
),class2 = list(
height = rnorm(10, 170),
weight = rnorm(10, 80),
sex = sample(c("M", "F", NA), 10, TRUE)
)
),group2 = list(
class1 = list(
height = rnorm(10, 170),
weight = rnorm(10, 80),
sex = sample(c("M", "F", NA), 10, TRUE)
),class2 = list(
height = rnorm(10, 170),
weight = rnorm(10, 80),
sex = sample(c("M", "F", NA), 10, TRUE)
)
)
)
# by default, `in2out = TRUE`;
# for this example, `in2out = FALSE` is used
# predict what dimensions `x` would have if casted as dimensional:
hier2dim(x, in2out = FALSE)
##
## 2 2 3
<- cast_hier2dim(x, in2out = FALSE) # cast as dimensional
x2
# since the original list uses the same names for all elements within the same depth,
# dimnames can be set easily:
# because in2out = FALSE, go from the shallow names to the deeper names:
dimnames(x2) <- list(
names( x ),
names( x[[1]] ),
names( x[[1]][[1]] )
)print(x2) # very compact, maybe too compact...?
## , , height
##
## class1 class2
## group1 numeric,10 numeric,10
## group2 numeric,10 numeric,10
##
## , , weight
##
## class1 class2
## group1 numeric,10 numeric,10
## group2 numeric,10 numeric,10
##
## , , sex
##
## class1 class2
## group1 character,10 character,10
## group2 character,10 character,10
# print a small portion of the list, but less compact:
cast_dim2flat(x2["group1", 1:2, , drop = FALSE])
## $`['group1', 'class1', 'height']`
## [1] 168.6068 170.2025 169.5394 172.1509 170.4328 170.5138 169.5229 171.0381
## [9] 169.9811 170.7287
##
## $`['group1', 'class2', 'height']`
## [1] 170.1237 169.4447 169.7150 169.0544 170.7450 169.9229 170.3794 169.2550
## [9] 169.1472 170.5456
##
## $`['group1', 'class1', 'weight']`
## [1] 79.07508 80.90087 80.21890 80.53534 78.45681 80.18640 81.58115 78.41691
## [9] 80.28970 80.11139
##
## $`['group1', 'class2', 'weight']`
## [1] 79.72999 79.42983 80.25719 80.22538 79.65252 80.98775 79.71258 80.69366
## [9] 79.06923 79.27470
##
## $`['group1', 'class1', 'sex']`
## [1] "F" NA "M" NA "F" "M" "M" "F" "M" "M"
##
## $`['group1', 'class2', 'sex']`
## [1] "F" NA NA NA NA "F" "F" "F" "F" "M"
# Example 3: padding ====
# For Example 3, take the same list as before, but remove x$group1$class2:
<- list(
x group1 = list(
class1 = list(
height = rnorm(10, 170),
weight = rnorm(10, 80),
sex = sample(c("M", "F", NA), 10, TRUE)
)
),group2 = list(
class1 = list(
height = rnorm(10, 170),
weight = rnorm(10, 80),
sex = sample(c("M", "F", NA), 10, TRUE)
),class2 = list(
height = rnorm(10, 170),
weight = rnorm(10, 80),
sex = sample(c("M", "F", NA), 10, TRUE)
)
)
)
hier2dim(x) # as indicated here, dimension 2 (i.e. columns) will have padding
## padding
## 3 2 2
# casting this to a dimensional list will resulting in padding with `NULL`:
<- cast_hier2dim(x)
x2 print(x2)
## , , 1
##
## [,1] [,2]
## [1,] numeric,10 NULL
## [2,] numeric,10 NULL
## [3,] character,10 NULL
##
## , , 2
##
## [,1] [,2]
## [1,] numeric,10 numeric,10
## [2,] numeric,10 numeric,10
## [3,] character,10 character,10
# The `NULL` values are added for padding.
# This is because all slices of the same dimension need to have the same number of elements.
# For example, all rows need to have the same number of columns.
# one can also use custom padding:
<- cast_hier2dim(x, padding = list(~ "this is padding"))
x2 print(x2)
## , , 1
##
## [,1] [,2]
## [1,] numeric,10 ~"this is padding"
## [2,] numeric,10 ~"this is padding"
## [3,] character,10 ~"this is padding"
##
## , , 2
##
## [,1] [,2]
## [1,] numeric,10 numeric,10
## [2,] numeric,10 numeric,10
## [3,] character,10 character,10
# because `x2` needs padding, there is no guarantee you can set dimnames using `x` properly:
if(requireNamespace("tinytest")) {
::expect_error(
tinytestdimnames(x2) <- list(
names( x[[1]][[1]] ),
names( x[[1]] ),
names( x )
),pattern = "length of 'dimnames' [2] not equal to array extent", # error message
fixed = TRUE
)
}## ----- PASSED : <-->
## call| tinytest::expect_error(dimnames(x2) <- list(names(x[[1]][[1]]),
## call| names(x[[1]]), names(x)), pattern = "length of 'dimnames' [2] not equal to array extent",
## call| fixed = TRUE)
# in this case I know what the dimnames should be, so I can try like so:
dimnames(x2) <- list(
c("height", "weight", "sex"),
c("class1", "class2"),
c("group1", "group2")
)
print(x2)
## , , group1
##
## class1 class2
## height numeric,10 ~"this is padding"
## weight numeric,10 ~"this is padding"
## sex character,10 ~"this is padding"
##
## , , group2
##
## class1 class2
## height numeric,10 numeric,10
## weight numeric,10 numeric,10
## sex character,10 character,10
cast_dim2flat(x2[1:2, , , drop = FALSE])
## $`['height', 'class1', 'group1']`
## [1] 170.2391 168.3717 169.5336 170.4431 169.6929 171.2758 171.2258 169.2087
## [9] 169.5819 170.0362
##
## $`['weight', 'class1', 'group1']`
## [1] 80.14299 78.75395 78.98962 81.22911 82.13576 80.81565 80.51676 78.98631
## [9] 80.86654 80.82321
##
## $`['height', 'class2', 'group1']`
## ~"this is padding"
##
## $`['weight', 'class2', 'group1']`
## ~"this is padding"
##
## $`['height', 'class1', 'group2']`
## [1] 169.9678 169.2674 169.4330 169.8741 172.0534 169.4503 169.2445 171.8089
## [9] 171.3814 170.0790
##
## $`['weight', 'class1', 'group2']`
## [1] 79.72124 79.64039 79.48213 79.23543 78.88011 79.75151 77.92625 79.52045
## [9] 81.22483 79.93831
##
## $`['height', 'class2', 'group2']`
## [1] 169.1040 170.3402 170.9394 169.7838 171.8775 169.6848 171.4707 169.7344
## [9] 170.1751 169.5916
##
## $`['weight', 'class2', 'group2']`
## [1] 79.80892 80.26522 79.34193 79.42257 79.39548 82.03909 79.64653 79.43924
## [9] 80.16008 79.91246
# we can also use in2out = FALSE:
<- cast_hier2dim(x, in2out = FALSE, padding = list(~ "this is padding"))
x2 dimnames(x2) <- list( # notice the order here is reversed, because in2out = FALSE
c("group1", "group2"),
c("class1", "class2"),
c("height", "weight", "sex")
)print(x2)
## , , height
##
## class1 class2
## group1 numeric,10 ~"this is padding"
## group2 numeric,10 numeric,10
##
## , , weight
##
## class1 class2
## group1 numeric,10 ~"this is padding"
## group2 numeric,10 numeric,10
##
## , , sex
##
## class1 class2
## group1 character,10 ~"this is padding"
## group2 character,10 character,10
cast_dim2flat(x2[, , 1:2, drop = FALSE])
## $`['group1', 'class1', 'height']`
## [1] 170.2391 168.3717 169.5336 170.4431 169.6929 171.2758 171.2258 169.2087
## [9] 169.5819 170.0362
##
## $`['group2', 'class1', 'height']`
## [1] 169.9678 169.2674 169.4330 169.8741 172.0534 169.4503 169.2445 171.8089
## [9] 171.3814 170.0790
##
## $`['group1', 'class2', 'height']`
## ~"this is padding"
##
## $`['group2', 'class2', 'height']`
## [1] 169.1040 170.3402 170.9394 169.7838 171.8775 169.6848 171.4707 169.7344
## [9] 170.1751 169.5916
##
## $`['group1', 'class1', 'weight']`
## [1] 80.14299 78.75395 78.98962 81.22911 82.13576 80.81565 80.51676 78.98631
## [9] 80.86654 80.82321
##
## $`['group2', 'class1', 'weight']`
## [1] 79.72124 79.64039 79.48213 79.23543 78.88011 79.75151 77.92625 79.52045
## [9] 81.22483 79.93831
##
## $`['group1', 'class2', 'weight']`
## ~"this is padding"
##
## $`['group2', 'class2', 'weight']`
## [1] 79.80892 80.26522 79.34193 79.42257 79.39548 82.03909 79.64653 79.43924
## [9] 80.16008 79.91246
cast_hier2dim
Cast Hierarchical List into Dimensional list
Description
cast_hier2dim()
casts a hierarchical/nested list into a dimensional list (i.e. an array of type list
).
hier2dim()
takes a hierarchical/nested list, and predicts what dimensions the list would have, if casted by the cast_hier2dim()
function.
Usage
cast_hier2dim(x, ...)
hier2dim(x, ...)
## Default S3 method:
cast_hier2dim(
x,
in2out = TRUE,
maxdepth = 16L,
recurse_classed = FALSE,
padding = list(NULL),
...
)
## Default S3 method:
hier2dim(x, in2out = TRUE, maxdepth = 16L, recurse_classed = FALSE, ...)
Arguments
x
|
a nested list. If x has redundant nesting, it is advisable (though not necessary) to reduce the redundant nesting using dropnests.
|
…
|
further arguments passed to or from methods. |
in2out
|
see broadcast_casting. |
maxdepth
|
a single, positive integer, giving the maximum depth to recurse into the list. The surface-level elements of a list is depth 1. |
recurse_classed
|
TRUE or FALSE , indicating if the function should also recurse through classed lists within x , like data.frames.
|
padding
|
a list of length 1 , giving the padding value to use when padding is required. Padding is used to ensure every all slices of the same dimension in the output have equal number of elements (for example, all rows must have the same number of columns). |
Value
For hier2dim()
:
An integer vector, giving the dimensions x
would have, if casted by cast_hier2dim()
.
The names of the output indicates if padding is required (name "padding"), or no padding is required (no name) for that dimension;
Padding will be required if not all list-elements at a certain depth have the same length.
For cast_hier2dim()
:
An array of type list
, with the dimensions given by hier2dim()
.
If the output needs padding (indicated by hier2dim()
), the output will have more elements than x
, filled with a padding value (as specified in the padding
argument).