data-science

lspector 2026-01-17T02:57:44.898069Z

Can anyone point me to a Clojure-only way to make a basic scatter plot from pairs of x and y values that are in some (any) Clojure data structure? After not trying to do anything like this for several years I was just poking around scicloj and other things I can find through web searches and what I'm seeing seems to all involve JSON and/or things from other programming language ecosystems and/or to be oriented toward fancier visualizations. I'm looking for something that doesn't require me (or my students) to think about anything other than Clojure data, even if it means adding a dependency that might internally use a bunch of other stuff.

Harold 2026-01-17T04:24:32.213049Z

1
πŸ™ 1
Harold 2026-01-17T04:24:50.845399Z

@daslu / @timothypratley ^ relevant to your interests

❀️ 1
respatialized 2026-01-17T04:25:39.865309Z

https://github.com/generateme/cljplot <- JVM only, lower level, might require your students to do a little bit more in Clojure to generate the plot (which might be useful depending on the learning goals)

❀️ 1
Harold 2026-01-17T04:26:28.787119Z

@lspector - there is a lot to learn about tech.ml.dataset, plotly, clay, and various other things in noj... but in 2026, the tools are there.

❀️ 1
Harold 2026-01-17T04:28:20.437649Z

The data science channel on zulip is where the most helpful people in this area hang out, as well, if you're interested: https://clojurians.zulipchat.com/#narrow/channel/151924-data-science

❀️ 1
lspector 2026-01-17T05:02:10.205419Z

So helpful! Thanks everybody! I will look into all of these leads soon.

lspector 2026-01-25T20:47:22.276879Z

@timothypratley that is gorgeous!! β€οΈπŸ™πŸŽ‰ The inference part is a surprise and quite cool! I have a little worry that it may sometimes infer something different than what the user expects, but maybe that's unlikely and/or will be made obvious by the axis labels, etc. While I haven't yet played with it myself, from the video I think that it does indeed fit my need quite nicely, and I will plan to use it and share it with my students. THANKS!!

πŸ‘ 1
❀️ 1
πŸ˜„ 1
✨ 1
timothypratley 2026-01-25T21:53:54.376669Z

Great πŸ™‚ you're welcome. I agree at some point inference is not enough, though I am also curious how far students can get with it. At some point there's no avoiding reaching for something like Plotly or Vega or Tableplot. If that happens, the good news is that (g/plot) also renders kindly annotated specs, so at least it's possible if someone wants to go further πŸ˜„ and learn about those.

timothypratley 2026-01-25T21:55:28.269189Z

For example here's how to make a "kindly annotated" Vega spec: https://scicloj.github.io/clay/clay_book.examples.html#vega-and-vega-lite not recommending it, just pointing out the more complicated options.

lspector 2026-01-25T22:13:11.156259Z

Wonderful. FWIW I understand they'll have to learn more to do more, which is totally fine. Some of my students may want to do that, but others needn't. My concern about the inference wasn't that it wouldn't do enough, but rather that it might do something unexpected. Again, maybe that won't be a problem either, but just to clarify, that's what I meant.

πŸ‘ 1
timothypratley 2026-01-25T22:14:46.634829Z

got it, thanks for clarifying πŸ˜„

πŸ‘ 1
lspector 2026-01-18T23:13:18.580139Z

