Statystyk na wakacjach

Miejsce: Park rozrywki w Szklarskiej Porębie, kolejka do kina 6D.
Aktorzy: [S]taystyk na wakacjach i [B]ileterka.
Czas: 14:55, na 5 minut przed seansem w ww. kinie. Seanse odbywają się co 30 minut. Przed wejściem ustawia się kolejka. 10 minut przed seansem osoby z kolejki zaczynają wchodzić do kina. Wchodzi pierwsze 25 osób.

– Na ten seans już nie ma miejsc, proszę przyjść na kolejny o 15:30 – informuje Bileterka.
– A ile minut przed seansem powinienem przyjść by były jeszcze miejsca? – grzecznie pyta Statystyk.
– 5 minut przed seansem, tak jak jest napisane w regulaminie – Bileterka wskazuje palcem regulamin.
– Ale teraz jestem 5 minut przed seansem i już nie ma miejsc – zauważa Statytyk. – Więc ile minut wcześniej powinienem przyjść aby były jeszcze miejsca? – docieka.
– To zależy od tego ile osób przyjdzie. Musi być Pan najpóźniej 5 minut przed seansem. – powtarza Bileterka zniecierpliwionym głosem.
– A ile minut przed seansem się zazwyczaj kończą bilety? – dopytuje Statystyk.

Mniej więcej tutaj dla mojej interlokutorki staje się jasne, że trafił się jej wyjątkowo dociekliwy/upierdliwy (strony mogą różnie określać tę cechę) osobnik. Jej odpowiedź jest już bardziej stanowcza.

– Różnie się kończą. To zależy ile osób przyjdzie na kolejny seans. A tego nikt nie wie – rozmówczyni niesłusznie zakłada, że odstraszy mnie brak precyzyjnych szacunków.

W tym miejscu przerwę relacjonowanie naszej rozmowy. Na kolejny seans przyszedłem 10 minut przed czasem i wszedłem mniej więcej w połowie kolejki.

Ale historia dopiero tutaj się zaczyna.

Przez kolejne dwie godziny moje szkraby szalały na dmuchańcach obok kina. Miałem trochę czasu by poobserwować kolejkę do kina, zebrać trochę danych i zastanowić się, jak sam bym odpowiedział na pytanie, które zadałem Bileterce.

Zagadnienie:

Oszacować ile minut przed seansem należy przyjść aby mieć 90% pewności, że wystarczy dla nas miejsc w kinie.

Dane:

Dla 4 seansów (dwie godziny obserwacji) mamy informację ile osób (najczęściej przychodzą całe rodziny) i ile minut przed seansem dołączyło do kolejki.

Model 1:

Rozwiązanie brutalne, praktycznie bez modelowania.
Dla każdego seansu liczymy ile minut przed seansem przyszła ostatnia osoba, która zmieściła się na sali. Dla naszych seansów było to odpowiednio 8,9,7,8 minut.

Rozwiązanie proste o uroku cepa. Bez modelu parametrycznego z czterech liczb trudno wyznaczyć 90% kwantyl. (Ok, można jeżeli jest się ultrasem bootstrapowcem).

Szukamy więc czegoś parametrycznego.

Model 2:

Zakładamy, że liczba osób dochodzących do kolejki opisana jest jednorodnym procesem Poissona.
Oznacza to, że zakładamy, że w pewnym okresie czasu, np. -15 do -5 minut przed seansem, chętni przychodzą pojedynczo ze stałą intensywnością (=nie w stałych odstępach czasu ale ze stałem prawdopodobieństwem pojawienia się).
Więcej o procesie Poissona np. tutaj.

I co dalej? Szacujemy intensywność przychodzenia osób (w tym modelu to średnia) i liczymy czas oczekiwania na przekroczenie przez proces Poissona bariery 22 osób (jeszcze my się musimy zmieścić).

Piękny parametryczny model.
Drażniące są tylko te nierealne założenia.
Może da się je osłabić.

Model 3:

Zakładamy, że liczba osób dochodzących do kolejki opisana jest złożonym procesem Poissona.
Złożony proces Poissona to połączenie zwykłego procesu Poissona (opisuje momenty, w których do kolejki dochodzi rodzina) oraz skoków o różnej wielkości (wielkość skoku to liczba osób w rodzinie, które dołączyły do kolejki, z obserwacji od 1 do 5, najczęściej 2-3). Jest to rozszerzenie modelu 2, w którym uwzględniamy to, że do kolejki na raz dołączyć może kilka osób.
Więcej o złożonym procesie Poissona np. tutaj.

