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).

See Also

broadcast_casting

Examples

library("broadcast")



# Example 1: Basics ====
x <- list(
  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

x2 <- cast_hier2dim(x) # cast as dimensional

# 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
  c("height", "weight", "sex"),
  c("class1", "class2"),
  c("group1", "group2")
)

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] 170.6042 171.9795 170.6307 170.7786 168.6365 171.5205 170.0569 169.1496
##  [9] 170.0763 169.6165
## 
## $`['weight', 'class1', 'group1']`
##  [1] 79.78112 78.90160 80.02882 79.85185 78.21930 80.01095 80.39764 79.82635
##  [9] 80.50099 80.22546
## 
## $`['sex', 'class1', 'group1']`
##  [1] NA  "M" "M" "F" "F" "M" "F" "F" "M" "M"
## 
## $`['height', 'class2', 'group1']`
##  [1] 171.0616 169.4523 170.4265 169.8087 169.6036 170.3339 169.7548 171.9040
##  [9] 169.0931 170.6154
## 
## $`['weight', 'class2', 'group1']`
##  [1] 77.78165 80.19957 79.51302 77.98475 81.52433 81.51517 81.51772 80.13911
##  [9] 80.75998 79.47356
## 
## $`['sex', 'class2', 'group1']`
##  [1] NA  NA  "M" "F" NA  "F" NA  "M" NA  NA


# Example 2: Cast from outside to inside ====
x <- list(
  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

x2 <- cast_hier2dim(x, in2out = FALSE) # cast as dimensional

# 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( # notice the order here is reversed, because in2out = FALSE
  c("group1", "group2"),
  c("class1", "class2"),
  c("height", "weight", "sex")
)

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] 171.0218 170.3662 171.3369 170.9799 168.9284 168.8926 170.5418 170.0679
##  [9] 169.4576 170.2209
## 
## $`['group1', 'class2', 'height']`
##  [1] 169.5231 168.6803 169.0853 168.9612 168.5667 170.7949 170.6937 169.7317
##  [9] 170.5907 169.4940
## 
## $`['group1', 'class1', 'weight']`
##  [1] 79.93001 80.13409 80.56831 79.88790 80.84925 80.31629 79.29787 82.12457
##  [9] 79.89329 80.50265
## 
## $`['group1', 'class2', 'weight']`
##  [1] 79.45174 79.82986 78.35989 81.07783 81.87092 79.75102 77.94752 79.33953
##  [9] 79.91751 78.24712
## 
## $`['group1', 'class1', 'sex']`
##  [1] "F" "F" "F" "M" "F" "F" NA  "M" "M" NA 
## 
## $`['group1', 'class2', 'sex']`
##  [1] "F" "F" "M" NA  NA  NA  "M" "M" NA  NA



# Example 3: padding ====

# For Example 3, take the same list as before, but remove x$group1$class2:

x <- list(
  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`:
x2 <- cast_hier2dim(x)
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:
x2 <- cast_hier2dim(x, padding = list(~ "this is padding"))
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

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] 168.8384 170.9978 171.0415 170.5444 170.0234 168.6327 170.5333 170.1162
##  [9] 170.5859 167.9903
## 
## $`['weight', 'class1', 'group1']`
##  [1] 78.76536 79.35851 81.37694 79.59842 80.60071 81.51864 81.48337 80.09223
##  [9] 79.26298 80.10139
## 
## $`['height', 'class2', 'group1']`
## ~"this is padding"
## 
## $`['weight', 'class2', 'group1']`
## ~"this is padding"
## 
## $`['height', 'class1', 'group2']`
##  [1] 168.3330 169.3250 169.8252 172.0827 171.2289 170.6383 169.9687 170.1287
##  [9] 168.7845 168.0444
## 
## $`['weight', 'class1', 'group2']`
##  [1] 80.62209 79.39244 81.11725 78.34978 80.21608 79.55982 80.43173 80.03030
##  [9] 79.60238 80.83670
## 
## $`['height', 'class2', 'group2']`
##  [1] 170.8469 171.5093 171.0565 168.4115 171.5525 172.2902 169.6402 170.8277
##  [9] 171.9081 169.5441
## 
## $`['weight', 'class2', 'group2']`
##  [1] 80.77095 79.73209 80.83369 79.96786 81.92833 80.64972 80.01695 78.44646
##  [9] 80.87572 79.50131

# we can also use in2out = FALSE:
x2 <- cast_hier2dim(x, in2out = FALSE, padding = list(~ "this is padding"))
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] 168.8384 170.9978 171.0415 170.5444 170.0234 168.6327 170.5333 170.1162
##  [9] 170.5859 167.9903
## 
## $`['group2', 'class1', 'height']`
##  [1] 168.3330 169.3250 169.8252 172.0827 171.2289 170.6383 169.9687 170.1287
##  [9] 168.7845 168.0444
## 
## $`['group1', 'class2', 'height']`
## ~"this is padding"
## 
## $`['group2', 'class2', 'height']`
##  [1] 170.8469 171.5093 171.0565 168.4115 171.5525 172.2902 169.6402 170.8277
##  [9] 171.9081 169.5441
## 
## $`['group1', 'class1', 'weight']`
##  [1] 78.76536 79.35851 81.37694 79.59842 80.60071 81.51864 81.48337 80.09223
##  [9] 79.26298 80.10139
## 
## $`['group2', 'class1', 'weight']`
##  [1] 80.62209 79.39244 81.11725 78.34978 80.21608 79.55982 80.43173 80.03030
##  [9] 79.60238 80.83670
## 
## $`['group1', 'class2', 'weight']`
## ~"this is padding"
## 
## $`['group2', 'class2', 'weight']`
##  [1] 80.77095 79.73209 80.83369 79.96786 81.92833 80.64972 80.01695 78.44646
##  [9] 80.87572 79.50131