
https://docs.racket-lang.org/graphite-tutorial/ hello all. any feedback on this document is appreciated, especially on data wrangling 201
bonus points if you have no idea what this library/libraries is/are and haven’t read the docs at all

bonus bonus points if you care about data science

I’m not sure I can even express this so that it’s comprehensible, but I’ll try. :wink:
I have a list of lists of strings and want to sort the outer list so that the inner lists are sorted by some comparison function. For example, the list '("foo", "bar")
should be sorted before '("foo", "bar2")
because the first elements are identical and when comparing “bar” and “bar2” with string<?
, “bar” comes first.
Of course I could do this with sort
and an “appropriate” comparison function, but I wonder if there’s a higer-order helper function so that I can write something like (recursive-sort list-of-lists-of-strings string<?)
where string<?
would be the comparison function for the items of the inner lists.

I wrote those for some of my work. Let me find them

Interestingly enough, I was working on sorting by multiple columns for one of my packages, and wrote such a comparison function, to pass to sort. It allows you to combine basic less than functions to define a less-than order for lists of elements. Here is the entire function:
(define (make-sx-comparator less-than-functions na-values na-on-front?)
(lambda (a b)
;; The A and B keys we compare have the position as the first element, so
;; the comparison skips the first element of A and B.
(let loop ([a (cdr a)]
[b (cdr b)]
[less-than-functions less-than-functions]
[na-values na-values])
(if (or (null? a) (null? b))
#f
(let ([va (car a)]
[vb (car b)]
[less-than? (car less-than-functions)]
[na (car na-values)])
(cond ((equal? va na) na-on-front?)
((equal? vb na) (not na-on-front?))
((less-than? va vb) #t)
((less-than? vb va) #f)
(else (loop (cdr a) (cdr b)
(cdr less-than-functions)
(cdr na-values)))))))))

you would use it as:
(define my-cmp (list string< string<) '(#f #f))
(sort data #:cmp my-cmp)

Wow, thanks. I’ll have a look. Can I use this under the MIT license in my own code?

yes

@sschwarzer: couldn’t find it, but I also wrote it in this comment: https://github.com/racket/racket/pull/3076#issuecomment-609053520

you might need to modify it though, as my function assumes that there is an extra element in the front of the list, which does not participate in the comparison.

Thanks for the heads up.
By the way, I also want to sort table rows. :slightly_smiling_face:

I don’t want to sort table rows with it — that is too expensive…

(of course you can do that if it suits you)

Ok, so that was a misunderstanding because of “columns.”
I have only a few rows in a few tables, so speed shouldn’t be a problem.

I don’t know if I understand it :wink: but if I do, can I use this under the MIT license?

Yes, that would work. I have lots of rows and lots of columns, and I need to “sort” by 2 or 3 columns only, it is more efficient to just build an index and make the table appear to be sorted. It also allows me to have a single large table appear to be sorted by different criteria instead of keeping the same data in multiple tables in different order…

I just noticed that the name recursive-sort
in my example is misleading. I don’t want to sort recursively, only compare recursively (and sort the outer list).

Reported the bug, but attempts at a minimal reproduction failed. I can try to get Herbie failing this way again.

I think this is a good tutorial, and data manipulation and visualization is an area that would suit Racket well, so I like seeing that work done in this area.
One suggestion I would make, perhaps for the graphite library itself, is to use different defaults for the plots to make them look appealing to people who just use graph
with no options. One simple thing is to change the default line width to 1.5 or 2, but the default colors and fonts are not particularly nice either.
The best place to change these defaults would be the plot library itself, but unfortunately this would be a backwards incompatible change so it is not possible.

If all the lists are of length 2, you could use comaparator-chain
in Rebellion to do that (require rebellion/base/comparator)
(define string+string<=>
(comparator-chain
(comparator-map string<=> first)
(comparator-map string<=> second)))
(define (string+string<? ss1 ss2)
(compare-infix string+string<=> ss1 < ss2))
(sort string+string-list string+string<?)

If they’re of varying lengths, or you don’t know the length at compile time, it’s trickier. I could add a utility to rebellion for that though.

so the default plot-font-family
with Graphite is 'swiss
which renders as sans-serif on most machines, but not on the Racket docs server