I co dalej? Osobno szacujemy intensywność pojawiania się rodzin (podobnie model z jednym parametrem szacowanym średnią), osobno szacujemy rozkład wielkości rodziny. Mając te składowe, wyznaczamy (np. symulacyjnie) rozkład czasu przekroczenia bariery 22 osób.

Model coraz piękniejszy, wymaga estymacji parametrów dwóch rozkładów (czasu przyjścia i wielkości rodziny). Drażni jedynie to założenie o stałej intensywności pojawiania się rodzin na odcinku -15 min do -5 min przed seansem.

Model 4:

Wykorzystajmy złożony niejednorodny proces Poissona. Czyli to co powyżej, ale tym razem intensywność pojawiania się rodzin jest nieujemną funkcją na odcinku -30 min do -5 min. Na początku raczej bliska zera (kto ustawia się w kolejce na 20 minut przed seansem gdy nikt inny w kolejce nie stoi?) a później szybko skacząca w czasie -15 min do -5 min przed seansem (nauczeni doświadczeniem wiedzą, że warto zjawić się wcześniej).
To już jest TEN model. W zmiennej intensywności możemy nawet uwzględnić porę dnia, liczbę osób przebywających w parku rozrywki i kilka innych parametrów. Samą intensywność można szacować np. estymatorem jądrowym.

Jedynym problemem okazało się to, że o 18 zamykali park i nie dało się zebrać więcej danych.

Więcej o niejednorodnym procesie Poissona można przeczytać tutaj.

Inne pomysły na modele?

[*] Ilustracja pochodzi z opowiadania ,,Jak długo żyją Muffinki”.

Liczba medali na olimpiadzie w Rio a wielkość kraju


Zastanawiałem się, czy liczba medali zdobytych na olimpiadzie w Rio koreluje z wielkością kraju.

Dane o populacji krajów można pobrać z wikipedii. O liczbie medali np. z serwisu wp.pl. Pobieramy dane pakietem XML i rysujemy pakietem rbokeh (interaktywna grafika, nadająca się na strony www).
Kod R dla obu tych operacji jest tutaj).

Otrzymujemy taki wykres (obie osie są w skali logarytmicznej). Korelacja Spearmana wynosi 0,44. Polska jest w okolicy 33 miejsca na obu osiach.

Wnioski? Korelacja jakaś jest. Co prawda są odstępstwa, częściej są to duże kraje o małej liczbie medali (Indie, Nigeria), rzadko odstępstwa dotyczą małego kraju o dużej liczbie medali.

BetaBit#3: nowa mini gra dla przyjaciół funkcji lm()

Wakacje w pełni. Dla tych, którzy chcieliby rozerwać się przy konsoli RStudio, mamy nową mini-grę z serii BetaBit. Gra nazywa się regression() i może być sporym wyzwaniem, o ile nie jest się bliskim przyjacielem funkcji lm().

Aby zagrać, należy zainstalować i włączyć wersję 1.3 pakietu BetaBit. Np. poleceniami

install.packages("BetaBit")
library("BetaBit")

Grę opracował Tomasz Żółtak. Podczas gry, w ramach wakacyjnego stażu, Beta i Bit pomagają profesorowi Pearsonowi w analizie pewnych danych edukacyjnych. Po rozwiązaniu wszystkich zadań prof. Pearson uraczy nas sentencją, która jest rozwiązaniem gry.

Przyjemnej rozrywki!

Osobom, które przyślą do końca sierpnia ww. sentencję wraz z rozwiązaniami zadań, prześlę kubek Bety (pierwsze 5 poprawnych zgłoszeń) lub opowiadania BetaBit (pozostałe rozwiązania).

Bez względu na to czy uda się czy nie rozwiązać wszystkie etapy, będę zobowiązany za wnioski, pomysły i komentarze dotyczące tej lub pozostałych gier z serii.

Rozwiązania i komentarze można wysyłać na przemyslaw.biecek na serwerze gmail.com.

A link that can tell more than dozens of lines of R code – what’s new in archivist?

Can you spot the difference between this plot:

