@@ -973,34 +973,61 @@ dbind <- function(..., force_unique_names = FALSE) {
973973
974974
975975 # Convert all matrices to ISMs if they aren't already.
976- mats <- lapply(mats , function (x ) {
976+ # Also build a parallel vector of group labels for each entry.
977+ input_names <- names(mats )
978+ converted <- lapply(seq_along(mats ), function (i ) {
979+ x <- mats [[i ]]
980+ nm <- if (! is.null(input_names ) && nzchar(input_names [i ])) input_names [i ] else NA_character_
981+
977982 if (is(x , " BlockedInfinitySparseMatrix" )) {
978- # Replace BISM with list of ISMs
979- findSubproblems(x )
983+ # Replace BISM with list of ISMs; use its existing group level names
984+ sp <- findSubproblems(x )
985+ list (mats = sp , labels = names(sp ))
980986 } else if (inherits(x , " list" )) {
981987 # If any entry in ... is a list,
988+ inner_names <- names(x )
982989 # 1) Convert all entries in that list to ISM while keeping BISM as BISM
983990 x <- lapply(x , .as.ism_or_bism )
984- # 2) If we have any BISMs, split into list of ISMS
985- x <- lapply(x , function (y ) {
991+ # 2) If we have any BISMs, split into list of ISMs, preserving labels
992+ inner_converted <- lapply(seq_along(x ), function (j ) {
993+ y <- x [[j ]]
994+ inner_nm <- if (! is.null(inner_names ) && nzchar(inner_names [j ])) inner_names [j ] else NA_character_
986995 if (is(y , " BlockedInfinitySparseMatrix" )) {
987- findSubproblems(y )
996+ sp <- findSubproblems(y )
997+ list (mats = sp , labels = names(sp ))
988998 } else {
989- y
999+ list ( mats = y , labels = inner_nm )
9901000 }
9911001 })
9921002 # 3) pull list of lists into list
993- flatten_list(x )
1003+ list (mats = flatten_list(lapply(inner_converted , `[[` , " mats" )),
1004+ labels = unlist(lapply(inner_converted , `[[` , " labels" )))
9941005 } else {
9951006 # This will error appropriately if some element in `mats` cannot be
9961007 # converted to an ISM.
997- .as.ism_or_bism(x )
1008+ list ( mats = .as.ism_or_bism(x ), labels = nm )
9981009 }
9991010 })
10001011
10011012 # If we were passed any BISMs, we have a list of lists of ISM, so flatten to a
10021013 # single list.
1003- mats <- flatten_list(mats )
1014+ mats <- flatten_list(lapply(converted , `[[` , " mats" ))
1015+ group_labels <- unlist(lapply(converted , `[[` , " labels" ))
1016+
1017+ # Replace NA labels (from unnamed entries) with numeric indices based on
1018+ # their position, incrementing to avoid collisions with existing labels.
1019+ na_idx <- which(is.na(group_labels ))
1020+ if (length(na_idx ) > 0 ) {
1021+ existing <- group_labels [! is.na(group_labels )]
1022+ for (i in na_idx ) {
1023+ candidate <- i
1024+ while (as.character(candidate ) %in% existing ) {
1025+ candidate <- candidate + 1L
1026+ }
1027+ group_labels [i ] <- as.character(candidate )
1028+ existing <- c(existing , as.character(candidate ))
1029+ }
1030+ }
10041031
10051032 # new row and column positions are based on current, incrementing by number of
10061033 # rows/columns in all previous matrices.
@@ -1052,10 +1079,10 @@ dbind <- function(..., force_unique_names = FALSE) {
10521079 newdim <- as.integer(c(sum(vapply(lapply(mats , methods :: slot , " dimension" ), " [" , 1 , 1 )),
10531080 sum(vapply(lapply(mats , methods :: slot , " dimension" ), " [" , 1 , 2 ))))
10541081
1055- # This needs to be much smarter, especially if any element is already a BISM
1056- groups <- as.factor(rep(seq_along(mats ), times =
1082+ groups <- factor (rep(group_labels , times =
10571083 vapply(lapply(mats , slot , " colnames" ), length , 1 ) +
1058- vapply(lapply(mats , slot , " rownames" ), length , 1 )))
1084+ vapply(lapply(mats , slot , " rownames" ), length , 1 )),
1085+ levels = unique(group_labels ))
10591086 names(groups ) <- do.call(c , Map(c , cnameslist , rnameslist ))
10601087
10611088 newdata <- do.call(c , mats )
0 commit comments