Jekyll2020-09-16T12:17:48+00:00http://blog.elle-est-au-nord.com//feed.xmlTech notesOn coding projects and other fun learning experiences!Éléonoreon teaching coding2019-03-02T00:00:00+00:002019-03-02T00:00:00+00:00http://blog.elle-est-au-nord.com//workshop/2019/03/02/on-teaching-coding<h1 id="on-teaching-coding">On teaching coding</h1>
<p><em>And by teaching, I mean being an instructor for coding workshops</em></p>
<p><img src="http://blog.elle-est-au-nord.com//assets/workshops/intro.jpg" alt="intro-at-emms-tech-workshop" /> credit: EMMS Technology (Mariana Bocoi)</p>
<h2 id="my-python-workshop-experience">My Python workshop experience</h2>
<p>I’ve done quite a bit of teaching recently</p>
<p>Since September 2017 I’ve found myself involved in teaching much more than I had before. I had helped out, coached or organised tech workshops at meetups or conferences. But interestingly I had beforehand (while training as a researcher) decided I didn’t want to teach (and only focused on research).</p>
<p>Fast forward a few years, and I’m out of academia for good. I still don’t consider myself a “good teacher” (whatever that means), but when I first met with <a href="http://jplusplus.org/">J++</a> (my current employer) they offered me to freelance for them and start by helping to teach an introductory Python course for journalists. I jumped on the occasion! Since then I’ve helped teach three Python classes (and soon five classes) with J++ so far as a secondary instructor. I feel more comfortable in one-to-one interactions in the classroom rather than standing in front of the classroom.</p>
<p>I’ve also helped teach workshops with <a href="https://twitter.com/marianabocoi">Mariana Bocoi</a> (on Serverless, Git, at Pink Programming, Hack for Sweden… - also Mariana is amazing!).
I recently taught an introductory Python workshop at <a href="https://www.emmstech.se/">EMMS Tech</a> and helped teach two introductory Python workshops with <a href="https://www.pinkprogramming.se/en/">Pink Programming</a> and Region Skåne (in case you don’t know it’s the South most region of Sweden where Malmö is).</p>
<h2 id="lessons-learned">Lessons learned</h2>
<p>I talked at <a href="http://www.pycon.se/">PyCon Sweden 2018</a> back in December about my experience at J++ including <strong>teaching Python to journalists</strong>. In this type of courses it’s really important to:</p>
<p>1) plan content suited to people’s needs (in our case the material is directly applicable to journalists because it was created by my colleagues who are journalists),</p>
<p>2) keep things as simple as possible,</p>
<p>3) adapt the content to people’s learning speed and ebergy level.</p>
<p>At EMMS Tech’s first event I ended up leading a <strong>beginners Python workshop</strong>. Aside from the stress and excitement of our first event aimed at women and girls of colour in Stockholm, I got to realise I could actually lead a coding workshop. It was indeed a short workshop and to make things easy I decided to:</p>
<p>4) use an interactive online <a href="https://www.learnpython.org/">tutorial</a> instead of starting with installing Python.</p>
<p><img src="http://blog.elle-est-au-nord.com//assets/workshops/emms-ws.jpg" alt="python-workshop-at-emms-tech" /> credit: EMMS Technology (Maryam Arai)</p>
<p>The <strong>two Python workshops for newcomer women</strong> were full-day events and a first for Pink Programming (no idea if we’ll do more in the future). Our job was for the immigrant women present to feel they could apply to an one-year coding free course called <a href="https://ideon.se/career/matchit/">MatchIT</a>. It is a really cool EU funded initiative to integrate newcomers to Sweden and provide workers to an industry lacking employees. As a secondary instructor I focused on <strong><em>hovering</em></strong>* over the class to make sure all participants were keeping up with the course and the new concepts “thrown at them”. As with the courses with J++ it was obvious that</p>
<p>5) classes of around 10 people where most are complete beginners benefit greatly from having a main instructor and two secondary instructors.</p>
<p>People learn at different speed and have different level when they come in. For that reason it is challenging to prevent some from falling behind when others are getting ahead. All I can think of to remedy that is</p>
<p>6) preparing resources for participants who are faster/already know a bit coming in.</p>
<p>But then it’s still hard to reply to questions of such a diverse group. I tend to focus on people that would be left behind because they need the support, while the ones ahead are usually more comfortable with getting answers using a search engine.</p>
<p><img src="http://blog.elle-est-au-nord.com//assets/workshops/pp-ws.jpg" alt="python-workshop-with-pp-malmo" /> credit: Pink Programming (Vanja Tufvesson)</p>
<p>* <strong><em>Hovering over people</em></strong> basically means going around the room and stopping behind people to see what they’re doing. It can potentially feel weird or creepy to participants. However I find it the best way to see how people are doing and help then understand a concept or an exercise even before they can formulate a question and hopefully also before they get too frustrated.</p>
<p>Note: I’m not judging, if people are doing emails or texting then I just go away and come back a few minutes later.</p>
<p>My non-scientific opinion is that the side effects of learning (to code) are excitement and frustration. And as you can see my beautiful plot below the key is to manage a person’s learning experience so they get as much excitement as possible, but step in before too much frustration comes in (“ideal limit” in yellow).</p>
<p><img src="http://blog.elle-est-au-nord.com//assets/workshops/learning-plot.jpg" alt="plot-of-learning-side-effect" /></p>
<h2 id="spread-the-code">Spread the code!</h2>
<p>Yes, everyone can code! Although not everyone can be a “good” developer, but that’s not the point here. Share this knowledge and see people have a blast learning something knew and getting exciting ideas for projects.
It’s not about using Machine Learning algorithms for everything, but automatisation of boring tasks, to decrease human errors and increase repeatability is a good start! Then there’s ultimately the potential of creating products and services that solve actual problems in different fields.</p>
<p>Several times now have people asked me with surprise (and even a touch of mockery) why teaching journalists to code. One day I’ll need to be better and get rid of this touch of mockery in my own voice as I answer them. But really how could one not see that the only way to maintain a semblance of democracy depend on journalists having all the tools possible to keep powerful people (wether in government or in corporations) in check. And for this they need to query, gather sometimes large amounts of data and analyse it in a reproducible way and visualise it for everyone to understand.</p>ÉléonoreOn teaching codingprint hello 20192019-01-14T00:00:00+00:002019-01-14T00:00:00+00:00http://blog.elle-est-au-nord.com//update/2019/01/14/print-hello-2019<h1 id="printhello-2019">print(“Hello, 2019”)</h1>
<p>I started this blog at the beginning of 2018 (see my first post, <a href="/update/2018/01/11/hello-world.html">here</a>).
Seeing as we’re at the beginning of 2019, it feels like a good time to reflect on the past year; my first year of blogging.</p>
<h2 id="1-raw-summary">1) Raw summary</h2>
<ul>
<li>Plan A: 2 posts/month</li>
<li>Plan B: 1 post/month</li>
<li>Reality: :-/</li>
</ul>
<p><img src="http://blog.elle-est-au-nord.com//assets/blog2018/visualization.svg" alt="plot-of-plan-vs-reality" />
[Vega-lite plot made using the <a href="https://vega.github.io/editor/">Vega editor</a>]</p>
<p><em>Note: I never measured, but it takes me at least half a day to write a blog post. This needs to be shorten down!</em></p>
<p>I wanted to blog more about conferences I attended (I even started to draft a post about MozFest), and to use it as an excuse to test coding libraries I’m curious about.</p>
<p>All in all, I’m glad I started a blog but I wish I could use it more and better in the future.</p>
<p>An idea was it could be useful to someone else. I feel this is not worth looking at until it has more content.</p>
<h2 id="2-plans-for-2019">2) Plans for 2019</h2>
<p>Looking ahead in 2019 I realised my excitement and priority lies in traveling and learning (sometimes combined).</p>
<p>A lot of my learning and traveling are tech related, so writing about those could be a good way to use my blog.</p>
<p>=> I will write more in 2019 than in 2018, but I will not overwhelm myself!</p>
<h2 id="3-upcoming-posts-look-at-me-being-optimistic">3) Upcoming posts (look at me being optimistic!)</h2>
<p>Based on my calendar this month, here are blog posts I should be able to write:</p>
<ul>
<li>What’s hand-drawing data viz?</li>
<li>How to use Python with geo data</li>
<li>Taking my front-end skills (CSS) to the next level!</li>
</ul>
<p>Note: I’ve drafted this post quickly on my phone (on a plane).
In the future I’ll try to draft a post quickly after an event or a learning experience. I’ll also keep track of the time spent so I get better at time management in the process.</p>Éléonoreprint(“Hello, 2019”)My OS upgrade adventures2018-08-28T00:00:00+00:002018-08-28T00:00:00+00:00http://blog.elle-est-au-nord.com//linux/2018/08/28/my-os-upgrade-adventures<h1 id="my-os-upgrade-adventures">My OS upgrade adventures</h1>
<p><em>** Aka my operating system (OS) upgrade postmortem **</em></p>
<p><strong>Note</strong>: This post is about Ubuntu OS, and could hopefully apply to other Linux distributions and other OS.</p>
<p><strong>Tl;dr</strong>: To upgrade from Ubuntu 14.04 to 18.04, back up your laptop (don’t forget your browser bookmarks) and go for a fresh install of Ubuntu 18.04.</p>
<p><strong>Before reading, have you updated your run your OS update manager recently?</strong></p>
<h2 id="funnystory-">“Funny”story 😬</h2>
<h3 id="once-upon-a-time">Once upon a time</h3>
<p>I remember a time not so long ago when I used to run <code class="language-plaintext highlighter-rouge">sudo apt-get update</code>* and <code class="language-plaintext highlighter-rouge">sudo apt-get upgrade</code>* each day after starting my laptop. Back then most packages were up to date at all time and all was for the best!</p>
<p>While daily updates might not be necessary, I was recently reminded how important an update manager is!</p>
<h3 id="not-so-long-ago">Not so long ago</h3>
<p>I am ashamed to say that I was still using Ubuntu 14.04 (Trusty Tahr) released in 2014.
<a href="https://wiki.ubuntu.com/Releases">Apparently</a> its end of life is set for April 2019, but several software didn’t have a latest update suited for this version already.</p>
<p>Anyway, I was and still am a satisfied Ubuntu user. So why not upgrade to the next stable version once the update manager told me to?</p>
<h3 id="what-happened-was">What happened was</h3>
<p>Well, when Ubuntu 16.04 (Xenial Xerus) came around in 2016 I heard it would have Python 3 by default while most of my Python projects use Python 2 (2.7) and I somehow thought updating would mess up too many things. While newer projects I usually did in Python 3 (3.4) in a virtualenv, I wanted to wait to upgrade Python 2.7 projects to Python 3… which I postponed and ultimately never did. And for the update manager to stop bugging me I unchecked the option to look for the latest stable version and I guess I did less and less updates as I feared new versions could break if their dependencies didn’t have a new version on Ubuntu 14.04.</p>
<p>Now I can see how counterproductive this behaviour was. But on a day to day basis things seemed to work okay at least for a (too long) while.</p>
<h2 id="the-push-">The push 🙂</h2>
<p>As mentioned earlier several softwares didn’t have a latest update available in the Ubuntu 14.04 package repository.</p>
<p>I can remember for example that the spell checker in Slack stopped working (and contacting support I learned this was specific to Ubuntu 14.04), I couldn’t install the latest Node.js (although I used <a href="https://github.com/tj/n">n</a> as a workaround), and there was a glitch when using pip3 to install Python packages while working with Python 3.6 in a virtualenv (Python 3.6 is not available for direct install in Ubuntu 14.04).
I guess those are memories soon to be forgotten, but mostly because I lost all my bookmarks of StackOverflow or Ask Ubuntu links.</p>
<p>The point is, it was starting to get too obvious that I should have upgraded Ubuntu. Also Ubuntu 16.04 was already “out” with the release of Ubuntu 18.04 (Bionic Beaver) in early 2018.</p>
<h2 id="horror-story-">“Horror story” 😱</h2>
<h3 id="its-a-plan">It’s a plan…</h3>
<p>So I finally found a moment to upgrade with minimum negative consequences on my work.
It was actually crucial for me to write down “Back up before upgrade” and “Ubuntu upgrade” as cards in my planning <a href="trello.com">Trello</a> board.
At this stage I had two choices: (1) a fresh Ubuntu 18.04 upgrade or (2) a progressive upgrade to Ubuntu 16.04 and then to 18.04. With solution (2) I’d keep all my softwares installed and files/folders. That’s the choice I made and thought I had actually wasted time with my backup! LoL</p>
<h3 id="-or-is-it">… Or is it?</h3>
<p>That’s with confidence I set out to upgrade up one version to 16.04 using the built-in <code class="language-plaintext highlighter-rouge">software-updater</code>. I started at midday thinking I could have lunch during the upgrade and go back to working (creating a one page app with React) after lunch. But how wrong was I!
It all want okay and a notification asked me to restart in order to finish the install. I clicked on “restart”, but after that there where more packages to install and something that looked like a Python error.</p>
<p>Well, then my laptop crashed. Not <a href="https://en.wikipedia.org/wiki/Blue_Screen_of_Death">BSOD</a>, but black screen and restart console mode. With an error message:
<code class="language-plaintext highlighter-rouge">ImportError: /usr/lib/x86_64-linux-gnu/libapt-pkg.so.5.0: symbol (...), version GLIBCXX_3.4.21 not defined in file libstdc++.so.6 with link time reference</code></p>
<h3 id="so-now-what">So now what?</h3>
<p>1) I realised I should have done the fresh Ubuntu 18.04 install, but I couldn’t do it then as “apt-get” didn’t even work to finish this install
2) I took a deep breath (to reproduce as many times as needed)
3) I used my phone to search for that error.</p>
<p>Luckily <a href="https://askubuntu.com/questions/777803/apt-relocation-error-version-glibcxx-3-4-21-not-defined-in-file-libstdc-so-6">others</a> have had this error before and I learned I needed to install a new version of <code class="language-plaintext highlighter-rouge">libstdc++.so.6</code> for Ubuntu 16.04. I spare you the time spend to try and connect to my wifi from the terminal (using <code class="language-plaintext highlighter-rouge">iwconfig</code> and <code class="language-plaintext highlighter-rouge">nmcli</code>) with no success.</p>
<h3 id="my-salvation">My salvation</h3>
<p>I headed to the nearest (opened) library to use another computer to dowload the packages needed and transfer them on an usb device.
One response from the Ask Ubuntu question linked above recommends to get two packages:</p>
<ul>
<li><code class="language-plaintext highlighter-rouge">libstdc++6_5.4.0-6ubuntu1~16.04.4_i386.deb</code></li>
<li><code class="language-plaintext highlighter-rouge">libstdc++6_5.4.0-6ubuntu1~16.04.4_amd64.deb</code></li>
</ul>
<p>I then mounted my usb device on my broken laptop, copied and <code class="language-plaintext highlighter-rouge">dpkg</code>-ed both packages.
After that the previous error message (with <code class="language-plaintext highlighter-rouge">libstdc++.so.6</code>) didn’t appear again, but I still couldn’t do a <code class="language-plaintext highlighter-rouge">sudo apt-get update</code>. I momentarily went back down the rabbit hole of trying to connect to the wifi and failing to do so.</p>
<p>I was saved by reading through the replies to the Ask Ubuntu link (once again). Someone said the packages needed have actually already been downloaded, but the previous error made Ubuntu crash while installing the packages and the solution is to use: <code class="language-plaintext highlighter-rouge">sudo apt-get install -f</code>.</p>
<h2 id="epilogue-">Epilogue 👩🏿💻</h2>
<p>After that I could restart normally. A window opened to signal more packages couldn’t be installed.
I wouldn’t have worried too much until I plugged my earphones and realised the sound didn’t work.</p>
<p>That’s when I had too much and went for the fresh Ubuntu 18.04 (yes, the one I should have done from the start!).</p>
<p>So now I have that new laptop feeling (Bionic Beaver, yay!).
I had back up my files and folders, but not the softwares installed. I’m okay with that as I can now pretend to start again clean! LoL
I forgot to back up my browser bookmarks, which you might want to do. I’ve actually realised I was keeping tons of bookmark I didn’t need.</p>
<hr />
<p>References:</p>
<ul>
<li>In the land of Ubuntu <code class="language-plaintext highlighter-rouge">sudo apt-get update</code> and <code class="language-plaintext highlighter-rouge">sudo apt-get upgrade</code> are the basic commands for updates from the command line</li>
<li>Ubuntu releases: <a href="https://wiki.ubuntu.com/Releases">wiki.ubuntu.com/Releases</a></li>
<li>Node.js versions manager: <a href="https://github.com/tj/n">https://github.com/tj/n</a></li>
<li>Ubuntu upgrade notes from <a href="https://help.ubuntu.com/community/UpgradeNotes">Ubuntu documentation</a></li>
<li>That <code class="language-plaintext highlighter-rouge">libstdc++.so.6</code> error on <a href="https://askubuntu.com/questions/777803/apt-relocation-error-version-glibcxx-3-4-21-not-defined-in-file-libstdc-so-6">Ask Ubuntu</a></li>
</ul>ÉléonoreMy OS upgrade adventuresExperimenting with zines (1)2018-07-24T00:00:00+00:002018-07-24T00:00:00+00:00http://blog.elle-est-au-nord.com//sketchnotes/zines/2018/07/24/experimenting-with-zines-1<h1 id="experimenting-with-zines-1">Experimenting with zines (1)</h1>
<p>It all started when I was trying to learn how to sketchnote (see previous <a href="/sketchnotes/zines/2018/05/31/visualising-a-data-viz-conference.html">post</a>).
<a href="https://twitter.com/malweene">Malwine</a> sent me a zine (“The Cycle”) and a mini-zine (“Little guide to sketchnoting”). Both were inspiring in different ways!</p>
<p>“The Cycle” made me realise how (health) information can easily be shared using this medium and the “Little guide to sketchnoting” (on top of being useful content) I found amazing the folding of an A4 sheet into a mini-zine.</p>
<p>This was all reinforced when I visited the “1, 2, 3 DATA” exhibition back in May (see same previous <a href="/sketchnotes/zines/2018/05/31/visualising-a-data-viz-conference.html">post</a>) and the bibliography section of the exhibition contained a really cool zine publication dedicated to data visualisation, <a href="https://marketcafemag.bigcartel.com/">Market Cafe Mag</a>!</p>
<p>In conclusion, I find the combination of data visualisation and the print medium makes so much sense and is something I want to get into :)</p>
<h2 id="folding-a-minizine">Folding a (mini)zine</h2>
<p>The first step was to learn how to fold a zine and I used this <a href="https://www.wikihow.com/Make-a-Zine">wiki</a>.</p>
<p>You only need a sheet of paper and a pair of scisors. Obviously the larger the sheet of paper, the larger the zine. I like mini-zines and only have A4 sheets available, so here’s what I went for:</p>
<p><img src="http://blog.elle-est-au-nord.com//assets/zine-1/template-zine.jpg" alt="template mini-zine" /></p>
<p>It’s different from other projects in the fact that the pages aren’t in order and you’ll need to fold it to see your progress and how it’s all coming together.</p>
<p><img src="http://blog.elle-est-au-nord.com//assets/zine-1/front-template.jpg" alt="front cover of template mini-zine" /></p>
<h2 id="designing-the-content">Designing the content</h2>
<p>I already had a simple idea for a first zine and that was sharing tips for visitors to Stockholm!
I moved to Stockholm, Sweden almost a year ago and since then friends and acquaintances ask me advices on what to do/see when coming to Stockholm for a few days.</p>
<p>I wasn’t sure how much information could fit in one zine page, but I made this plan which I ended up staying very close to during the execution phase:</p>
<p><img src="http://blog.elle-est-au-nord.com//assets/zine-1/zine-design.jpg" alt="notebook with zine design" /></p>
<p>I somehow thought a table of content to be useful, and I planned what data visualisation or illustration i wanted to have for which subject. Here I have a plot to represent the evolution of the population of Stockholm over time and show the city is growing. When mentioning places I thought maps where indispensable. So I added (hand drawn) maps; one for Sweden and two for Stockholm. Hand drawn maps are obviously approximative, but I think they’re informative enough in that case. The last bit is a more detailed design of the cover.</p>
<p>Once I knew what the content would be, it was time to actually create the zine!</p>
<h2 id="time-for-execution">Time for execution</h2>
<p>I wish one day I’ll be able to directly draw with markers, but this time I wrote and drew it all using a carbon pencil.</p>
<p>I got this:</p>
<p><img src="http://blog.elle-est-au-nord.com//assets/zine-1/carbon-zine.jpg" alt="zine drafted with carbon pencil" /></p>
<p>The good thing with carbon pencil is obviously the possibility to change and correct until you’re satisfied. I was unsure of wether I had added too much information, but I still decided to go forward with the markers step!</p>
<p>At this step I thought that I didn’t need colours because I was certainly going to copy it in black and white later. I planned to use a thin tip black marker and a grey coloured marker (that would look lighter even in black and white copies).</p>
<p>In the end I couldn’t resist adding a bit of colours (especially for the Swedish flag) and I also realised my thin tip marker didn’t have such a thin tip after all. So I used a fine tip (0.5 mm) blue marker from Muji and for black text I ended up buying two new fine tip markers (0.4 mm) by Stabilo.</p>
<p>Below is the final result.</p>
<p>The front cover:</p>
<p><img src="http://blog.elle-est-au-nord.com//assets/zine-1/finished-cover.jpg" alt="finished zine cover" /></p>
<p>The whole thing:</p>
<p><img src="http://blog.elle-est-au-nord.com//assets/zine-1/finished-zine.jpg" alt="whole finished zine" /></p>
<p>And my favourite bits :)</p>
<p>A scatter plot and maps:</p>
<p><img src="http://blog.elle-est-au-nord.com//assets/zine-1/zine-dataviz.jpg" alt="dataviz stockholm" /></p>
<p>Yummy pastries:</p>
<p><img src="http://blog.elle-est-au-nord.com//assets/zine-1/zine-fika.jpg" alt="fika stockholm" /></p>
<h2 id="my-take-away">My take away</h2>
<p>The whole process took me roughly two days to complete!
Depending on the level of details and quantity of information you wish to add, your zine could take you much less or way more time.</p>
<p>For a first try I’d advise to start with a less detailed zine, maybe limit yourself to one plot, one map and one illustration. Especially if you tend to be impatient, a perfectionist or an impatient perfectionist like me :-/ .</p>
<p>I haven’t had access to a working copy machine (yet) to see what it looks like in black and white. But so far I’m really pleased with how it turned out :D</p>
<p>Stay tuned for my attempt at a “digital” (as in not hand drawn) zine!</p>
<hr />
<h2 id="resources">Resources</h2>
<ul>
<li>Previous post mentioned in this post: <a href="/sketchnotes/zines/2018/05/31/visualising-a-data-viz-conference.html">Visualising a data viz conference</a></li>
<li>Market Cafe Mag: <a href="https://marketcafemag.bigcartel.com/">zine store</a> - <a href="https://twitter.com/marketcafemag">twitter</a> - <a href="https://www.instagram.com/marketcafemag/">instagram</a></li>
<li>zine folding: <a href="https://www.wikihow.com/Make-a-Zine">wikihow.com/Make-a-Zine</a></li>
</ul>ÉléonoreExperimenting with zines (1) It all started when I was trying to learn how to sketchnote (see previous post). Malwine sent me a zine (“The Cycle”) and a mini-zine (“Little guide to sketchnoting”). Both were inspiring in different ways!Viz Playground - basic data viz with D32018-07-02T00:00:00+00:002018-07-02T00:00:00+00:00http://blog.elle-est-au-nord.com//data%20visualisation/2018/07/02/basic-dataviz-with-d3<h1 id="viz-playground---basic-data-viz-with-d3">Viz Playground - basic data viz with D3</h1>
<h2 id="my-d3-therapy">My D3 “therapy”</h2>
<p>So, I’ve tried to write that blog post before but it ended up taking so long and I wasn’t satisfied with the content. I think it induced a frustration that is a reflection of my relationship with D3.</p>
<p>I’ve been into data visualisation for years, and D3 being the tool of choice for aesthetic and interactive web visualisations I wanted to add it to my skillset. In programming (as in a lot of fields) it’s rare to feel you mastered a skill, and can move on to the next. And I really feel like D3 is a work in progress, maybe more so because I’ve never had data visualisation as a central part of my job.
I don’t remember how my D3 journey started, but I think my first plots where created during hackathons and involved searching for examples online and reproducing them using datasets of interest. I then took a workshop by <a href="http://cambridgecoding.com/">Cambridge Coding Academy</a> which was really good for learning the basics. Since then I’ve used D3 with the help of other people’s online tutorials. I’ve also mostly tried out tools (Pandas, Bokeh, Seaborn, Leaflet, Folium, QGIS, Altair, Vega…) that can create nice visualisations easily as a way around D3’s steep learning curve.
As I’m now freelancing, I figured I could steer my work towards professional data visualisation, which means D3 is now a critical tool to master.
Here is real life picture of me going up D3 learning curve:</p>
<p><img src="http://blog.elle-est-au-nord.com//assets/d3_learning_curve.jpg" alt="Person cycling up a steep hill" /></p>
<p>Because I learned that being lazy is a good trait in a programmer and because I have tons of ideas for projects involving data visualisation that I can’t wait to work on, here’s my plan:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>1) Create templates for different D3 plots
2) Use templates in projects
</code></pre></div></div>
<p>Et voilà! Easy, just two steps… and I’m ready to take over the world! Mwahahaha! *evil hands rub*</p>
<h2 id="implementation">Implementation</h2>
<h3 id="idea">Idea</h3>
<p>Let’s focus on the first step of my plan for now!</p>
<p>I’m thinking of creating code samples as <a href="https://help.github.com/articles/about-gists/">gists</a>/<a href="https://bl.ocks.org/-/about">locks</a>[1] that will ultimately be gathered inside a code repository. They’d be named after the visualisation they enable and they’d be well documented so that others can use them, too.
Oh, and here I am dreaming of data visualisations:</p>
<p><img src="http://blog.elle-est-au-nord.com//assets/d3_dream_viz.jpg" alt="Person at a desk dreaming of plots and maps" /></p>
<h3 id="action-plan">Action plan</h3>
<p>For the sake of lazyness (and time efficiency) I’m not going to reinvent the wheel. (I think that’s also where I’ve had troubles before.)
Luckily <a href="https://www.meetup.com/Data-Visualization-Stockholm/members/56537022/">Patrick</a>, Data Visualization Stockholm co-organiser, mentioned <a href="http://blockbuilder.org/about">Block builder</a> which let’s you create a new Block or search other people’s Blocks and fork them as a gist and modify them.</p>
<h3 id="block-builder">Block builder</h3>
<p>Block builder is an amazing platform to work on a (data visualisation) project. You can edit your files and see the output update in a panel above or on the side of the data edition section.
Here’s a screenshot:
<img src="http://blog.elle-est-au-nord.com//assets/blockbuilder.png" alt="Block builder screenshot" /></p>
<p>You can <a href="http://blockbuilder.org/search">search</a> for other’s Blocks which I did. I searched for a “bar chart” done by “mbostock” because <a href="https://github.com/mbostock">Mike Bostock</a> is D3’s creator and I assume his code to follow the best practices. Here’s a <a href="http://blockbuilder.org/mbostock/3885304">link</a> to the Block I wished to reuse. On the Block builder platform, if/once you’re logged in to your Github account, you can just fork the project and a forked Block will be opened in a Block editor. Behind the scene (because you gave the app access to your Github account) it also creates a new gist, and each time you save the project in Block builder this gist is updated.</p>
<h3 id="my-bar-chart-template">My bar chart template</h3>
<p>There are very little changes to <a href="http://blockbuilder.org/Eleonore9/978e35ff4bbdf53de90c896e2afdc879">my block</a> compared to the original one. I just expect to work mostly from CSV files, so I created a test data CSV and use the D3 function <code class="language-plaintext highlighter-rouge">d3.csv</code> to load the data.
I’m reusing most of the code as I’m still creating rectangular bars.
I changed the colours, removed the “%” on the y axis in the html file and edited the Readme for it to be informative as to what I did, what’s the aim and how the template can be used.</p>
<p>Because I intend to use this project as a template I added a section at the top of the html file with variables which values might need to be updated when creating a new project:</p>
<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="c1">// *** EDIT TO CUSTOMISE ***</span>
<span class="kd">var</span> <span class="nx">dataFile</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">test-data.csv</span><span class="dl">"</span><span class="p">,</span>
<span class="nx">xName</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">year</span><span class="dl">"</span><span class="p">,</span> <span class="c1">// column name for x-axis in the csv</span>
<span class="nx">xAxisLabel</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">Years</span><span class="dl">"</span><span class="p">,</span>
<span class="nx">xLabelxPosition</span> <span class="o">=</span> <span class="mi">50</span><span class="p">,</span> <span class="nx">xLabelyPosition</span> <span class="o">=</span> <span class="mi">80</span><span class="p">,</span>
<span class="nx">yName</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">value</span><span class="dl">"</span><span class="p">,</span> <span class="c1">// column name for y-axis in the csv</span>
<span class="nx">yAxisLabel</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">Value</span><span class="dl">"</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">transformXdata</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">data</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">transformYdata</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="o">+</span><span class="nx">data</span><span class="p">;</span> <span class="c1">// '+' converts to numbers</span>
<span class="p">}</span>
<span class="c1">// **************************</span></code></pre></figure>
<p>So this is actually an improved template after a first test. In the section showed above, a new project would include a new CSV file, with different column names for the data to be visualised and different labels for the axes. The label for the x-axis can also easily be adjusted. Something more crucial to the visualisation is the potential need to transform the data that can be done with the two functions <code class="language-plaintext highlighter-rouge">transformXdata</code> and <code class="language-plaintext highlighter-rouge">transformYdata</code>.
In the case of the test data, the values have to be converted to numbers.</p>
<h3 id="testing-the-template">Testing the template</h3>
<p>The template is supposed to be as generic as possible and I plan to add to it as I go along. For now let’s see if I can reuse it with a simple dataset of temperatures.</p>
<p>You might neither know nor care, but May 2018 was the warmest May ever recorded in Sweden where I live. I looked up the temperatures for each day of May 2018 on this <a href="https://www.accuweather.com/en/se/stockholm/314929/may-weather/314929">website</a> [2].
I then created a bar chart of the maximal temperatures (in Celsius degrees) in Stockholm throughout May 2018.
<img src="http://blog.elle-est-au-nord.com//assets/d3_sthlm_weather.png" alt="Bar chart of maximal temperatures in Stockholm in May 2018" />
Not bad!</p>
<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="kd">var</span> <span class="nx">dataFile</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">stockholm_may_temp.csv</span><span class="dl">"</span><span class="p">,</span>
<span class="nx">xName</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">day</span><span class="dl">"</span><span class="p">,</span> <span class="c1">// column name for x-axis in the csv</span>
<span class="nx">xAxisLabel</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">Days of the month (May 2018)</span><span class="dl">"</span><span class="p">,</span>
<span class="nx">xLabelxPosition</span> <span class="o">=</span> <span class="mi">150</span><span class="p">,</span> <span class="nx">xLabelyPosition</span> <span class="o">=</span> <span class="mi">80</span><span class="p">,</span>
<span class="nx">yName</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">maximal</span><span class="dl">"</span><span class="p">,</span> <span class="c1">// column name for y-axis in the csv</span>
<span class="nx">yAxisLabel</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">Temperature (°C)</span><span class="dl">"</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">transformXdata</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">data</span><span class="p">.</span><span class="nx">substring</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">2</span><span class="p">);</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">transformYdata</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">data</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>
<p>I updated the info in the customise section including a transformation of the x-axis data (dates). The full dates had the x-axis all cluttered up so I only kept the day, which is enough to understand the chart.</p>
<h2 id="my-take-away">My take-away</h2>
<p>I’m so glad I made my first reusable D3 template! Yay! ^^</p>
<p>However I can already see that the more I add to the template, the harder it’ll be to keep it “generic”. I hope to make well-documented decisions when the time comes :)</p>
<hr />
<p><strong>Notes</strong></p>
<p>[1] Gists are an easy way to create and share files on Gihub and Bl.ocks are a cool project to visualise code from gists!
Note: Sorry, but I used <code class="language-plaintext highlighter-rouge">Block</code> throughout the post as it’s easier to type than <code class="language-plaintext highlighter-rouge">Bl.ock</code>.</p>
<p>data source: <a href="://www.accuweather.com/en/se/stockholm/314929/may-weather/314929">https://www.accuweather.com/en/se/stockholm/314929/may-weather/314929</a></p>
<p>[2] One data point seemed really high (40C) so I used the temperature from <a href="https://darksky.net/">Dark Sky</a> instead.</p>
<p><strong>Links</strong></p>
<ul>
<li>
<p>Basic bar chart template:
<a href="https://bl.ocks.org/Eleonore9/978e35ff4bbdf53de90c896e2afdc879">Block</a>, <a href="https://gist.github.com/Eleonore9/978e35ff4bbdf53de90c896e2afdc879">gist</a> and on <a href="http://blockbuilder.org/Eleonore9/978e35ff4bbdf53de90c896e2afdc879">Block builder</a></p>
</li>
<li>
<p>Local data visualisation meetup: <a href="https://www.meetup.com/Data-Visualization-Stockholm/">Data Visualization Stockholm</a></p>
</li>
</ul>ÉléonoreViz Playground - basic data viz with D3Visualising a data viz conference2018-05-31T00:00:00+00:002018-05-31T00:00:00+00:00http://blog.elle-est-au-nord.com//sketchnotes/zines/2018/05/31/visualising-a-data-viz-conference<h1 id="visualising-a-data-viz-conference">Visualising a data viz conference</h1>
<h2 id="on-openvisconf-and-sketchnoting">On OpenVisConf and sketchnoting</h2>
<p>I recently attended <a href="http://openvisconf.com/">OpenVisConf</a> (the conference for opensource data visualisation) in Paris. I was super excited as I had followed the conference from afar (it used to be in Boston) for a few years.</p>
<p><img src="http://blog.elle-est-au-nord.com//assets/logo-openvisconf.png" alt="The logo for the OpenVisConf 2018" /></p>
<p>Another thing I’m excited about since I discovered it a little while ago is <strong>sketchnoting</strong>.</p>
<p>Sketchnoting is the process of taking visual notes. And some people use it to communicate technical information. I’m particularly inspired by my friend and badass coder/artist/sketchnoter <a href="https://twitter.com/malweene">Malwine</a> who often sketchnotes tech conference talks and awesome Linux “sorceress” <a href="https://twitter.com/b0rk">Julia Evans</a> who sketchnotes to share technical topics she learns about.</p>
<p>Since I had a conference coming up, and one about a visual subject, I thought it would be a good time to try out sketchnoting.</p>
<h2 id="how-did-i-prepare-for-sketchnoting-at-a-conference">How did I prepare for Sketchnoting at a conference?</h2>
<p>I love data visualisations and maps and I’m a visual learner. I believe sharing information visually makes a lot of sense and that’s definitely part of my professional goals.</p>
<p>This is why I (attended this conference and) want to learn to sketchnote, but behind quite impatient I wanted to do it well (enough) on my first trial. This means I would have had to prepare, by watching a conference talk video and sketchnote at home. Indeed sketchnoting live (during a talk) means you need to be fast and improvise as you don’t know how much of the paper you’ll need and what part of the talk to highlight.</p>
<p>Unfortunately I wasn’t organised enough to rehearse before the conference. But I was lucky to get a sketchnoting guide zine from Malwine :)</p>
<p><img src="http://blog.elle-est-au-nord.com//assets/sketchnoting-guide-small.jpeg" alt="Picture of sketchnoting zines with emojis" /></p>
<p>I also had a motivating discussion with fellow Stockholm based developer friend <a href="https://twitter.com/MarianaBocoi">Mariana</a> who shared her experience of starting to sketchnote at EuroClojure 2017.</p>
<p>Basically I needed to accept I wasn’t going to do great at first, but I’d improve over time. And I shouldn’t worry too much right now about the medium and pens/pencils. I should just be careful about the disposition of info and try different fonts, shapes and colours to make the content more understandable and appealing.</p>
<h2 id="how-did-it-go">How did it go??</h2>
<p>So coming at the conference I tried to take it easy and just create a better versions of notes I would normally take. I used the notebook and pen from the conference swag bag. I stressed connections using arrows, and highlighted important things by uppercasing, underlining or drawing a shape around the words.</p>
<p>What happened was:</p>
<ul>
<li>I got disappointed and discouraged because it didn’t look like what I wanted to produce</li>
<li>It didn’t always felt right to be taking notes. Sometimes I just wanted to listen to the talks (the amazing “Disagreements” talk by Amanda Cox and Kevin Quealy was a good example of that)</li>
<li>I didn’t know how to represent talks filled with so many beautiful visual elements which added to the discouragement</li>
<li>I got tired</li>
</ul>
<p>How I solved my issues:</p>
<ul>
<li>I missed a talk to sit down, relax and try to improve on my notes, then sent a picture to Mariana who gave me useful and very encouraging feedback :)</li>
<li>I went back to the conference talks with less pressure and took notes when it felt right to do so</li>
<li>I sat at home after the conference and added colours and drawings to make my notes more visual and tweeted the outcome</li>
</ul>
<p>Here are my fave ones from what I did for OpenVisConf:</p>
<p><img src="http://blog.elle-est-au-nord.com//assets/first-sketchnotes.jpeg" alt="Picture of three sketchnotes for talks at OpenVisConf" /></p>
<p>Adding small drawings was a good compromise (especially because the need to represent the visual aspects of the talk accurately faded with time).
And I got positive feedback :)</p>
<h2 id="how-would-i-do-it-better-next-time">How would I do it better next time?</h2>
<h3 id="tools">Tools</h3>
<p>I resisted the temptation to buy more pens and I’ll make do with what I have (regular blue or black writing pen and Crayola <a href="http://shop.crayola.com/color-and-draw/markers/washable-super-tips-markers-10-count-5886100015.html">colouring pens</a> I had bought for lettering).</p>
<h3 id="preparation">Preparation</h3>
<p>I’d like to think I’ll prepare myself by reading the abstracts of the talks beforehand and preparing the names of speakers and talk titles in a notebook.</p>
<p>Unfortunately I doubt this will happen :-/</p>
<h3 id="advice">Advice</h3>
<p>I’m such a sketchnoting noob, but the advice I’d give someone interested is to experiment with different styles and tools to produce something you like best. I know I will experiment more from now on!</p>
<p>More importantly take it easy, you don’t have to sketchnote all the talks but you have to have fun and enjoy the conference :)</p>
<h2 id="conclusion">Conclusion</h2>
<p>Sketchnoting is awesome! You can share your creations by posting pictures on social media and even create zines that you can print and share!! Come on, I can’t be the only one excited about zines!</p>
<p>Also at the <a href="https://123data.paris/collection">“1, 2, 3 DATA” exhibition</a> that presents all types of data visualisation projects I discovered a data visualisation zine called <a href="https://twitter.com/marketcafemag">Market Cafe Mag</a></p>
<hr />
<h2 id="resources">Resources</h2>
<h3 id="some-cool-sketchnoters">Some cool sketchnoters</h3>
<ul>
<li>
<p>Fellow <code class="language-plaintext highlighter-rouge">#sketchnotes</code> and <a href="https://twitter.com/sketchnoteclub">@sketchnoteclub</a> on Twitter</p>
</li>
<li>Malwine is on Twitter at <a href="https://twitter.com/malweene">@malweene</a> and you can see examples of her sketchnotes on her <a href="http://malweene.com/sketchnotes/">website</a>
-> share her <a href="https://docs.google.com/forms/d/e/1FAIpQLSfSDaLRrsGB8Dok3_16lGBV8ISJWe1ViwdxXhgJnDaeCpbxfg/viewform">call for conferences</a> with conference organisers</li>
<li>Julia Evans is on Twitter at <a href="https://twitter.com/b0rk">@b0rk</a> and she makes zines you can find (and order!) on her <a href="https://jvns.ca/zines/">website</a>.</li>
<li>Amy is also a great example of a coder gifted with artsy skills and who uses them to explain technical concepts. She’s on Twitter at <a href="https://twitter.com/sailorhg">@sailorhg</a> and her pretty zines and merchs are on the <a href="https://shop.bubblesort.io/collections/all">BubbleSort website</a>.</li>
</ul>
<h3 id="data-viz-inspiration">Data viz inspiration</h3>
<ul>
<li>OpenVisConf was super inspiring to me! <a href="https://www.youtube.com/watch?v=fp-WNqaQG0s&list=PL0t7o-LDSDFbNzmv7ULnuksJ3h1LZI18j">Here</a> is a link to the talks videos on YouTube :)</li>
<li>The opening keynote at OpenVisConf 2018 was made by <a href="https://twitter.com/moritz_stefaner">Moritz Stefaner</a> who presented a project part of the “1, 2, 3 DATA” exhibition in Paris. I went to see it and was very inspired as well!
You can look at the collection of awesome data viz projects <a href="https://123data.paris/collection">here</a></li>
</ul>ÉléonoreVisualising a data viz conferenceCombining functions with Clojure (2)2018-05-02T00:00:00+00:002018-05-02T00:00:00+00:00http://blog.elle-est-au-nord.com//programming%20languages/2018/05/02/combining-functions-with-clojure-2<h1 id="combining-functions-with-clojure-2">Combining functions with Clojure (2)</h1>
<p>My first technical post was named <a href="/programming%20languages/2018/01/17/combining-functions-with-clojure-1.html">Combining functions with Clojure (1)</a> which calls for a part two :)</p>
<p>I actually forgot what my initial plan was, because I took so long to draft the part two :-/</p>
<p>In the part one I used Clojure built-in functions <em>juxt</em> and <em>comp</em> to perform several steps of transformation on a data collection.</p>
<p>The data collection is very simple: <code class="language-plaintext highlighter-rouge">[:value :location :unit]</code>, and the aim is for it to undergo two steps of transformation (using the built-in functions <em>name</em> and <em>clojure.string/capitalize</em>) to get the following collection: <code class="language-plaintext highlighter-rouge">["Value" "Location" "Unit"]</code>.</p>
<p>This time I’m using Clojure built-in function <a href="https://clojuredocs.org/clojure.core/partial"><em>partial</em></a>.</p>
<h2 id="meet-partial">Meet <em>partial</em></h2>
<p>Here’s what’s the doc says:</p>
<blockquote>
<p>Takes a function f and fewer than the normal arguments to f, and
returns a fn that takes a variable number of additional args. When
called, the returned function calls f with args + additional args.</p>
</blockquote>
<p>Afaik <em>partial</em> is a <a href="https://en.wikipedia.org/wiki/Higher-order_function">higher-order function</a> as it takes in a function and returns a function. It’s quite cool and also useful!</p>
<p>In case you’re curious, it’s defined using nested <a href="http://clojure-doc.org/articles/language/functions.html#multi-arity-functions">multi-arity</a>.</p>
<p>As you can see below, <em>partial</em> always expects a function as an argument. The multi-arity enables it to accept as many arguments as the user wants, but always with a function as its first argument.
Then it returns a function, and multi-arity enables this new function to be called with the arguments given when defining the “partial function” and the arguments given when calling this new function.</p>
<figure class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="k">defn</span><span class="w"> </span><span class="nb">partial</span><span class="w">
</span><span class="p">([</span><span class="n">f</span><span class="p">]</span><span class="w"> </span><span class="n">f</span><span class="p">)</span><span class="w">
</span><span class="p">([</span><span class="n">f</span><span class="w"> </span><span class="n">arg1</span><span class="p">]</span><span class="w">
</span><span class="p">(</span><span class="k">fn</span><span class="w">
</span><span class="p">([]</span><span class="w"> </span><span class="p">(</span><span class="nf">f</span><span class="w"> </span><span class="n">arg1</span><span class="p">))</span><span class="w">
</span><span class="p">([</span><span class="n">x</span><span class="p">]</span><span class="w"> </span><span class="p">(</span><span class="nf">f</span><span class="w"> </span><span class="n">arg1</span><span class="w"> </span><span class="n">x</span><span class="p">))</span><span class="w">
</span><span class="p">([</span><span class="n">x</span><span class="w"> </span><span class="n">y</span><span class="p">]</span><span class="w"> </span><span class="p">(</span><span class="nf">f</span><span class="w"> </span><span class="n">arg1</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="n">y</span><span class="p">))</span><span class="w">
</span><span class="p">([</span><span class="n">x</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="n">z</span><span class="p">]</span><span class="w"> </span><span class="p">(</span><span class="nf">f</span><span class="w"> </span><span class="n">arg1</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="n">z</span><span class="p">))</span><span class="w">
</span><span class="p">([</span><span class="n">x</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="n">z</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="n">args</span><span class="p">]</span><span class="w"> </span><span class="p">(</span><span class="nb">apply</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="n">arg1</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="n">z</span><span class="w"> </span><span class="n">args</span><span class="p">))))</span><span class="w">
</span><span class="p">([</span><span class="n">f</span><span class="w"> </span><span class="n">arg1</span><span class="w"> </span><span class="n">arg2</span><span class="p">]</span><span class="w">
</span><span class="p">(</span><span class="k">fn</span><span class="w">
</span><span class="p">([]</span><span class="w"> </span><span class="p">(</span><span class="nf">f</span><span class="w"> </span><span class="n">arg1</span><span class="w"> </span><span class="n">arg2</span><span class="p">))</span><span class="w">
</span><span class="p">([</span><span class="n">x</span><span class="p">]</span><span class="w"> </span><span class="p">(</span><span class="nf">f</span><span class="w"> </span><span class="n">arg1</span><span class="w"> </span><span class="n">arg2</span><span class="w"> </span><span class="n">x</span><span class="p">))</span><span class="w">
</span><span class="p">([</span><span class="n">x</span><span class="w"> </span><span class="n">y</span><span class="p">]</span><span class="w"> </span><span class="p">(</span><span class="nf">f</span><span class="w"> </span><span class="n">arg1</span><span class="w"> </span><span class="n">arg2</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="n">y</span><span class="p">))</span><span class="w">
</span><span class="p">([</span><span class="n">x</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="n">z</span><span class="p">]</span><span class="w"> </span><span class="p">(</span><span class="nf">f</span><span class="w"> </span><span class="n">arg1</span><span class="w"> </span><span class="n">arg2</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="n">z</span><span class="p">))</span><span class="w">
</span><span class="p">([</span><span class="n">x</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="n">z</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="n">args</span><span class="p">]</span><span class="w"> </span><span class="p">(</span><span class="nb">apply</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="n">arg1</span><span class="w"> </span><span class="n">arg2</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="n">z</span><span class="w"> </span><span class="n">args</span><span class="p">))))</span><span class="w">
</span><span class="p">([</span><span class="n">f</span><span class="w"> </span><span class="n">arg1</span><span class="w"> </span><span class="n">arg2</span><span class="w"> </span><span class="n">arg3</span><span class="p">]</span><span class="w">
</span><span class="p">(</span><span class="k">fn</span><span class="w">
</span><span class="p">([]</span><span class="w"> </span><span class="p">(</span><span class="nf">f</span><span class="w"> </span><span class="n">arg1</span><span class="w"> </span><span class="n">arg2</span><span class="w"> </span><span class="n">arg3</span><span class="p">))</span><span class="w">
</span><span class="p">([</span><span class="n">x</span><span class="p">]</span><span class="w"> </span><span class="p">(</span><span class="nf">f</span><span class="w"> </span><span class="n">arg1</span><span class="w"> </span><span class="n">arg2</span><span class="w"> </span><span class="n">arg3</span><span class="w"> </span><span class="n">x</span><span class="p">))</span><span class="w">
</span><span class="p">([</span><span class="n">x</span><span class="w"> </span><span class="n">y</span><span class="p">]</span><span class="w"> </span><span class="p">(</span><span class="nf">f</span><span class="w"> </span><span class="n">arg1</span><span class="w"> </span><span class="n">arg2</span><span class="w"> </span><span class="n">arg3</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="n">y</span><span class="p">))</span><span class="w">
</span><span class="p">([</span><span class="n">x</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="n">z</span><span class="p">]</span><span class="w"> </span><span class="p">(</span><span class="nf">f</span><span class="w"> </span><span class="n">arg1</span><span class="w"> </span><span class="n">arg2</span><span class="w"> </span><span class="n">arg3</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="n">z</span><span class="p">))</span><span class="w">
</span><span class="p">([</span><span class="n">x</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="n">z</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="n">args</span><span class="p">]</span><span class="w"> </span><span class="p">(</span><span class="nb">apply</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="n">arg1</span><span class="w"> </span><span class="n">arg2</span><span class="w"> </span><span class="n">arg3</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="n">z</span><span class="w"> </span><span class="n">args</span><span class="p">))))</span><span class="w">
</span><span class="p">([</span><span class="n">f</span><span class="w"> </span><span class="n">arg1</span><span class="w"> </span><span class="n">arg2</span><span class="w"> </span><span class="n">arg3</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="n">more</span><span class="p">]</span><span class="w">
</span><span class="p">(</span><span class="k">fn</span><span class="w"> </span><span class="p">[</span><span class="o">&</span><span class="w"> </span><span class="n">args</span><span class="p">]</span><span class="w"> </span><span class="p">(</span><span class="nb">apply</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="n">arg1</span><span class="w"> </span><span class="n">arg2</span><span class="w"> </span><span class="n">arg3</span><span class="w"> </span><span class="p">(</span><span class="nb">concat</span><span class="w"> </span><span class="n">more</span><span class="w"> </span><span class="n">args</span><span class="p">)))))</span></code></pre></figure>
<p>The way <em>partial</em> is used is by defining a function without arguments using <code class="language-plaintext highlighter-rouge">def</code> (as opposed to <code class="language-plaintext highlighter-rouge">defn</code>) and then call partial with a build-in Clojure function or an anonymous function:</p>
<figure class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="k">def</span><span class="w"> </span><span class="n">ktcs-partial</span><span class="w">
</span><span class="p">(</span><span class="nb">partial</span><span class="w"> </span><span class="o">#</span><span class="p">(</span><span class="nb">-></span><span class="w"> </span><span class="n">%</span><span class="w">
</span><span class="nb">name</span><span class="w">
</span><span class="n">clojure.string/capitalize</span><span class="p">)))</span></code></pre></figure>
<p>Here I expect this new function (<code class="language-plaintext highlighter-rouge">ktcs-partial</code>) to be called on each element of the collection inside a <em>map</em>. For this reason I want it to return a <em>thread</em> (Clojure function represented as a <a href="https://clojuredocs.org/clojure.core/-%3E"><code class="language-plaintext highlighter-rouge">-></code></a> like here, or a <a href="https://clojuredocs.org/clojure.core/-%3E%3E"><code class="language-plaintext highlighter-rouge">->></code></a>) of the two steps of transformation needed.</p>
<figure class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="nb">map</span><span class="w"> </span><span class="n">ktcs-partial</span><span class="w"> </span><span class="p">[</span><span class="no">:value</span><span class="w"> </span><span class="no">:location</span><span class="w"> </span><span class="no">:unit</span><span class="p">])</span><span class="w">
</span><span class="p">(</span><span class="s">"Value"</span><span class="w"> </span><span class="s">"Location"</span><span class="w"> </span><span class="s">"Unit"</span><span class="p">)</span></code></pre></figure>
<p>In this case there’s no benefit over using <em>comp</em> for example (see blog post <a href="/programming%20languages/2018/01/17/combining-functions-with-clojure-1.html">part 1</a>). However when you have several steps of transformations to be executed several times, using <em>partial</em> in this way gets useful.</p>
<h2 id="partial-combined-with-comp"><em>partial</em> combined with <em>comp</em></h2>
<p>In the previous post I used the Clojure built-in function <em>comp</em> (for “compose”) to combine two functions (namely <em>name</em> and <em>capitalize</em>) into one.</p>
<p>Here I got wondering if I could define a <em>partial</em> function that uses <em>comp</em> to combine the two steps of transformation I want to perform. I’m just combining Clojure functions for the fun of it!</p>
<p>If I’d need this transformations performed many times and always on a collection of keywords, I’d define this function:</p>
<figure class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="k">def</span><span class="w"> </span><span class="n">comp-partial</span><span class="w">
</span><span class="p">(</span><span class="nb">partial</span><span class="w"> </span><span class="p">(</span><span class="k">fn</span><span class="w"> </span><span class="p">[</span><span class="n">list-kw</span><span class="p">]</span><span class="w">
</span><span class="p">(</span><span class="nb">map</span><span class="w"> </span><span class="o">#</span><span class="p">((</span><span class="nb">comp</span><span class="w"> </span><span class="n">clojure.string/capitalize</span><span class="w"> </span><span class="nb">name</span><span class="p">)</span><span class="w"> </span><span class="n">%</span><span class="p">)</span><span class="w">
</span><span class="n">list-kw</span><span class="p">))))</span></code></pre></figure>
<p>And it’d be used like so:</p>
<figure class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="nf">comp-partial</span><span class="w"> </span><span class="p">[</span><span class="no">:value</span><span class="w"> </span><span class="no">:location</span><span class="w"> </span><span class="no">:unit</span><span class="p">])</span><span class="w">
</span><span class="p">(</span><span class="s">"Value"</span><span class="w"> </span><span class="s">"Location"</span><span class="w"> </span><span class="s">"Unit"</span><span class="p">)</span></code></pre></figure>
<p>So again, no revolution here. Just trying out functions so I can use them efficiently when needed!</p>
<h2 id="what-did-i-learn">What did I learn?</h2>
<ul>
<li>I reviewed the use of Clojure built-in function <em>partial</em>, and i think I’ll use it more now.</li>
<li>I had never looked at the source code for <em>partial</em> and it’s quite cool to see the two levels of multi-arity B-)</li>
</ul>
<p><strong>That’s it for now! Hopefully I’ll (finally) get faster at writing blog posts!</strong></p>
<hr />
<p>References:</p>
<ul>
<li>Documentation for <a href="https://clojuredocs.org/clojure.core/partial"><em>partial</em></a></li>
<li>Concept of functional programming: <a href="https://en.wikipedia.org/wiki/Higher-order_function">higher order functions</a></li>
<li>Interesting feature of Clojure: <a href="http://clojure-doc.org/articles/language/functions.html#multi-arity-functions">multi-arity</a></li>
</ul>ÉléonoreCombining functions with Clojure (2)Viz Playground - basic data viz with Vega2018-03-29T00:00:00+00:002018-03-29T00:00:00+00:00http://blog.elle-est-au-nord.com//data%20visualisation/2018/03/29/basic-dataviz-with-vega<h1 id="viz-playground---basic-data-viz-with-vega">Viz Playground - basic data viz with Vega</h1>
<p>Oh no :-/ I haven’t written a post in so long!</p>
<p>For my second technical post, I had in mind something related to the talk I gave at <a href="http://pycon.se/">PyCon Sweden 2017</a> back in September 2017 (here’s a <a href="https://github.com/Eleonore9/pyconse17/blob/master/slides-ele-pyconse17.pdf">link</a> to my slides on Github).
My idea then was to share my experience of <strong>trying a new data visualisation tool</strong>. This tool called <a href="https://github.com/altair-viz/altair"><strong>Altair</strong></a> isn’t another data visualisation library as such, but a Python API to access the powerful and simple <a href="https://github.com/vega/vega-lite"><strong>Vega-Lite</strong></a> <strong>JSON like grammar for interactive graphics</strong> (itself build on top of <strong>Vega</strong>).</p>
<h2 id="why-vega">Why Vega?</h2>
<p>While it was fun and interesting to try out <strong>Altair</strong> (I used it for a personal <a href="https://eleonore9.github.io/ebola_outbreaks/">project</a>), it is still in the process of supporting Vega-Lite 2.0. So, I now decided to directly try out <strong>Vega</strong>.</p>
<p>The idea is still to have a go-to tool for creating a rapid data visualisation. Specific use cases would be a prototype, a hackathon project… Come on, don’t tell me you don’t have a dataset of interest to visualise and share with a colleague or the world (well, your Twitter followers at least)!</p>
<p>Vega generates web visualisation using either HTML5 Canvas or SVG. And here we’re working with <strong>Vega-Lite</strong> which provides a more concise syntax than <strong>Vega</strong>.</p>
<h2 id="create-a-vega-lite-chart">Create a Vega-Lite chart</h2>
<p><em>Note:</em> You can have a look at the plot on <a href="https://bl.ocks.org/Eleonore9/0a759cc56022e40930530f32a0d92525">Blocks</a>!</p>
<p><strong>Vega-Lite</strong> visualisations are specified by JSON objects that can contain several properties like “name”, “description”, “title”, “data”, “transform”, etc…</p>
<p>To define a minimal chart you want to provide the “data”, “mark” and “encoding” properties.</p>
<ul>
<li>The <code class="language-plaintext highlighter-rouge">data</code> source is expected to be tabular data. It can be inline data (see below) or loaded from a file (JSON, CSV or TSV). [1]</li>
<li>The <code class="language-plaintext highlighter-rouge">mark</code> is the type of visualisation you need, in this case “bar” for a bar chart. It can be a simple string or a <code class="language-plaintext highlighter-rouge">mark</code> object. [2]</li>
<li>The <code class="language-plaintext highlighter-rouge">encoding</code> property links the data fields and the axis of the chart. In our case we’re creating an horizontal bar chart, so we’re inverting “x” and “y”. Here the “y” axis will display the “element” which is an “ordinal” data type as I’m using it as a label for each data point and want to keep the order. And the “x” axis will display the actual “value” field hence the type is “quantitative”.
The <code class="language-plaintext highlighter-rouge">encoding</code> can have more properties to transform the data. [3]</li>
</ul>
<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="p">{</span>
<span class="dl">"</span><span class="s2">data</span><span class="dl">"</span><span class="p">:</span> <span class="p">{</span>
<span class="dl">"</span><span class="s2">values</span><span class="dl">"</span><span class="p">:</span> <span class="p">[{</span><span class="dl">"</span><span class="s2">element</span><span class="dl">"</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span> <span class="dl">"</span><span class="s2">value</span><span class="dl">"</span><span class="p">:</span> <span class="mi">4</span><span class="p">},</span>
<span class="p">{</span><span class="dl">"</span><span class="s2">element</span><span class="dl">"</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span> <span class="dl">"</span><span class="s2">value</span><span class="dl">"</span><span class="p">:</span> <span class="mi">8</span><span class="p">},</span>
<span class="p">{</span><span class="dl">"</span><span class="s2">element</span><span class="dl">"</span><span class="p">:</span> <span class="mi">3</span><span class="p">,</span> <span class="dl">"</span><span class="s2">value</span><span class="dl">"</span><span class="p">:</span> <span class="mi">15</span><span class="p">},</span>
<span class="p">{</span><span class="dl">"</span><span class="s2">element</span><span class="dl">"</span><span class="p">:</span> <span class="mi">4</span><span class="p">,</span> <span class="dl">"</span><span class="s2">value</span><span class="dl">"</span><span class="p">:</span> <span class="mi">16</span><span class="p">},</span>
<span class="p">{</span><span class="dl">"</span><span class="s2">element</span><span class="dl">"</span><span class="p">:</span> <span class="mi">5</span><span class="p">,</span> <span class="dl">"</span><span class="s2">value</span><span class="dl">"</span><span class="p">:</span> <span class="mi">23</span><span class="p">},</span>
<span class="p">{</span><span class="dl">"</span><span class="s2">element</span><span class="dl">"</span><span class="p">:</span> <span class="mi">6</span><span class="p">,</span> <span class="dl">"</span><span class="s2">value</span><span class="dl">"</span><span class="p">:</span> <span class="mi">42</span><span class="p">}]</span>
<span class="p">},</span>
<span class="dl">"</span><span class="s2">mark</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">bar</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">encoding</span><span class="dl">"</span><span class="p">:</span> <span class="p">{</span>
<span class="dl">"</span><span class="s2">y</span><span class="dl">"</span><span class="p">:</span> <span class="p">{</span>
<span class="dl">"</span><span class="s2">field</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">element</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">type</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">ordinal</span><span class="dl">"</span>
<span class="p">},</span>
<span class="dl">"</span><span class="s2">x</span><span class="dl">"</span><span class="p">:</span> <span class="p">{</span>
<span class="dl">"</span><span class="s2">field</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">value</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">type</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">quantitative</span><span class="dl">"</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span></code></pre></figure>
<p>You can copy/paste this code in a <a href="https://vega.github.io/editor/">Vega editor</a>!</p>
<h2 id="embed-a-vega-lite-chart-in-html">Embed a Vega-Lite chart in html</h2>
<p>The easier way to publish a Vega-Lite visualisation is to embed it using the libray <a href="https://github.com/vega/vega-embed">Vega-Embed</a>.</p>
<p>1) Add the CDN (content delivery network) links in your HTML page:</p>
<figure class="highlight"><pre><code class="language-html" data-lang="html"><span class="nt"><script </span><span class="na">src=</span><span class="s">"https://cdn.jsdelivr.net/npm/vega@3"</span><span class="nt">></script></span>
<span class="nt"><script </span><span class="na">src=</span><span class="s">"https://cdn.jsdelivr.net/npm/vega-lite@2"</span><span class="nt">></script></span>
<span class="nt"><script </span><span class="na">src=</span><span class="s">"https://cdn.jsdelivr.net/npm/vega-embed@3"</span><span class="nt">></script></span></code></pre></figure>
<p>2) Add a <em>div</em> where the visualisation will be attached <code class="language-plaintext highlighter-rouge"><div id="vis"></div></code>.</p>
<p>3) Link the <code class="language-plaintext highlighter-rouge">#vis</code> div to the Vega-Lite <code class="language-plaintext highlighter-rouge">chart</code> object using the function <em>vegaEmbed()</em>, like this: <code class="language-plaintext highlighter-rouge">vegaEmbed("#vis", chart);</code>.</p>
<p>The <code class="language-plaintext highlighter-rouge">chart</code> object to be embedded contains “data”, “mark” and “encoding” properties as well as an optional JSON schema, “$schema”, and an optional “description”.</p>
<p>In my example below you can see the <em>vegaEmbed</em> function can take an extra optional property (called <code class="language-plaintext highlighter-rouge">opt</code> below). This gives you more control on the rendering of the visualisation.
Here I choose to render a SVG (instead of a PNG image) and I specify its size.</p>
<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="kd">var</span> <span class="nx">chart</span> <span class="o">=</span> <span class="p">{</span>
<span class="dl">"</span><span class="s2">$schema</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">https://vega.github.io/schema/vega-lite/v2.json</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">description</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">A simple bar chart with embedded data.</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">data</span><span class="dl">"</span><span class="p">:</span> <span class="p">{</span>
<span class="dl">"</span><span class="s2">values</span><span class="dl">"</span><span class="p">:</span> <span class="p">[{</span><span class="dl">"</span><span class="s2">element</span><span class="dl">"</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span> <span class="dl">"</span><span class="s2">value</span><span class="dl">"</span><span class="p">:</span> <span class="mi">4</span><span class="p">},</span>
<span class="p">{</span><span class="dl">"</span><span class="s2">element</span><span class="dl">"</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span> <span class="dl">"</span><span class="s2">value</span><span class="dl">"</span><span class="p">:</span> <span class="mi">8</span><span class="p">},</span>
<span class="p">{</span><span class="dl">"</span><span class="s2">element</span><span class="dl">"</span><span class="p">:</span> <span class="mi">3</span><span class="p">,</span> <span class="dl">"</span><span class="s2">value</span><span class="dl">"</span><span class="p">:</span> <span class="mi">15</span><span class="p">},</span>
<span class="p">{</span><span class="dl">"</span><span class="s2">element</span><span class="dl">"</span><span class="p">:</span> <span class="mi">4</span><span class="p">,</span> <span class="dl">"</span><span class="s2">value</span><span class="dl">"</span><span class="p">:</span> <span class="mi">16</span><span class="p">},</span>
<span class="p">{</span><span class="dl">"</span><span class="s2">element</span><span class="dl">"</span><span class="p">:</span> <span class="mi">5</span><span class="p">,</span> <span class="dl">"</span><span class="s2">value</span><span class="dl">"</span><span class="p">:</span> <span class="mi">23</span><span class="p">},</span>
<span class="p">{</span><span class="dl">"</span><span class="s2">element</span><span class="dl">"</span><span class="p">:</span> <span class="mi">6</span><span class="p">,</span> <span class="dl">"</span><span class="s2">value</span><span class="dl">"</span><span class="p">:</span> <span class="mi">42</span><span class="p">}]</span>
<span class="p">},</span>
<span class="dl">"</span><span class="s2">mark</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">bar</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">encoding</span><span class="dl">"</span><span class="p">:</span> <span class="p">{</span>
<span class="dl">"</span><span class="s2">y</span><span class="dl">"</span><span class="p">:</span> <span class="p">{</span> <span class="dl">"</span><span class="s2">field</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">element</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">type</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">ordinal</span><span class="dl">"</span> <span class="p">},</span>
<span class="dl">"</span><span class="s2">x</span><span class="dl">"</span><span class="p">:</span> <span class="p">{</span> <span class="dl">"</span><span class="s2">field</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">value</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">type</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">quantitative</span><span class="dl">"</span> <span class="p">}</span>
<span class="p">}</span>
<span class="p">};</span>
<span class="kd">var</span> <span class="nx">opt</span> <span class="o">=</span> <span class="p">{</span>
<span class="dl">"</span><span class="s2">mode</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">vega-lite</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">renderer</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">svg</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">width</span><span class="dl">"</span><span class="p">:</span> <span class="mi">450</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">height</span><span class="dl">"</span><span class="p">:</span> <span class="mi">450</span>
<span class="p">};</span>
<span class="nx">vegaEmbed</span><span class="p">(</span><span class="dl">"</span><span class="s2">#vis</span><span class="dl">"</span><span class="p">,</span> <span class="nx">chart</span><span class="p">,</span> <span class="nx">opt</span><span class="p">).</span><span class="nx">then</span><span class="p">(</span><span class="kd">function</span> <span class="p">(</span><span class="nx">result</span><span class="p">)</span> <span class="p">{</span>
<span class="p">}).</span><span class="k">catch</span><span class="p">(</span><span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">);</span></code></pre></figure>
<p>This code creates the following chart:</p>
<p><img src="http://blog.elle-est-au-nord.com//assets/vega.svg" alt="horizontal barchart" /></p>
<h2 id="minimal-interaction">Minimal interaction</h2>
<p>I thought it would help the user experience to add a display of information about a data point when one hovers over said data point. For that I used the Vega plugin called <a href="https://github.com/vega/vega-tooltip">Tooltip</a>.</p>
<p>There isn’t much more to do once the chart is embedded in htlm.</p>
<p>1) Add links to Tooltip javascript and CSS CDNs:</p>
<figure class="highlight"><pre><code class="language-html" data-lang="html"><span class="nt"><script </span><span class="na">src=</span><span class="s">"https://cdn.jsdelivr.net/npm/vega-tooltip@[VERSION]"</span><span class="nt">></script></span>
<span class="nt"><link</span> <span class="na">rel=</span><span class="s">"stylesheet"</span> <span class="na">type=</span><span class="s">"text/css"</span> <span class="na">href=</span><span class="s">"https://cdn.jsdelivr.net/npm/vega-tooltip@[VERSION]/build/vega-tooltip.min.css"</span><span class="nt">></span></code></pre></figure>
<p>2) Create a tooltip using the <em>vegaTooltip.vegaLite()</em> function using the Vega view and the Vega-Lite chart object:</p>
<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="nx">vegaEmbed</span><span class="p">(</span><span class="dl">"</span><span class="s2">#vis</span><span class="dl">"</span><span class="p">,</span> <span class="nx">chart</span><span class="p">,</span> <span class="nx">opt</span><span class="p">).</span><span class="nx">then</span><span class="p">(</span><span class="kd">function</span> <span class="p">(</span><span class="nx">result</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">vegaTooltip</span><span class="p">.</span><span class="nx">vegaLite</span><span class="p">(</span><span class="nx">result</span><span class="p">.</span><span class="nx">view</span><span class="p">,</span> <span class="nx">chart</span><span class="p">);</span>
<span class="p">}).</span><span class="k">catch</span><span class="p">(</span><span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">);</span></code></pre></figure>
<p>Here’s what the tooltip looks like:</p>
<p><img src="http://blog.elle-est-au-nord.com//assets/vega-tooltip.gif" alt="gif of horizontal barchart with tooltip" /></p>
<p>And interact with it <a href="https://bl.ocks.org/Eleonore9/raw/0a759cc56022e40930530f32a0d92525/">here</a>.</p>
<h2 id="my-take-away">My take away</h2>
<p>I find Vega-Lite grammar super nice! The usage is straightforward and it’s very well documented! I’m definitely going to use it more in the future.</p>
<p>I’m also looking forward to the new version of <a href="https://github.com/altair-viz/altair">Altair</a> and I’ll try the Clojure API for Vega called <a href="https://github.com/metasoarous/oz">Oz</a>.</p>
<hr />
<p>Notes:</p>
<p>[1] Vega-Lite <code class="language-plaintext highlighter-rouge">data</code> property: <a href="https://vega.github.io/vega-lite/docs/data.html">vega.github.io/vega-lite/docs/data.html</a></p>
<p>[2] Vega-Lite <code class="language-plaintext highlighter-rouge">mark</code> property: <a href="https://vega.github.io/vega-lite/docs/mark.html">vega.github.io/vega-lite/docs/mark.html</a></p>
<p>[3] Vega-Lite <code class="language-plaintext highlighter-rouge">encoding</code> property: <a href="https://vega.github.io/vega-lite/docs/encoding.html">vega.github.io/vega-lite/docs/encoding.html</a></p>
<p>References:</p>
<ul>
<li>
<p>More on Vega and Vega-Lite: <a href="https://vega.github.io/">vega.github.io/</a></p>
</li>
<li>
<p>Vega in Python with <a href="https://github.com/altair-viz/altair">Altair</a> and in Clojure with <a href="https://github.com/metasoarous/oz">Oz</a></p>
</li>
<li>
<p>Code and visualisation done for this blog post on <a href="https://bl.ocks.org/Eleonore9/0a759cc56022e40930530f32a0d92525">Blocks</a></p>
</li>
<li>
<p>Read up options to embed Vega visualisations on <a href="https://github.com/vega/vega-embed">Vega-embed</a> Readme.</p>
</li>
<li>
<p>The Vega <a href="https://github.com/vega/vega-tooltip">Tooltip</a> plugin.</p>
</li>
</ul>ÉléonoreViz Playground - basic data viz with VegaCombining functions with Clojure (1)2018-01-17T00:00:00+00:002018-01-17T00:00:00+00:00http://blog.elle-est-au-nord.com//programming%20languages/2018/01/17/combining-functions-with-clojure-1<h1 id="combining-functions-with-clojure-1">Combining functions with Clojure (1)</h1>
<hr />
<p><strong>DISCLAIMER</strong>
This post doesn’t contain any amazing coding ninja trick!
It’s basically me taking the time to try out two built-in Clojure functions I’m uncomfortable with instead of doing it the way I’m comfortable with.</p>
<hr />
<p>This first technical post is based on a gist I wrote (two years ago apparently) to keep notes while writing code. As you can deduce from the title this is about combining functions (here, in order to transform data). It should be a straightforward example to follow even if you don’t know Clojure (if not, please give me feedback [0]) and will at one point be followed by another post on the same subject using a different built-in Clojure function.</p>
<h2 id="whats-the-problem-at-hand">What’s the “problem” at hand?</h2>
<p>At the time I was simply trying to transform a collection of <em>keywords</em> [1] <code class="language-plaintext highlighter-rouge">[:value :location :unit]</code> into a collection of capitalised strings <code class="language-plaintext highlighter-rouge">["Value" "Location" "Unit"]</code> using Clojure (note: here I don’t care if the output is a list or a vector [2]).</p>
<p>My idea is to <a href="https://clojuredocs.org/clojure.core/map"><em>map</em></a> over the input collection and apply a combination of functions that would perform the transformation. I know the functions I need for this basic transformation are <a href="https://clojuredocs.org/clojure.core/name"><em>name</em></a> and <a href="https://clojuredocs.org/clojure.string/capitalize"><em>capitalize</em></a> [3].</p>
<p>My go-to function would be a <a href="https://clojure.org/guides/threading_macros">threading macro</a>:</p>
<figure class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="nb">map</span><span class="w"> </span><span class="o">#</span><span class="p">(</span><span class="nb">-></span><span class="w"> </span><span class="n">%</span><span class="w">
</span><span class="nb">name</span><span class="w">
</span><span class="n">str/capitalize</span><span class="p">)</span><span class="w">
</span><span class="p">[</span><span class="no">:value</span><span class="w"> </span><span class="no">:location</span><span class="w"> </span><span class="no">:unit</span><span class="p">])</span></code></pre></figure>
<p>[4]</p>
<p>But I wanted to try out a “more elaborate” way of doing it while I had an easy example at hand. And by more elaborate, I mean using the <a href="https://clojuredocs.org/clojure.core/juxt"><em>juxt</em></a> or <a href="https://clojuredocs.org/clojure.core/comp"><em>comp</em></a> functions. Both those functions are expected to take in functions and return a function that in a way combines the functions pasted in as arguments [5].</p>
<h2 id="meet-juxt">Meet <em>juxt</em></h2>
<p><em>Juxt</em> stands for juxtapose.
You can have a look at the source code <a href="https://github.com/clojure/clojure/blob/clojure-1.9.0-alpha14/src/clj/clojure/core.clj#L2549">here</a>. Let see what the doc says:</p>
<blockquote>
<p>Takes a set of functions and returns a fn that is the juxtaposition of those fns.
The returned fn takes a variable number of args, and returns a vector containing the result of applying each fn to the args (left-to-right).</p>
</blockquote>
<p>It looks like I can use <em>juxt</em> to juxtapose the functions <em>name</em> and <em>capitalize</em> and I’ll get the output collection as a vector (which is fine with me).</p>
<p>Here’s how I tried it:</p>
<figure class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="nb">map</span><span class="w"> </span><span class="o">#</span><span class="p">((</span><span class="nf">juxt</span><span class="w"> </span><span class="nb">name</span><span class="w"> </span><span class="n">str/capitalize</span><span class="p">)</span><span class="w"> </span><span class="n">%</span><span class="p">)</span><span class="w">
</span><span class="p">[</span><span class="no">:value</span><span class="w"> </span><span class="no">:location</span><span class="w"> </span><span class="no">:unit</span><span class="p">])</span></code></pre></figure>
<p>And the result was: <code class="language-plaintext highlighter-rouge">(["value" ":value"] ["location" ":location"] ["unit" ":unit"])</code>. So obviously not what I want. And if I inverse my argument functions:</p>
<figure class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="nb">map</span><span class="w"> </span><span class="o">#</span><span class="p">((</span><span class="nf">juxt</span><span class="w"> </span><span class="n">str/capitalize</span><span class="w"> </span><span class="nb">name</span><span class="p">)</span><span class="w"> </span><span class="n">%</span><span class="p">)</span><span class="w">
</span><span class="p">[</span><span class="no">:value</span><span class="w"> </span><span class="no">:location</span><span class="w"> </span><span class="no">:unit</span><span class="p">])</span></code></pre></figure>
<p>This gives me <code class="language-plaintext highlighter-rouge">([":value" "value"] [":location" "location"] [":unit" "unit"])</code>, so still not what I’m looking for!</p>
<p>I don’t know about you, but sometimes I want so much for a function to do what I need that I misread the doc. Here <em>juxt</em> as indeed applied <em>name</em> and <em>capitalize</em> on each element of my collection and returned it in a vector: <code class="language-plaintext highlighter-rouge">[":location" "location"]</code>. It’s not obvious for <em>capitalize</em> and I’d have expected an exception when a function intended for strings is used on a keyword. But we can reproduce it separately:</p>
<figure class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="nb">></span><span class="w"> </span><span class="p">(</span><span class="nf">clojure.string/capitalize</span><span class="w"> </span><span class="no">:my-keyword</span><span class="p">)</span><span class="w">
</span><span class="s">":my-keyword"</span></code></pre></figure>
<p><em>Capitalize</em> when used on a keyword somehow returns a string containing a copy of the keyword.</p>
<p>Now let’s try <em>comp</em>!</p>
<h2 id="meet-comp">Meet <em>comp</em></h2>
<p><em>Comp</em> stands for compose.
You can have a look at the source code <a href="https://github.com/clojure/clojure/blob/clojure-1.9.0-alpha14/src/clj/clojure/core.clj#L2530">here</a>. Let see what the doc says:</p>
<blockquote>
<p>Takes a set of functions and returns a fn that is the composition of those fns.
The returned fn takes a variable number of args, applies the rightmost of fns to the args, the next fn (right-to-left) to the result, etc.
This time it looks more like what I need; creating a function from <em>name</em> and <em>capitalize</em>, then apply it on elements of my collection. I just need to remember the functions are applied right to left:</p>
</blockquote>
<figure class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="nb">map</span><span class="w"> </span><span class="o">#</span><span class="p">((</span><span class="nb">comp</span><span class="w"> </span><span class="n">str/capitalize</span><span class="w"> </span><span class="nb">name</span><span class="p">)</span><span class="w"> </span><span class="n">%</span><span class="p">)</span><span class="w">
</span><span class="p">[</span><span class="no">:value</span><span class="w"> </span><span class="no">:location</span><span class="w"> </span><span class="no">:unit</span><span class="p">])</span></code></pre></figure>
<p>And this returns <code class="language-plaintext highlighter-rouge">("Value" "Location" "Unit")</code> just as I wanted! W00T :D</p>
<h2 id="what-did-i-learn">What did I learn?</h2>
<ul>
<li><em>clojure.string/capitalize</em> can be used on keywords, who knew? (Not me, obviously.)</li>
<li>Be more careful when reading the documentation!</li>
<li>Although there’s not an obvious gain here, I should now remember what <em>juxt</em> and <em>comp</em> do. And if I don’t I’ll come back to this post :)</li>
</ul>
<hr />
<p>Notes:</p>
<p>[0] I haven’t implemented comments (yet), but for feedback you can @ me or DM me on Twitter at <a href="https://twitter.com/eleonoremayola">@EleonoreMayola</a>!</p>
<p>[1] <a href="https://clojure.org/reference/data_structures#Keywords">Keywords</a> are a data type in Clojure often used as index in the key/value data structure called a map.</p>
<p>[2] More on Clojure data types, see <a href="https://clojure.org/reference/data_structures">here</a>.</p>
<p>[3] The <em>capitalize</em> function is defined in the clojure.string namespace, so if you try it at home you need to use <code class="language-plaintext highlighter-rouge">clojure.string/capitalize</code> or set <code class="language-plaintext highlighter-rouge">str</code> as <code class="language-plaintext highlighter-rouge">clojure.string/capitalize</code>.</p>
<p>[4] If you’re not used to this syntax <code class="language-plaintext highlighter-rouge">#(%)</code>, know that <code class="language-plaintext highlighter-rouge">#()</code> let’s you define an anonymous function like <code class="language-plaintext highlighter-rouge">fn(x)</code> and <code class="language-plaintext highlighter-rouge">%</code> in that case is a placeholder for the function’s argument. Also <code class="language-plaintext highlighter-rouge">-></code> is the threading function in Clojure called “thread first” as it adds <code class="language-plaintext highlighter-rouge">%</code> as the first argument of the function <em>name</em> and the output of calling <em>name</em> on our argument will be the first argument of the *capitilize function. Although here it’s not a big deal as those functions only take one argument.</p>
<p>[5] Well, we’re using a functional programming language here after all so there was bound to be a little bit of function inception ;)</p>ÉléonoreCombining functions with Clojure (1)Hello, world!2018-01-11T00:00:00+00:002018-01-11T00:00:00+00:00http://blog.elle-est-au-nord.com//update/2018/01/11/hello-world<h1 id="hello-world-">Hello, world :)</h1>
<p>I’m <a href="http://elle-est-au-nord.com/">Éléonore</a>!
I’m currently a freelance developer based in Stockholm, Sweden. I’ve worked with web technologies and data science/engineering mainly using <strong>Clojure</strong>, <strong>Python</strong>, <strong>Javascript</strong>, <strong>HTML</strong> and <strong>CSS</strong>.</p>
<p>I’ve considered creating a blog for years always finding reasons (mostly lack of time) for why I wouldn’t be able to sustain it with posts. But suddenly this week it made so much sense! Even if no one reads it, I now feel like a blog will be super useful for me to keep track of the things I learn over time.</p>
<p>I’ve actually written quite a few blog posts at my previous job where we had an internal blog to keep track of technical and business decisions and progress. And I ended up enjoying writing! The best part being when your post helps someone understand a process or problem. But memory can be faulty and having a record of previous trials and errors definitely saves time!</p>
<p>I have quite a few notes here and there than would be good material for the type of posts I want to write. I also plan to document the next things I’ll learn.</p>
<p>The themes I have in mind are: <strong>programming languages</strong> I know/learn (core functions and libraries), <strong>Linux stuffs</strong> I learn (well, Ubuntu mostly), <strong>projects</strong> I work on (sharing my experience and what went wrong), <strong>geo-related things</strong> (creating maps using open source software, contributing to humanitarian mapping) and maybe <strong>exploring (digital) art</strong>.</p>
<p><em>Disclaimer</em>: I’m not a native English speaker so you might have to suffer terrible grammatical errors (hopefully not spelling ones except for the odd typo).</p>ÉléonoreHello, world :)