And this one:

You are right! The latter has an embedded piece of R code.
What for?

It’s a call to a function aread from archivist – a package that manages external copies of R objects. This piece of code was added by the function addHooksToPrint(), that enriches knitr reports in links to all objects of a given class, e.g. ggplot.

You can copy this hook to your R session and you will automagically recreate this plot in your local session.

But it’s not all.
Actually here the story is just beginning.

Don’t you think, that this plot is badly annotated? It is not clear what is being presented. Something about terrorism, but for which year, are these results for all countries or there is some filtering? What is on axes? Why the author skip all these important information? Why he does not include the full R code that explains how this plot was created?

Actually, having this single link you can get answers for all these questions.

First, let’s download the plot and extract the data out of it.

This data object is also in the repository so I can download it with the aread function.

But here is the coolest part.
Having an object one can (in some cases) examine the history of this objects, i.e. check how it was created. Here is how to do this:

Now you can see what operations have been used to create data used in this plot. It’s clear how the aggregation has been done, what is the filtering condition and so on.
Also you have hashes to all objects created along the way, co you can download the partial results. This history is being recorded with an operator %a% that is working in a similar fashion to %>%.

We have the plot, now we know what is being presented, let’s change some annotations.

The ahistory() function for remote repositories was introduced to archivist in version 2.1 (on CRAN since yesterday). Other new feature is the support for repositories in shiny applications. Now you can enrich your app in links to copies of R objects generated by shiny.
You can find more information about these and other features in the useR2016 presentation about archivist (html, video).
Or look for Marcin Kosiński talk during the european R users meeting in Poznań.

The data presented in here is just a small fraction of data from National Consortium for the Study of Terrorism and Responses to Terrorism (START) (2016) retrieved from http://www.start.umd.edu/gtd.

Z pamiętnika nauczyciela akademickiego

Jedną z zaproszonych prelegentek na useR 2016 była Deborah Nolan z referatem ,,Statistical Thinking in a Data Science Course’’. Dora jest profesorem na Berkeley, zajmuje się między innymi technikami nauczania statystyki i napisała świetną książkę ,,Teaching Statistics: A Bag of Tricks’’. Jest też orędowniczką wizualizacji danych i poznawania statystyki przez eksperyment. W swoim referacie poruszyła kilka kwestii, które są mi bliskie i które uważam za ważne, więc poniżej przedstawię je miksując z własnymi doświadczeniami z prowadzenia zajęć w poprzednim semestrze. Całą prezentacje Dory można obejrzeć tutaj a grafiki w tym wpisie pochodzą z jej prezentacji.

Swoją drogą, podczas useR zorganizowane były dwie sesje poświęcone nauczaniu statystyki z użyciem R, jedną nawet miałem przyjemność moderować. Lista referatów z tych sesji znajduje się tutaj. Można też obejrzeć nagrania.

Wróćmy do prezentacji Dory.
Jedną z praktyk dotyczących nauczania statystyki z którą chciała się rozliczyć, jest podejście, że analiza eksploracyjna i wizualizacja danych jest dla dzieci, można tego uczyć w przedszkolu, ale nie wypada uczyć tego matematyków na studiach. Na studiach jest miejsce wyłącznie na teorię. Słowo wyłącznie jest tu użyte dosłownie. Nie jeden z nas doświadczył zajęć ze statystyki w których nie pojawiły się żadne [!] dane. Zdaniem Dory teoria jest bardzo ważna, ale drogą do niej są doświadczenia i intuicje zrodzone z EDA.

Czasem, nawet jeżeli dane się pojawiają, to często w charakterze obiadu w puszce. Dane tak przygotowane by zastosować do tych konkretnych danych jedną, jedyną właściwą, konkretną metodę, pokazać wyniki i lecieć dalej.
Tymczasem prawdziwa analiza danych dla niebanalnych problemów wygląda zupełnie inaczej.
Czasem w ogóle nie wiadomo co trzeba zrobić. A nawet jeżeli już wiadomo co zrobić to często nie wiadomo jaką metodą. Samo ustalanie co i jak może stanowić najtrudniejszy problem, który jest do rozwiązania.

Ok, wiemy już, że na zajęciach ze statystyki chcemy użyć danych i że chcemy by problemy były niebanalne. Jak to zrobić? Pomysł jest w sumie prosty, wprowadzić projekty oparte o współczesne, duże, bogate, złożone dane, związane z otwartymi pytaniami badawczymi.

