[R] Sorting based a custom sorting function
Duncan Murdoch
murdoch@dunc@n @end|ng |rom gm@||@com
Thu Dec 14 20:30:27 CET 2023
On 14/12/2023 11:37 a.m., Martin Morgan wrote:
> In the spirit of 'advent of code', maybe it is better to exploit the features of the particular language you've chosen? Then the use of factors seems very relevant.
>
> value_levels <- c("Small", "Medium", "Large")
> df <- data.frame(
> person = c("Alice", "Bob", "Bob", "Charlie"),
> value = factor(
> c("Medium", "Large", "Small", "Large"),
> levels = value_levels
> )
> )
> df[with(df, order(person, value)),]
>
> Likely this is more efficient than the hints of your existing solution, because it will act on vectors rather than iterating through individual elements of the 'person' and 'value' vectors.
>
> For a more general solution, I don't think I'd follow the low-level approach Duncan suggests (maybe see also ?Math for S3 generics), but rather define a class (e.g., that requires vectors person and value) and implement a corresponding `xtfrm()` method.
I'd agree, in cases where it's feasible to implement one. But there are
cases where the pairwise comparison is obvious, while the numeric
conversion isn't.
A simple one would be a list of string vectors of different lengths,
where you want to sort lexicographically.
Duncan
>
> Have fun with the remainder of the advent!
>
> Another Martin
>
> From: R-help <r-help-bounces using r-project.org> on behalf of Martin Møller Skarbiniks Pedersen <traxplayer using gmail.com>
> Date: Thursday, December 14, 2023 at 6:42 AM
> To: R mailing list <r-help using r-project.org>
> Subject: Re: [R] Sorting based a custom sorting function
> On Thu, 14 Dec 2023 at 12:02, Duncan Murdoch <murdoch.duncan using gmail.com> wrote:
>>
>
>> class(df$value) <- "sizeclass"
>>
>> `>.sizeclass` <- function(left, right) custom_sort(unclass(left),
>> unclass(right)) == 1
>>
>> `==.sizeclass` <- function(left, right) custom_sort(unclass(left),
>> unclass(right)) == 0
>>
>> `[.sizeclass` <- function(x, i) structure(unclass(x)[i], class="sizeclass")
>>
>> df[order(df$value),]
>>
>> All the "unclass()" calls are needed to avoid infinite recursion. For a
>> more complex kind of object where you are extracting attributes to
>> compare, you probably wouldn't need so many of those.
>
> Great! Just what I need. I will create a class and overwrite > and ==.
> I didn't know that order() used these exact methods.
>
> My best solution was something like this:
>
> quicksort <- function(arr, compare_func) {
> if (length(arr) <= 1) {
> return(arr)
> } else {
> pivot <- arr[[1]]
> less <- arr[-1][compare_func(arr[-1], pivot) <= 0]
> greater <- arr[-1][compare_func(arr[-1], pivot) > 0]
> return(c(quicksort(less, compare_func), pivot, quicksort(greater,
> compare_func)))
> }
> }
>
> persons <- c("alfa", "bravo", "charlie", "delta", "echo", "foxtrot", "golf",
> "hotel", "india", "juliett", "kilo", "lima", "mike", "november",
> "oscar", "papa", "quebec", "romeo", "sierra", "tango", "uniform",
> "victor", "whiskey", "x-ray", "yankee", "zulu")
>
> quicksort(persons, function(left, right) {
> nchar(left) - nchar(right)
> })
>
> Regards
> Martin
>
> ______________________________________________
> R-help using r-project.org mailing list -- To UNSUBSCRIBE and more, see
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.
>
> [[alternative HTML version deleted]]
>
> ______________________________________________
> R-help using r-project.org mailing list -- To UNSUBSCRIBE and more, see
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.
More information about the R-help
mailing list