sort alphanumeric values within a list format
Usage
mixedSorts(
x,
blanksFirst = TRUE,
na.last = NAlast,
keepNegative = FALSE,
keepInfinite = TRUE,
keepDecimal = FALSE,
ignore.case = TRUE,
useCaseTiebreak = TRUE,
sortByName = FALSE,
na.rm = FALSE,
verbose = FALSE,
NAlast = TRUE,
honorFactor = TRUE,
xclass = NULL,
indent = 0,
debug = FALSE,
...
)Arguments
- x
vector- blanksFirst
logicalwhether to order blank entries before entries containing a value.- na.last
logicalindicating whether to move NA entries at the end of the sort.- keepNegative
logicalwhether to keep '-' associated with adjacent numeric values, in order to sort them as negative values.- keepInfinite
logicalwhether to allow "Inf" to be considered a numeric infinite value.- keepDecimal
logicalwhether to keep the decimal in numbers, sorting as a true number and not as a version number. By default keepDecimal=FALSE, which means "v1.200" should be ordered before "v1.30". When keepDecimal=TRUE, the numeric sort considers only "1.2" and "1.3" and sorts in that order.- ignore.case
logicalwhether to ignore uppercase and lowercase characters when defining the sort order. Note that whenxisfactorthe factor levels are converted usingunique(toupper(levels(x))), therefore the values inxwill be sorted by factor level.- useCaseTiebreak
logicalindicating whether to break ties whenignore.case=TRUE, using mixed case as a tiebreaker.- sortByName
logicalwhether to sort the vector x by names(x) instead of sorting by x itself.- na.rm
logical, default FALSE, indicating whether to remove NA values.- verbose
logicalwhether to print verbose output.- NAlast
logicaldeprecated in favor of argumentna.lastfor consistency withbase::sort().- honorFactor
logical, default TRUE, used to enforce factor level sort order, when FALSE it sorts ascharacter.- xclass
charactervector of classes inx, used for slight optimization to re-use this vector if it has already been defined forx. WhenNULLit is created within this function.- indent
numericused only whenverbose=TRUEto determine the number of spaces indented for verbose output, passed toprintDebug().- debug
logical, default FALSE, whether to print detailed debug output.- ...
additional parameters are sent to
mixedOrder.
Value
list after applying mixedSort() to its elements.
Details
This function is an extension to mixedSort() to sort each vector
in a list. It applies the sort to the whole unlisted vector then
splits back into list form.
In the event the input is a nested list of lists, only the first
level of list structure is maintained in the output data. For
more information, see rlengths() which calculates the recursive
nested list sizes. An exception is when the data contained in x
represents multiple classes, see below.
When data in x represents multiple classes, for example character
and factor, the mechanism is slightly different and not as well-
optimized for large length x. The method uses
rapply(x, how="replace", mixedSort) which recursively, and iteratively,
calls mixedSort() on each vector, and therefore returns data in the
same nested list structure as provided in x.
When data in x represents only one class, data is unlist() to one
large vector, which is sorted with mixedSort(), then split back into
list structure representing x input.
See also
Other jam sort functions:
mixedOrder(),
mixedSort(),
mixedSortDF(),
mmixedOrder()
Other jam list functions:
cPaste(),
heads(),
jam_rapply(),
list2df(),
mergeAllXY(),
rbindList(),
relist_named(),
rlengths(),
sclass(),
sdim(),
uniques(),
unnestList()
Examples
# set up an example list of mixed alpha-numeric strings
set.seed(12);
x <- paste0(sample(letters, replace=TRUE, 52), rep(1:30, length.out=52));
x;
#> [1] "b1" "z2" "p3" "w4" "n5" "e6" "e7" "b8" "h9" "r10" "r11" "y12"
#> [13] "f13" "l14" "j15" "z16" "g17" "p18" "m19" "x20" "d21" "x22" "y23" "h24"
#> [25] "z25" "k26" "n27" "g28" "l29" "e30" "y1" "b2" "g3" "n4" "g5" "z6"
#> [37] "t7" "t8" "s9" "t10" "d11" "m12" "m13" "p14" "e15" "w16" "p17" "o18"
#> [49] "v19" "g20" "m21" "t22"
# split into a list as an example
xL <- split(x, rep(letters[1:5], c(6,7,5,4,4)));
xL;
#> $a
#> [1] "b1" "z2" "p3" "w4" "n5" "e6" "n27" "g28" "l29" "e30" "y1" "b2"
#>
#> $b
#> [1] "e7" "b8" "h9" "r10" "r11" "y12" "f13" "g3" "n4" "g5" "z6" "t7"
#> [13] "t8" "s9"
#>
#> $c
#> [1] "l14" "j15" "z16" "g17" "p18" "t10" "d11" "m12" "m13" "p14"
#>
#> $d
#> [1] "m19" "x20" "d21" "x22" "e15" "w16" "p17" "o18"
#>
#> $e
#> [1] "y23" "h24" "z25" "k26" "v19" "g20" "m21" "t22"
#>
# now run mixedSorts(xL)
# Notice "e6" is sorted before "e30"
mixedSorts(xL)
#> $a
#> [1] "b1" "b2" "e6" "e30" "g28" "l29" "n5" "n27" "p3" "w4" "y1" "z2"
#>
#> $b
#> [1] "b8" "e7" "f13" "g3" "g5" "h9" "n4" "r10" "r11" "s9" "t7" "t8"
#> [13] "y12" "z6"
#>
#> $c
#> [1] "d11" "g17" "j15" "l14" "m12" "m13" "p14" "p18" "t10" "z16"
#>
#> $d
#> [1] "d21" "e15" "m19" "o18" "p17" "w16" "x20" "x22"
#>
#> $e
#> [1] "g20" "h24" "k26" "m21" "t22" "v19" "y23" "z25"
#>
# for fun, compare to lapply(xL, sort)
# Notice "e6" is sorted after "e30"
lapply(xL, sort)
#> $a
#> [1] "b1" "b2" "e30" "e6" "g28" "l29" "n27" "n5" "p3" "w4" "y1" "z2"
#>
#> $b
#> [1] "b8" "e7" "f13" "g3" "g5" "h9" "n4" "r10" "r11" "s9" "t7" "t8"
#> [13] "y12" "z6"
#>
#> $c
#> [1] "d11" "g17" "j15" "l14" "m12" "m13" "p14" "p18" "t10" "z16"
#>
#> $d
#> [1] "d21" "e15" "m19" "o18" "p17" "w16" "x20" "x22"
#>
#> $e
#> [1] "g20" "h24" "k26" "m21" "t22" "v19" "y23" "z25"
#>
# test super-long list
xL10k <- rep(xL, length.out=10000);
names(xL10k) <- as.character(seq_along(xL10k));
print(head(mixedSorts(xL10k), 10))
#> $`1`
#> [1] "b1" "b2" "e6" "e30" "g28" "l29" "n5" "n27" "p3" "w4" "y1" "z2"
#>
#> $`2`
#> [1] "b8" "e7" "f13" "g3" "g5" "h9" "n4" "r10" "r11" "s9" "t7" "t8"
#> [13] "y12" "z6"
#>
#> $`3`
#> [1] "d11" "g17" "j15" "l14" "m12" "m13" "p14" "p18" "t10" "z16"
#>
#> $`4`
#> [1] "d21" "e15" "m19" "o18" "p17" "w16" "x20" "x22"
#>
#> $`5`
#> [1] "g20" "h24" "k26" "m21" "t22" "v19" "y23" "z25"
#>
#> $`6`
#> [1] "b1" "b2" "e6" "e30" "g28" "l29" "n5" "n27" "p3" "w4" "y1" "z2"
#>
#> $`7`
#> [1] "b8" "e7" "f13" "g3" "g5" "h9" "n4" "r10" "r11" "s9" "t7" "t8"
#> [13] "y12" "z6"
#>
#> $`8`
#> [1] "d11" "g17" "j15" "l14" "m12" "m13" "p14" "p18" "t10" "z16"
#>
#> $`9`
#> [1] "d21" "e15" "m19" "o18" "p17" "w16" "x20" "x22"
#>
#> $`10`
#> [1] "g20" "h24" "k26" "m21" "t22" "v19" "y23" "z25"
#>
# Now make some list vectors into factors
xF <- xL;
xF$c <- factor(xL$c)
# for fun, reverse the levels
xF$c <- factor(xF$c,
levels=rev(levels(xF$c)))
xF
#> $a
#> [1] "b1" "z2" "p3" "w4" "n5" "e6" "n27" "g28" "l29" "e30" "y1" "b2"
#>
#> $b
#> [1] "e7" "b8" "h9" "r10" "r11" "y12" "f13" "g3" "n4" "g5" "z6" "t7"
#> [13] "t8" "s9"
#>
#> $c
#> [1] l14 j15 z16 g17 p18 t10 d11 m12 m13 p14
#> Levels: z16 t10 p18 p14 m13 m12 l14 j15 g17 d11
#>
#> $d
#> [1] "m19" "x20" "d21" "x22" "e15" "w16" "p17" "o18"
#>
#> $e
#> [1] "y23" "h24" "z25" "k26" "v19" "g20" "m21" "t22"
#>
mixedSorts(xF)
#> $a
#> [1] "b1" "b2" "e6" "e30" "g28" "l29" "n5" "n27" "p3" "w4" "y1" "z2"
#>
#> $b
#> [1] "b8" "e7" "f13" "g3" "g5" "h9" "n4" "r10" "r11" "s9" "t7" "t8"
#> [13] "y12" "z6"
#>
#> $c
#> [1] z16 t10 p18 p14 m13 m12 l14 j15 g17 d11
#> Levels: z16 t10 p18 p14 m13 m12 l14 j15 g17 d11
#>
#> $d
#> [1] "d21" "e15" "m19" "o18" "p17" "w16" "x20" "x22"
#>
#> $e
#> [1] "g20" "h24" "k26" "m21" "t22" "v19" "y23" "z25"
#>
# test super-long list
xF10k <- rep(xF, length.out=10000);
names(xF10k) <- as.character(seq_along(xF10k));
print(head(mixedSorts(xF10k), 10))
#> $`1`
#> [1] "b1" "b2" "e6" "e30" "g28" "l29" "n5" "n27" "p3" "w4" "y1" "z2"
#>
#> $`2`
#> [1] "b8" "e7" "f13" "g3" "g5" "h9" "n4" "r10" "r11" "s9" "t7" "t8"
#> [13] "y12" "z6"
#>
#> $`3`
#> [1] z16 t10 p18 p14 m13 m12 l14 j15 g17 d11
#> Levels: z16 t10 p18 p14 m13 m12 l14 j15 g17 d11
#>
#> $`4`
#> [1] "d21" "e15" "m19" "o18" "p17" "w16" "x20" "x22"
#>
#> $`5`
#> [1] "g20" "h24" "k26" "m21" "t22" "v19" "y23" "z25"
#>
#> $`6`
#> [1] "b1" "b2" "e6" "e30" "g28" "l29" "n5" "n27" "p3" "w4" "y1" "z2"
#>
#> $`7`
#> [1] "b8" "e7" "f13" "g3" "g5" "h9" "n4" "r10" "r11" "s9" "t7" "t8"
#> [13] "y12" "z6"
#>
#> $`8`
#> [1] z16 t10 p18 p14 m13 m12 l14 j15 g17 d11
#> Levels: z16 t10 p18 p14 m13 m12 l14 j15 g17 d11
#>
#> $`9`
#> [1] "d21" "e15" "m19" "o18" "p17" "w16" "x20" "x22"
#>
#> $`10`
#> [1] "g20" "h24" "k26" "m21" "t22" "v19" "y23" "z25"
#>
# Make a nested list
set.seed(1);
l1 <- list(
A=sample(nameVector(11:13, rev(letters[11:13]))),
B=list(
C=sample(nameVector(4:8, rev(LETTERS[4:8]))),
D=sample(nameVector(LETTERS[2:5], rev(LETTERS[2:5])))
)
)
l1;
#> $A
#> m l k
#> 11 12 13
#>
#> $B
#> $B$C
#> H G D F E
#> 4 5 8 6 7
#>
#> $B$D
#> D B E C
#> "C" "E" "B" "D"
#>
#>
# The output is a nested list with the same structure
mixedSorts(l1);
#> $A
#> m l k
#> 11 12 13
#>
#> $B
#> $B$C
#> H G F E D
#> 4 5 6 7 8
#>
#> $B$D
#> E D C B
#> "B" "C" "D" "E"
#>
#>
mixedSorts(l1, sortByName=TRUE);
#> $A
#> k l m
#> 13 12 11
#>
#> $B
#> $B$C
#> D E F G H
#> 8 7 6 5 4
#>
#> $B$D
#> B C D E
#> "E" "D" "C" "B"
#>
#>
# Make a nested list with two sub-lists
set.seed(1);
l2 <- list(
A=list(
E=sample(nameVector(11:13, rev(letters[11:13])))
),
B=list(
C=sample(nameVector(4:8, rev(LETTERS[4:8]))),
D=sample(nameVector(LETTERS[2:5], rev(LETTERS[2:5])))
)
)
l2;
#> $A
#> $A$E
#> m l k
#> 11 12 13
#>
#>
#> $B
#> $B$C
#> H G D F E
#> 4 5 8 6 7
#>
#> $B$D
#> D B E C
#> "C" "E" "B" "D"
#>
#>
# The output is a nested list with the same structure
mixedSorts(l2);
#> $A
#> $A$E
#> m l k
#> 11 12 13
#>
#>
#> $B
#> $B$C
#> H G F E D
#> 4 5 6 7 8
#>
#> $B$D
#> E D C B
#> "B" "C" "D" "E"
#>
#>
mixedSorts(l2, sortByName=TRUE);
#> $A
#> $A$E
#> k l m
#> 13 12 11
#>
#>
#> $B
#> $B$C
#> D E F G H
#> 8 7 6 5 4
#>
#> $B$D
#> B C D E
#> "E" "D" "C" "B"
#>
#>
# when one entry is missing
L0 <- list(A=3:1,
B=list(C=c(1:3,NA,0),
D=LETTERS[c(4,5,2)],
E=NULL));
L0
#> $A
#> [1] 3 2 1
#>
#> $B
#> $B$C
#> [1] 1 2 3 NA 0
#>
#> $B$D
#> [1] "D" "E" "B"
#>
#> $B$E
#> NULL
#>
#>
mixedSorts(L0)
#> $A
#> [1] 1 2 3
#>
#> $B
#> $B$C
#> [1] 0 1 2 3 NA
#>
#> $B$D
#> [1] "B" "D" "E"
#>
#> $B$E
#> NULL
#>
#>
mixedSorts(L0, na.rm=TRUE)
#> $A
#> [1] 1 2 3
#>
#> $B
#> $B$C
#> [1] 0 1 2 3 NA
#>
#> $B$D
#> [1] "B" "D" "E"
#>
#> $B$E
#> NULL
#>
#>