Skąd brać takie projekty? Na naszych zajęciach na MIM UW czy MiNI PW udało się nawiązać współpracę z Ministerstwem Zdrowia, firmą Applica, działem badawczym Centrum Nauki Kopernik, Entuzjastami Edukacji i zespołem USOSa. Każdy z partnerów dał zbiór danych i wsparcie przy pozyskaniu wiedzy dziedzinowej. Dużych i ciekawych danych było więc sporo, do danych były dołączone dosyć otwarte problemy do rozwiązania.
Każdy projekt miał trzy fazy, co pozwoliło na stopniowe usprawnianie opracowanego rozwiązania, podsłuchanie tego co zrobiły inne grupy i ewentualne zaadaptowanie ich rozwiązań. Miłym bonusem była możliwość zaproszenia ekspertów dziedzinowych ze współpracujących instytucje na prezentacje projektów, dzięki czemu można wymienić się doświadczeniami z analiz (udało się między innymi zaprosić dyrektora IBE, capo di tutti capi USOSa, zrobić prezentacje w CNK).
[btw: Teraz szukam partnerów do projektów na przyszły rok, więc jeżeli Wasza firma/organizacja robi ciekawe rzeczy z ciekawymi danymi to zapraszam do kontaktu].

Co ciekawe, dyskusja po referacie Dory krążyła wokół obawy (wspólnej dla wielu krajów) ,,Ale nasi przełożeni są matematykami, nasi koledzy są matematykami, nasi studenci są matematykami, czy im się to spodoba?”. Odpowiedź prowadzącej była prosta. Jednym się spodoba, innym nie. Ale warto dać studentom trochę różnorodności. Bo na obecnie przematematyzowanej statystyce osoby preferujące doświadczalne podejście do analizy danych mogą nie znaleźć inspiracji. Może więc warto im pokazać, że analiza danych ma wiele oblicz i różne oblicza kręcą różne osoby.

Jak te projekty przyjeli moi studenci? Czy chciało im się spędzać godziny nad projektem, by sprawdzać co tam jeszcze można z tych danych wycisnąć? Czy studentom przyzwyczajonym do dowodzenia twierdzeń takie zajęcia mogą się w ogóle spodobać jeżeli za problemem do analizy nie stoi Google albo Microsoft?

Jednym tak innym nie. Znaleźli się studenci traktujący projekty jako zło konieczne. Wczytaj dane, wytrenuj las losowy, pokaż wynik, zapomnij. Ale trafiły się grupy robiące z danymi cuda. Na statystyce II znalazły się grupy, które do predykcji używały modeli mieszanych, regresji Poissona czy thin plate splines, choć żadnej z tych metod nie omawialiśmy na wykładzie [!!! i o to chodzi]. Na R i Duże Dane kilka zespołów wykorzystało łańcuchy markowa (których nie omawialiśmy na naszych zajęciach) i wywiązała się dyskusja czy założenia tej metody są w określonej sytuacji spełnione czy nie.

Jaka jest więc pointa? Dajmy studentom trochę różnorodności. Obok klasycznych matematycznych wykładów ze statystyki zróbmy miejsce na trochę szaleństwa w eksploracje danych mniej lub bardziej na oślep licząc, tak by uczyć się poruszać w gąszczu prawdziwych problemów. A nuż im się ten gąszcz spodoba.

Przyszłość ggvis

data-science
W przybliżeniu taki tytuł nosił referat Hadleya Wickhama, ale w rzeczywistości był to referat o przyszłości universum pakietów tworzonych i współtworzonych przez Hadleya.
A jest to ciekawy kierunek, więc poniżej napiszę o nim trochę więcej. (btw: zaproponował by zamiast hadleyverse używać nazwy tidyverse. Dlaczego tidy? o tym poniżej).

Prezentacja była świetnie przygotowana. Była jedną z dwóch najlepszych tego useR (drugą była prezentacja Donalda Knutha, ale z zupełnie innego powodu).
Niedługo powinna być dostępna pod tym adresem.