I'd love a little more hand-holding on this if anyone has the bandwidth. While the pure Clojure/java approach was good to see, I'm thinking that the Clay approach is better long term. I can make something like @hhausman's code above work in a way that I can communicate to students pretty concisely -- I'll give them the noj dependency to put in deps.edn, then three :require vectors to put in their ns form, and then something like the other parts of @hhausman's code. However, when trying to package this up in a function and workflow for students to follow, I have three issues. First, I don't see a way to write a plot function like this one (which I'd have students paste into their code) without the ugliness of a def within the function.

(defn plot
  [xy-map]
  (def dataset (ds/->dataset xy-map))
  (clay/make! {:single-form '(plotly/layer-point dataset)}))
This is because something's a macro? Is there a nicer way to do this? Second, I get this when I run any version of the things I tried:
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See  for further details.
Is this something I'm doing wrong, or something that should be ignored? Third, the plot appears in a browser window, which is well and good, and it updates if I leave that window open and re-evaluate my code (in Calva) with different data. But if I close the window, then I don't see how to get it back without restarting the REPL. Any pointers on any of this would be appreciated!

Daniel Slutsky 2026-01-18T23:22:52.496439Z

Thanks for looking into it. : ) Clay is mostly intended for interactive use through https://scicloj.github.io/clay/#setup -- the students may find https://scicloj.github.io/clay/#videoss helpful for that. We may also prepare a focused short video for the recommended setup that your students will use.

Daniel Slutsky 2026-01-18T23:22:55.682759Z

If you do call clay/make! explicitly (which is not the common way it is used), you may also pass a value directly -- the following two are equivalent:

(clay/make! {:single-form '(+ 1 2)})
and
(clay/make! {:single-value 3})

Daniel Slutsky 2026-01-18T23:24:29.394479Z

If you wish to reopen the browser view again, you may call (clay/browse!) . Some of the editor/IDE bindings also have a command for that.

Daniel Slutsky 2026-01-18T23:28:19.809729Z

The logging warnings are indeed annoying and confusing. They can be removed by adding a logging backend as a dependency. E.g.

org.slf4j/slf4j-simple {:mvn/version "2.0.17"}

lspector 2026-01-18T23:31:16.233499Z

Thanks! Especially for the speedy and detailed reply! FWIW I'd rather avoid requiring new IDE bindings or any other setup or learning curve for this. Your suggestions look really helpful and I will try them soon --- but am just posting this quickly now since I think I have to go offline shortly for a bit.

Daniel Slutsky 2026-01-18T23:34:41.085819Z

Thanks. It'll be valuable for us to explore towards a good workflow that works for your students and learn from their feedback. Possibly, the live-reload approach (that is IDE-agnostic) can fit well. short demo: https://www.youtube.com/watch?v=tDz1x2d65C0 longer demo: https://www.youtube.com/watch?v=gHwFCOkBb_o

lspector 2026-01-18T23:38:56.684619Z

Still here πŸ™‚. Tried :single-value and that works nicely, allowing this:

(defn plot
  [xy-map]
  (clay/make! {:single-value (plotly/layer-point (ds/->dataset xy-map))}))
I will try the other things you mentioned soon! But I'm also curious: You say calling clay/make! explicitly is not the normal way; what is the normal way to do what I'm trying to do here? I ended up with that just because of the code I grabbed from above.

lspector 2026-01-18T23:45:13.407989Z

Oh nice -- I can add (clay/browse!) to the end of my plot function and it always re-opens when needed, without creating duplicates if the old one was left open.

πŸ’‘ 1
Daniel Slutsky 2026-01-18T23:47:33.789419Z

Oh, I just meant most people would call make! through editor bindings. This allows us to write user code that does not even mention Clay, so Clay is just a tool to visualize values , like the REPL.

Harold 2026-01-19T00:41:29.522489Z

@lspector - glad you're persevering. clay/make! makes (no pun intended) for the nice screenshot I posted above, which was evidently sufficiently enticing. But in real life I never write clay/make!, I have bound various keys in emacs that do clay/make!-ish things to whatever is under my cursor. This workflow is a bit less 'simple' and a bit more 'opaque' (perhaps), but it's probably mandatory for actual day to day use. Depending on what editor each user is using, there will be a different good way to set it up. You're lucky to have @daslu’s help.

πŸ‘ 1
lspector 2026-01-19T03:06:36.867079Z

Ah, I see. Thanks @daslu and @hhausman! FYI part of my context is a course I teach in which it's already a stretch to teach Clojure at all, and I don't want to require any more setup or learning curve than necessary. Any time students aren't spending on learning core Clojure concepts and functions I'd like to be directed to the course's actual focus, which is evolutionary computation, and using Clojure to write and experiment with evolutionary algorithms. I can see that other choices might make sense in a course focused on Clojure, functional programming, software development, data science, etc. While my students can use whatever tools they want, I don't want to require them to learn more than the Clojure language itself (and basics of Clojure idioms and style) to engage with the core content of the course. This means I don't want to require learning new ways to edit (no emacs, no paredit) or deal with peculiarities of an IDE aside from the basics of formatting and evaluating code. Perhaps not unrelatedly, I don't myself want any more setup or IDE learning curve for myself for my own research programming, even though I've been writing Lisp since the mid-80s and Clojure since 2010. Maybe I'm just a freak 🀷. But regardless, I'm pretty confident that the amount of tooling/language overhead for this course is already maxed out, without requiring learning new key bindings or anything like that. That's why I was looking for a way that a student who is just working on code in a single Clojure file (yes, you can write interesting evolutionary algorithms in a single short file!), can add a bit of code to get a basic plot of some numerical data, with no setup or learning curve for an IDE or other tools. I think you've provided it πŸ˜„ ! But maybe now you also understand a bit more about why I wanted it.

❀️ 1
lspector 2026-01-19T03:13:33.803529Z

BTW also I should make it clear that it's fabulous that there are now tools that a student in my class who wants to dive into more serious data analysis and visualization can use from Clojure!!! And I can understand that the student who wants to do that may have to learn more about various tools and how to use them. But that's not something that I will require of all students, many of whom will be focusing on other aspects of evolutionary algorithms, which they'll be able to explore with pure Clojure. When such a student wants a quick look at the shape of a data set, or the way error decreases over generations, etc., I wanted to give them a simple plot function they could use to look at it, without learning a lot of new stuff or exporting to some separate graphing software, etc.

Daniel Slutsky 2026-01-19T08:08:36.380769Z

It is fantastic that you keep creating these opportunities to learn Clojure. I think many of us have been using your teaching materials from the past, such as https://github.com/lspector/clojinc. Probably the main question is whether and how the students get some kind of REPL workflow connected to their editor, so they can edit code with a friendly feedback loop. As far as I understand, you used to teach using Gorilla REPL, which provided easy data visualizations, a sort of a REPL, and a nice UI. While Gorilla is unmaintained, there are similar options now such as Jupyter notebooks, which are now reasonably compatible with our plotting libraries, etc. Jupyter is probably familiar to students. Clay's live reload experience (demonstrated in the videos above) is another form of visual feedback loop. I am also guessing that many students nowadays are familiar with VSCode, which has good Clay support (visualizing inside the editor) without much setup. Arguably, to a person who knows VSCode, it doesn't feel like more to learn -- just another command from the command palette to visualize something. I understand that you cannot take much of their attention to any of that, so I am just laying the options here in case there is an opportunity to teach more.

Daniel Slutsky 2026-01-19T08:08:43.380819Z

If you happen to run into students who are curious to learn more and use Clojure for a project, we'll be glad to help them, maybe organize a meetup/workshop, or prepare more tailored materials.

πŸ†’ 1
lspector 2026-01-19T16:18:14.289109Z

Thanks @daslu! Indeed I've bounced among a bunch of setups over the years including Gorilla REPL, Clooj, Counterclockwise, Nightcode, Cursive, and Calva, always looking for the approach with the best combination of easy startup, low incidental complexity, a few critical features like bracket matching and auto re-indenting, and freedom from unwanted features like forced paredit or parinfer. Lately the sweet spot has indeed been VSCode/Calva, in part because @pez has been so helpful in filling gaps for my use case, especially recently by adding a straightforward way to create minimal projects which was otherwise a bigger speed bump than most people could imagine. I use Jupyter in another course (a Python-based machine learning course) and both that and Clay within VSCode sound like exciting options that I will check out more later today! Thanks for those suggestions!!! The question will be, as described above, whether I will be able to get them to work, and show students how to use them, with virtually no additional setup or learning curve.

lspector 2026-01-19T17:00:39.189509Z

Just watched the live-reload noj in a jar videos (I couldn't watch videos yesterday because I was traveling) and that project is a thing of beauty! For that to be our primary platform, however, we'd have to pair it with the right editor (where right for me means "trivial installation/setup, includes bracket matching and auto-reindenting, and doesn't force parinfer or paredit or otherwise get in the way of normal text editing"), and I'm not sure what that would be unless it's something like Calva that's already providing a REPL etc. I will continue to check out the other options.

lspector 2026-01-19T17:21:50.395649Z

Just also now watched the Calva integration video. Also very nice! FWIW though I'm thinking at the moment that for my use case the sweet spot is to mostly just use Calva's built-in REPL, looking at outputs in the Calva terminal, and use Clay just for rendering plots to a browser window using a function like the one I sketched above. I think that should work quite nicely, with little incidental complexity or learning curve beyond what's required for working with Calva. But I will continue to mull this as I make the final preparations for my next instance of the course, which starts next week πŸ™‚. Just in case you're curious, the very explicit, from-scratch, no-prerequisites instructions that I give my students for getting started with Clojure and Calva are at https://discourse.pushlanguage.org/t/clojure-quickstart-instructions/2169. I may add something for basic plotting with Clay!

πŸ“ˆ 1
πŸ‘€ 2
❀️ 1
timothypratley 2026-01-19T22:34:40.249309Z

Hi, I think your Clojure quickstart instructions are excellent and appropriate. I like Noj and Clay very much, and I think that creating your own plot function as you did is a really smart way to wrap the main value of Noj into something your students can access more readily without getting distracted by the details. Regarding the SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder" message(s): to avoid them you can add a dependency org.slf4j/slf4j-simple {:mvn/version "1.7.36"} or slf4j-nop to your project.

timothypratley 2026-01-19T22:37:43.361819Z

FWIW I think this idea of "just plot" should become part of Noj itself in the near future as it solves an important use-case. i.e. It would be great to add your helper function as a namespace in Noj itself as a more convenient entry point, if @daslu agrees we could possibly add it sometime this week?

Daniel Slutsky 2026-01-19T22:42:36.007279Z

Sounds great

timothypratley 2026-01-19T22:47:52.899719Z

Also just mentioning that given the current quickstart instructions to install "Calva", installing "Calva Powertools" as well is all you need to get the Clay commands to appear in the command palette (obviously not necessary for the initial use case of "just plot", but if you did want to do other interesting things with Clay later then the commands would be there).

timothypratley 2026-01-19T22:50:24.300049Z

What's a good namespace for "just plot"? Would it be scicloj.noj.plot ? Maybe something else?

Daniel Slutsky 2026-01-19T22:52:15.125949Z

(Also, when using an example project like https://github.com/scicloj/noj-v2-getting-started/, it is possible to include https://github.com/scicloj/noj-v2-getting-started/blob/main/.vscode/settings.json and https://github.com/scicloj/noj-v2-getting-started/blob/main/.vscode/extensions.json to install, so vscode will have decent easy defaults and will also automatically suggest to install Calva Powertools.)

Daniel Slutsky 2026-01-19T22:53:53.840079Z

> What's a good namespace for "just plot"? I think this should be discussed at the Zulip chat, so the relevant people can respond.

πŸ‘ 1
2026-01-17T11:54:18.710379Z

and this if you want to avoid plotly, vega et al https://clojurecivitas.github.io/data_visualization/splom_tutorial.html (tho cljplot is good for this too)

❀️ 1
Daniel Slutsky 2026-01-17T14:17:08.730519Z

Hello @lspector! Just linking to Clay and Tableplot that Harold mentioned above. These are relevant in case you wish to visualize to the browser in a notebook environment: https://scicloj.github.io/clay/ -- the namespace-as-anotebook tool https://scicloj.github.io/tableplot/ -- a plotting library (somewhat inspired by ggplot2's layered grammar of graphics) These days, a few of us meet weekly at the https://scicloj.github.io/docs/community/groups/real-world-data/ to discuss the state of data libraries and related projects and experiments. Plotting has been a frequent topic there, as we are exploring new APIs to improve Tableplot. Maybe one day you'll like to join us on those meetings or others -- it'd be amazing to have your perspective there.

❀️ 1
Ben Kamphaus 2026-01-17T14:52:04.784739Z

pure clojure/java starting point for reference: https://gist.github.com/benkamphaus/42acc930af9197b6e68bd5fb7f357000 obviously when you add all the conveniences of proper plotting libs that kind of approach would get unwieldy, but re: the instruction: β€œmake a basic scatter plot from pairs of x and y values that are in some (any) Clojure data structure” β€” I think it’s worth knowing how little it takes to get started with plotting or any simple graphics w/the core of clojure & the java class lib stuff you get for free w/the jvm.

❀️ 1
Ben Kamphaus 2026-01-17T15:06:08.322909Z

I also want to say for β€˜real work’ or what have you, I’m using Clay and it and kind/kindly’s wrapping of plotly & other libs pretty intensely. That includes REPL/literate hybrid programming and writing up markdown in comments, etc. Or things like the single form example like @hhausman shows β€” I’ll put that in a rich comment block (w/the clay, etc. specific requires) when dev-ing up something at the REPL for backend or data flow or whatever if I need a quick plot or other visualization to make sense of things.

❀️ 1
Daniel Slutsky 2026-01-21T19:31:54.594599Z

Since this is not visible here, I'm just updating that this conversation has initiated great development discussions at the Zulip chat (where the relevant people are present). https://clojurians.zulipchat.com/#narrow/channel/422115-clay-dev/topic/clay.20for.20students/ https://clojurians.zulipchat.com/#narrow/channel/321125-noj-dev/topic/Proposal.3A.20add.20a.20just.20plot.20namespace/

timothypratley 2026-01-24T08:18:47.386179Z

Here is the proposed new library for "just plot" called Glance Docs: https://scicloj.github.io/glance/ Github: https://github.com/scicloj/glance I plan to push an alpha jar to Clojars tomorrow.

πŸ‘€ 1
✨ 2
timothypratley 2026-01-25T00:45:43.503289Z

org.scicloj/glance {:mvn/version "0.1.0-alpha2"} is up πŸ˜„

timothypratley 2026-01-25T05:41:12.328589Z

@lspector here's a 3 min video showing Glance, is this what you had in mind?

❀️ 1
πŸ’œ 1
timothypratley 2026-01-25T05:41:16.571349Z

https://www.youtube.com/watch?v=M807DeA1hyA