hazel
2021-8-12 17:38:47

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


hazel
2021-8-12 17:42:43

bonus bonus points if you care about data science


sschwarzer
2021-8-12 22:25:40

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.


sorawee
2021-8-12 22:29:54

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


alexharsanyi
2021-8-12 22:30:01

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


alexharsanyi
2021-8-12 22:30:56

you would use it as:

(define my-cmp (list string< string<) '(#f #f)) (sort data #:cmp my-cmp)


sschwarzer
2021-8-12 22:31:12

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


alexharsanyi
2021-8-12 22:31:25

yes


sorawee
2021-8-12 22:31:55

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


alexharsanyi
2021-8-12 22:32:26

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.


sschwarzer
2021-8-12 22:33:16

Thanks for the heads up.

By the way, I also want to sort table rows. :slightly_smiling_face:


alexharsanyi
2021-8-12 22:34:20

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


alexharsanyi
2021-8-12 22:34:47

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


sschwarzer
2021-8-12 22:38:37

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.


sschwarzer
2021-8-12 22:40:27

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


alexharsanyi
2021-8-12 22:50:01

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…


sschwarzer
2021-8-12 23:11:07

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


pavpanchekha
2021-8-12 23:30:45

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


alexharsanyi
2021-8-13 00:20:51

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.


notjack
2021-8-13 02:02:56

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


notjack
2021-8-13 02:03:30

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.


hazel
2021-8-13 02:16:27

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