Jednym z ciekawszych wątków był wybór stawiany przed R pomiędzy byciem językiem programowania a byciem językiem do interaktywnej analizy danych. Z pewnością R jest bardziej językiem eksploracji danych niż językiem programistów, stąd pozycje typu The R inferno, wytykające rozwiązania nie do pomyślenia w dojrzałych językach programowania. Niekonsekwencje, które przeszkadzają lub drażnią wielu programistów, są jednak czasem wprowadzane celowo, po to by ułatwić prace z danymi.

O jakie niekonsekwencje chodzi? Zagadka z prezentacji Hadleya jest następująca, co jest wynikiem poniższego kodu.

Programiści przyzwyczajeni do klasycznych języków programowania spodziewaliby się, że wynikiem jest albo błąd (w obiekcie df nie ma slotu x, jest xyz) albo wektor z napisem. A tymczasem wynikiem jest factor z uwagi na domyślne parametry data.frame (uzupełnianie nazw argumentów i domyślna konwersja do faktorów). R core podjął lata temu decyzje by budować język ułatwiający analizę danych a nie pracę programistów, stąd niektóre błędy są maskowane i ,,naprawiane’’ po cichu w tle.

Drugim wyborem o którym mówił Hadley jest rozdźwięk pomiędzy byciem konserwatywnym a utopistą. Przy czym konserwatywny oznacza tu dbający o wsteczną zgodność z poprzednimi wersjami a utopista oznacza radosną budowę nowych rzeczy czasem bez zachowywania ciągłości z przeszłością. Użytkownicy ggplot2 i pochodnych pakietów na własnej skórze doświadczyli, że Hadley stawia się raczej bliżej utopisty adoptującego nowe rozwiązania, w przeciwieństwie do R core, które stara się zachować stabilność i wsteczną kompatybilność.

No właśnie, w przypadku obu wyborów kierunek tidyverse okazał się inny, niż ten który wybrał R code.

A tidyverse rośnie w siłę, zapowiedziane są pakiety gggeom i ggstat które mają zająć się właściwym uporządkowaniem tworzenia geometrii i tworzenia statystyk. data.frame zostanie zastąpiony przez tibble.
Funkcje będą jeszcze bardziej leniwe (w sensie leniwej ewaluacji) a struktury obiektów ujednolicone (do ramek danych) przez co będzie można pracować na bardziej spójnych strukturach.
To uniwersum rozwiązań rozrastać się będzie wewnątrz R, ale stanie się od reszty R coraz bardziej niezależne.
Pokryje kluczowe aktywności wykonywane przy analizie danych, opisane na wykresie rozpoczynającym ten blog (oczywiście autorstwa HW).
A co będzie później?
Obserwując tempo rozwoju tego universum, dowiemy się już wkrótce.

eRka: wakacyjny zespołowy konkurs z R

R_competition_final2

eRka wspólnie z Do-IT Solutions (z patronami INIME, FuRBS i SmarterPoland.pl) przygotowała na te wakacje zespołowy konkurs analizy danych.

Dane dotyczą wyników edukacyjnych uczniów z RPA. Być może pamiętacie, że dane były wykorzystywane w hackatonie organizowanym przez eRka rok temu, ale teraz i danych jest więcej i wyzwań jest więcej.

Więcej informacji o tym konkursie, w tym zasady i tematy analiz, znajduje się na tej stronie, a w języku polskim na tej stronie.

Od piątku można będzie zgłaszać zespoły.

useR 2016 – tutoriale

IMG_1102

Właśnie zakończył się pierwszy dzień useR2016, czyli sesja z tutorialami.
Do wyboru było wiele ciekawych pozycji (lista z opisami tutaj). Poniżej opiszę wrażenia z czterech, w których uczestniczyłem.

Never Tell Me the Odds! Machine Learning with Class Imbalances Max Kuhn – Pfizer.
Materiały do tego tutorialu znajdują się na githubie. Max (znany pewnie większości jako twórca pakietu caret) opowiadał o strategiach radzenia sobie z niezrównoważonymi klasami w problemie klasyfikacji. I oczywiście pokazywał jak rozwiązać ten problem z pakietem caret. O ile problemu prawie nie ma dla takich metod jak regresja logistyczna, to dla metod opartych o drzewa problem może być poważny. W materiałach jest porównanie trzech głównych strategii radzenia sobie z tym problemem: undersampling, oversampling i zmiana funkcji kosztu.
To był moim zdaniem najlepszy tutorial tej edycji useR.

