Re: [R] Sorting based a custom sorting function

2023-12-14 Thread Duncan Murdoch

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  on behalf of Martin Møller Skarbiniks 
Pedersen 
Date: Thursday, December 14, 2023 at 6:42 AM
To: R mailing list 
Subject: Re: [R] Sorting based a custom sorting function
On Thu, 14 Dec 2023 at 12:02, Duncan Murdoch  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@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@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.


__
R-help@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.


Re: [R] Sorting based a custom sorting function

2023-12-14 Thread Martin Morgan
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.

Have fun with the remainder of the advent!

Another Martin

From: R-help  on behalf of Martin Møller 
Skarbiniks Pedersen 
Date: Thursday, December 14, 2023 at 6:42 AM
To: R mailing list 
Subject: Re: [R] Sorting based a custom sorting function
On Thu, 14 Dec 2023 at 12:02, Duncan Murdoch  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@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@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.


[R] Suggestion for list - change reply-to

2023-12-14 Thread Martin Møller Skarbiniks Pedersen
Hi,

  I suggest that reply-to is changed to r-help@r-project.org and not
the original sender.

  The reason for my suggestion:
  I just made a mistake when replying to a message.
  I forgot to change the reply address from the sender to the r-help
and I think that happens quite often for others also.

  Any reason to keep it to the original sender?

Regards
Martin

__
R-help@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.


Re: [R] Sorting based a custom sorting function

2023-12-14 Thread Martin Møller Skarbiniks Pedersen
On Thu, 14 Dec 2023 at 12:02, Duncan Murdoch  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@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.


Re: [R] Sorting based a custom sorting function

2023-12-14 Thread Martin Møller Skarbiniks Pedersen
> This sounds suspiciously like homework (which is off-topic... see the Posting 
> Guide)

It is not homework.
Currently I am trying to solve this: https://adventofcode.com/2023/day/7

But it is something that has puzzled me for a long time.
In many programming languages, you can give a "less" function to the
sorting function.

The "less" function normally takes two arguments and tells which is
greater. The sorting function then uses that.
Eg. in perl:
@products = sort { $a->{price} <=> $b->{price} || $b->{discount} <=>
$a->{discount} } @products;

>  and you haven't indicated how you plan to encode your poker hands
> If this is not homework, then please show your work so far instead of showing 
> a completely different example.

I believe a MRE is better than a lot of code with many details that
are not related to the precise problem.
See https://stackoverflow.com/help/minimal-reproducible-example

My encoding of poker hands doesn't matter for the general problem of
providing a custom sorting function to any of the many
sorting functions in R.

> Most core features of other languages are possible in R so if you really 
> understand these other techniques and R then you should be able to do this 
> already.

I understand R quite well and implemented my own quicksort but I was
wondering for a better solution.

Here is my current solution.

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

Regards
Martin



Martin

__
R-help@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.


Re: [R] Sorting based a custom sorting function

2023-12-14 Thread Duncan Murdoch

On 14/12/2023 3:00 a.m., Martin Møller Skarbiniks Pedersen wrote:

Hi,

   I need to sort a data.frame based on a custom sorting function.
   It is easy in many languages but I can't find a way to do it in R.

   In many cases I could just use an ordered factor but my data.frame
contains poker hands and
I need to rank these hands. I already got a function that compares two hands.

Here is a MRE (Minimal, Reproducible Example):


df <- data.frame(person = c("Alice", "Bob", "Charlie"), value =
c("Medium", "Small", "Large"))

# 0 means equal, -1 means left before right, 1 means right before left
custom_sort <- function(left, right) {
   if (left == right) return(0)
   if (left == "Small") return(-1)
   if (left == "Medium" & right == "Large") return(-1)
   return(1)
}

#  sort df according to custom_soft
# expect output is a data.frame:
# name   size
# 1 Bob Medium
# 2   Alice  Small
# 3 Charlie  Large

In this simple case I can just use an ordered factor but what about
the poker hands situation?



The general way in base R is to put the objects in a vector (which might 
be a list if they are complex objects), assign a class to that vector, 
and define either an xtfrm method or methods for ==, >, is.na, and 
extraction for that vector.  The xtfrm method is basically
the same as using an ordered factor, so I'll skip that, and show you the 
other way:


For your example, you could do it like this:

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.


There are likely other ways to do this in particular packages such as 
dplyr or data.table.


Duncan Murdoch

__
R-help@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.


Re: [R] Sorting based a custom sorting function

2023-12-14 Thread Jeff Newmiller via R-help
This sounds suspiciously like homework (which is off-topic... see the Posting 
Guide), and you haven't indicated how you plan to encode your poker hands, and 
most core features of other languages are possible in R so if you really 
understand these other techniques and R then you should be able to do this 
already.

If this is not homework, then please show your work so far instead of showing a 
completely different example.

On December 14, 2023 12:00:12 AM PST, "Martin Møller Skarbiniks Pedersen" 
 wrote:
>Hi,
>
>  I need to sort a data.frame based on a custom sorting function.
>  It is easy in many languages but I can't find a way to do it in R.
>
>  In many cases I could just use an ordered factor but my data.frame
>contains poker hands and
>I need to rank these hands. I already got a function that compares two hands.
>
>Here is a MRE (Minimal, Reproducible Example):
>
>
>df <- data.frame(person = c("Alice", "Bob", "Charlie"), value =
>c("Medium", "Small", "Large"))
>
># 0 means equal, -1 means left before right, 1 means right before left
>custom_sort <- function(left, right) {
>  if (left == right) return(0)
>  if (left == "Small") return(-1)
>  if (left == "Medium" & right == "Large") return(-1)
>  return(1)
>}
>
>#  sort df according to custom_soft
># expect output is a data.frame:
># name   size
># 1 Bob Medium
># 2   Alice  Small
># 3 Charlie  Large
>
>In this simple case I can just use an ordered factor but what about
>the poker hands situation?
>
>Regards
>Martin
>
>__
>R-help@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.

-- 
Sent from my phone. Please excuse my brevity.

__
R-help@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.


[R] Sorting based a custom sorting function

2023-12-14 Thread Martin Møller Skarbiniks Pedersen
Hi,

  I need to sort a data.frame based on a custom sorting function.
  It is easy in many languages but I can't find a way to do it in R.

  In many cases I could just use an ordered factor but my data.frame
contains poker hands and
I need to rank these hands. I already got a function that compares two hands.

Here is a MRE (Minimal, Reproducible Example):


df <- data.frame(person = c("Alice", "Bob", "Charlie"), value =
c("Medium", "Small", "Large"))

# 0 means equal, -1 means left before right, 1 means right before left
custom_sort <- function(left, right) {
  if (left == right) return(0)
  if (left == "Small") return(-1)
  if (left == "Medium" & right == "Large") return(-1)
  return(1)
}

#  sort df according to custom_soft
# expect output is a data.frame:
# name   size
# 1 Bob Medium
# 2   Alice  Small
# 3 Charlie  Large

In this simple case I can just use an ordered factor but what about
the poker hands situation?

Regards
Martin

__
R-help@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.