Machine Learning Algorithmic Deep Dive, Erin LeDell – H2O.ai.
Równolegle prowadzony był tutorial pracownika H2O. To właśnie afiliacja prelegenta jak i atrakcyjne ,,deep dive” skusiła mnie i ponad 150 innych osób do wzięcia udziału w tym tutorialu. Ale okazało się, że nie było miejsca na głębokie zanurzenie, co najwyżej udało się zamoczyć stopy.
O ile sam tutorial był średnio udany (problemy z instalacją jupitera wykosiły ponad połowę osób, a jak się okazało wcale nie był on potrzebny bo i tak nie było czasu na uruchomienie kodu) to materiały są całkiem niezłe. Znajdują się one na githubie.

An Introduction to Bayesian Inference using R Interfaces to Stan, Ben Goodrich
Ponieważ język Stan znajduje się bardzo wysoko na liście rzeczy, które chciałbym bliżej poznać, z wielkimi nadziejami zapisałem się na ten tutorial. Ben jest jednym z kluczowych twórców Stana. Materiały z tego tutorialu znajdują się na tej stronie.
Materiały są ciekawe, choć jak dla mnie mogłoby być więcej bardziej złożonych przykładów zamiast zastanawiania się dlaczego ci częstościowi statystycy są tacy źli.
Najbardziej spodobał mi się ten slajd pokazujący jak sprawnie NUTS radzi sobie z korelacją kolejnych obserwacji (w porównaniu do RW Metropolisa czy algorytmu Gibbsa). To akurat dobra motywacja by dalej zgłębiać ten pakiet.

Using R with Jupyter Notebooks for Reproducible Research, Andrie de Vries & Micheleen Harris
W sali obok stan’a toczył się tutorial poświęcony bibliotece jupiter. Materiały są dostępne na githubie. Poza podstawami jupitera można było poznać https://notebooks.azure.com, czyli usługę pozwalającą na hostowanie notebooków na microsoftowym azurze. Najciekawsza na tym tutorialu była forma. Prowadząca wykorzystywała kilka ciekawych tricków związanych z prowadzeniem warsztatów, jak np. używanie karteczek aby szybko sygnalizować, że są jakieś problemu czy by robić szybkie binarne ankiety.

Obejrzyj dane zanim je pokażesz

Dzisiaj Polityka opublikowała artykuł Rząd zapowiadał, że ograniczy biurokrację. Zamiast tego cudownie się rozmnożył. W artykule są przykłady rosnącej biurokracji, tutaj mierzonej liczbą ministrów i wiceministrów.

Generalnie lubię w Polityce to, że często (w porównaniu z innymi portalami) opierają się na liczbach. Choć niestety rzadko pokazują te liczby za pomocą wykresu, zazwyczaj są to tabele lub takie zestawienie jak po prawej stronie.

Ale, myślę sobie, są dane wiec je pokażę. Przepisałem nazwy krajów i liczby ministrów, z wikipedii pobrałem informacje o wielkości ludności poszczególnych krajów.
Wyniki poniżej.
Widząc taki wykres dwie rzeczy rzucają się w oczy, (1) po Brexicie średnia liczba ministrów na kraj zmaleje, (2) co jest w sumie zaskakujące, liczba ministrów praktycznie nie zależy od ludności kraju (poniżej oś OX jest w skali sqrt a wciąż nie widać zależności).

Screen Shot 2016-06-27 at 22.07.17

Pointa: Z biurokracją trzeba walczyć. Ale akurat dane o liczbie ministrów nie pokazują polskiej biurokracji w najgorszym świetle.

Wykres i dane można pobrać instrukcją

Shiny + archivist = reproducible interactive exploration


Shiny is a great tool for interactive exploration (and not only for that). But, due to its architecture, all objects/results that are generated are stored in a separate R process so you cannot access them easily from your R console.

In some cases you may wish to retrieve a model or a plot that you have just generated. Or maybe just wish to store all R objects (plots, data sets, models) that have been ever generated by your Shiny application. Or maybe you would like to do some further tuning or validation of a selected model or plot. Or maybe you wish to collect and compare all lm() models ever generated by your app? Or maybe you would like to have an R code that will recover given R object in future.

So, how to do this?

Czytaj dalej Shiny + archivist = reproducible interactive exploration