Settings, imports, data


In [1]:
%matplotlib inline
%load_ext autoreload
%autoreload 2

In [39]:
from collections import OrderedDict
from IPython.display import display, Markdown
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
import learn
from monitoring.data import get_production_data
from monitoring.visualization import display_level_overview

sns.set()
pd.options.display.float_format = '{:.2f}'.format

In [3]:
# Load data from local cache, fetch and store if not available.
data = get_production_data('2018-06-21')


Data loaded from cache (/home/xeffenb1/projects/robomission/.prodcache/robomission-2018-06-21/).

In [4]:
ts = data['task_sessions']
ts = ts[ts.time_spent > 0]
ts = ts.assign(date=ts.end.str[:10])

Metrics


In [5]:
grouped_ts = ts.groupby('date')
metrics = pd.DataFrame(OrderedDict(
    active_students=grouped_ts.student.nunique(),
    solving_hours=grouped_ts.time_spent.sum() / 3600,
    solved_count=grouped_ts.solved.sum(),
    success_rate=grouped_ts.solved.mean(),
)).sort_index()
metrics.index = pd.to_datetime(metrics.index)

Active Students


In [6]:
metrics.active_students.resample('1W').mean().plot()


Out[6]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f0d6c1731d0>

In [7]:
metrics.solving_hours.resample('1W').mean().plot()


Out[7]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f0d6c118e10>

In [8]:
metrics.solved_count.resample('1W').mean().plot()


Out[8]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f0d6b5d76d8>

In [9]:
metrics.success_rate.resample('1W').mean().plot(ylim=[0,1])


Out[9]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f0d6b557748>

All task sessions

Histogram of log-times


In [10]:
ts.time_spent.apply(np.log).hist()


Out[10]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f0d6b48f630>

All tasks


In [6]:
grouped_ts = ts.groupby('task')
metrics = pd.DataFrame(OrderedDict(
    time=grouped_ts.time_spent.median(),
    success=grouped_ts.solved.mean(),
    n_attempts=grouped_ts.task.count(),
    n_solved=grouped_ts.solved.sum(),
))
metrics['n_unsolved'] = metrics.n_attempts - metrics.n_solved
tasks = data['tasks'].join(metrics).fillna(0)

Solved and Unsolved Attempts


In [7]:
ordered_tasks = tasks.sort_values('n_attempts', ascending=False)
ax = ordered_tasks[['n_solved', 'n_unsolved']].plot.bar(
    title='Attempts',
    stacked=True,
    color=[sns.xkcd_rgb['medium green'], sns.xkcd_rgb['pale red']],
    figsize=(9,6))
ax.set_xticklabels([])
ax.set_xlabel('task');


Success rate distribution


In [13]:
ax = tasks.success.plot.hist(title='success rate')


Median time distribution


In [14]:
ax = tasks.time.plot.hist(title='median time')


Median Time vs Success Rate


In [15]:
tasks.plot.scatter(x='success', y='time', logy=True)


Out[15]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f0d6b41e828>

Missions Overview


In [55]:
grouped_tasks = tasks.groupby('mission')
missions = pd.DataFrame(OrderedDict(
    level=grouped_tasks['level'].min(),
    time=grouped_tasks.time.median(), # median of medians
    success=grouped_tasks.success.mean(),
    n_attempts=grouped_tasks.n_attempts.sum(),
    n_solved=grouped_tasks.n_solved.sum(),
    n_tasks=grouped_tasks.name.count(),
)).reset_index()
missions = missions.rename(columns={'mission': 'name'})
missions = missions.sort_values(by='level')
missions = missions[
    ['level', 'name', 'n_tasks', 'n_attempts', 'success', 'time']]
display_level_overview(missions, order_by='level')


level name n_tasks n_attempts success time
0 1 commands 10 9382 95% 24s
1 2 commands-2 7 5895 87% 94s
7 3 repeat 11 5470 83% 86s
8 4 while 7 2601 83% 74s
5 5 loops 11 2507 72% 115s
3 6 if 7 932 55% 160s
2 7 comparing 9 506 40% 170s
4 8 if-else 7 217 57% 138s
6 9 loops-if 16 572 43% 253s

Tasks in Levels


In [57]:
def display_plot(ax):
    display(ax)
    plt.show()  # forcing to display here

def display_success_rate_hist(tasks):
    ax = tasks.success.plot.hist(
        bins=np.linspace(0, 1, 11),
        title='success rate')
    ax.set_xlim(0, 1)
    ax.set_ylim(0, 10)
    display_plot(ax)
    
def display_time_vs_success(tasks):
    ax = tasks.plot.scatter(x='success', y='time')
    ax.set_xlim(0, 1)
    display_plot(ax)
    
def analyze_level(name):
    ts = tasks[tasks.mission == name]
    ts = ts[['name', 'level2', 'order',
             'n_attempts', 'success', 'time']]
    display(Markdown('# {name}'.format(name=name)))
    display_level_overview(ts.reset_index(), order_by=['level2', 'order'])
    display_success_rate_hist(ts)
    display_time_vs_success(ts)
    display(Markdown('-----'))

for name in missions.name:
    analyze_level(name)


commands

id name level2 order n_attempts success time
0 51 three-steps-forward 1 1 979 97% 8s
1 49 turning-right 2 1 898 97% 18s
2 44 turning-left 2 2 911 97% 20s
3 26 turning-right-and-left 2 3 894 95% 19s
4 2 turning-left-and-right 2 4 1219 94% 44s
5 31 diamond-on-right 3 1 929 95% 26s
6 14 beware-of-asteroid 3 2 1028 93% 30s
7 67 plus 3 3 835 96% 21s
8 86 diamond-path 3 4 855 95% 28s
9 66 surrounded-diamond 3 5 834 89% 72s
<matplotlib.axes._subplots.AxesSubplot at 0x7f3912297b00>
<matplotlib.axes._subplots.AxesSubplot at 0x7f391227ea20>

commands-2

id name level2 order n_attempts success time
0 10 shot 1 1 906 99% 17s
1 8 shooting 1 2 852 97% 32s
2 12 wormhole-demo 2 1 873 98% 25s
3 6 tunnel 3 1 960 77% 178s
4 23 dont-forget-shot 3 2 784 79% 96s
5 19 2diamonds-2meteorids 3 3 791 74% 176s
6 79 last-shot 3 4 729 84% 94s
<matplotlib.axes._subplots.AxesSubplot at 0x7f39123303c8>
<matplotlib.axes._subplots.AxesSubplot at 0x7f3912eb9908>

repeat

id name level2 order n_attempts success time
0 11 ladder 1 1 671 90% 56s
1 1 diamonds-in-meteoroid-cloud 1 2 490 86% 62s
2 71 big-left-turn 2 1 401 98% 55s
3 70 big-right-turn 2 2 416 93% 48s
4 76 blocked-wormhole 2 3 402 91% 72s
5 84 triangle 2 4 432 84% 86s
6 13 n 2 5 592 84% 90s
7 21 steal-the-nose 3 1 591 77% 100s
8 46 find-the-path 3 2 491 69% 113s
9 57 stairs 3 3 499 72% 122s
10 18 clean-your-path 3 4 485 64% 179s
<matplotlib.axes._subplots.AxesSubplot at 0x7f3912c9e128>
<matplotlib.axes._subplots.AxesSubplot at 0x7f3912c71748>

while

id name level2 order n_attempts success time
0 3 zig-zag 1 1 460 79% 74s
1 53 direct-flight-ahead 1 2 355 94% 37s
2 17 yellow-is-not-red 2 1 395 77% 100s
3 41 yellow-hint 2 2 354 86% 62s
4 73 stop-on-red 2 3 335 80% 74s
5 38 direction-change 2 4 387 79% 95s
6 69 diamond-in-house 3 1 315 90% 118s
<matplotlib.axes._subplots.AxesSubplot at 0x7f3912dfa7f0>
<matplotlib.axes._subplots.AxesSubplot at 0x7f3912dfae10>

loops

id name level2 order n_attempts success time
0 56 diamond-cross 1 1 246 93% 50s
1 68 stripes 1 2 198 74% 78s
2 37 big-slalom 1 3 290 78% 94s
3 50 double-bend 1 4 230 80% 90s
4 58 collect-diamonds 2 1 233 75% 104s
5 55 color-slalom 2 2 225 61% 123s
6 52 zig-zag-plus 2 3 241 81% 119s
7 72 four-vs 2 4 165 71% 115s
8 63 rectangle 2 5 217 58% 171s
9 47 arrow 3 1 239 84% 200s
10 32 double-track 3 2 223 39% 265s
<matplotlib.axes._subplots.AxesSubplot at 0x7f3912af1fd0>
<matplotlib.axes._subplots.AxesSubplot at 0x7f39123885c0>

if

id name level2 order n_attempts success time
0 27 on-yellow-to-left 1 1 157 58% 105s
1 5 diamonds-with-signals 1 2 176 55% 138s
2 34 follow-colors 1 3 122 85% 110s
3 59 two-diamonds 2 1 143 46% 171s
4 60 red-shooting 2 2 108 54% 170s
5 78 yellow-squares 2 3 110 55% 160s
6 81 belgian-flag 3 1 116 35% 322s
<matplotlib.axes._subplots.AxesSubplot at 0x7f3912abdcf8>
<matplotlib.axes._subplots.AxesSubplot at 0x7f3912f3f588>

comparing

id name level2 order n_attempts success time
0 85 chessboard 1 1 56 43% 142s
1 48 edge-to-edge 1 2 44 45% 150s
2 7 meteoroids-and-wormholes 1 3 36 61% 200s
3 83 maneuvers-on-left 1 4 43 60% 195s
4 82 free-column 2 1 42 33% 140s
5 9 diamond-lines 2 2 90 39% 156s
6 65 letter-h 2 3 61 30% 170s
7 64 wave 3 1 57 26% 278s
8 28 slalom-position-testing 3 2 77 23% 260s
<matplotlib.axes._subplots.AxesSubplot at 0x7f39124e4400>
<matplotlib.axes._subplots.AxesSubplot at 0x7f3912a972e8>

if-else

id name level2 order n_attempts success time
0 80 letter-e 1 1 45 42% 66s
1 24 narrow-passage 1 2 26 65% 84s
2 29 color-navigation 1 3 22 64% 129s
3 75 bouncing-from-edge 2 1 34 68% 153s
4 16 diamonds-on-yellow 2 2 26 54% 138s
5 22 triple-steps 2 3 26 62% 160s
6 43 colorful-flowers 3 1 38 42% 296s
<matplotlib.axes._subplots.AxesSubplot at 0x7f3912b58a20>
<matplotlib.axes._subplots.AxesSubplot at 0x7f3912bf6518>

loops-if

id name level2 order n_attempts success time
0 20 five-diamonds 1 1 25 64% 120s
1 61 mirror 1 2 141 14% 192s
2 40 plan-your-shooting 1 3 38 24% 220s
3 45 diagonal-lines 1 4 23 57% 275s
4 15 wormhole-cloud 1 5 45 42% 195s
5 30 edge-wormholes 1 6 24 67% 238s
6 42 two-color-tracks 2 1 62 32% 252s
7 33 diamond-ring 2 2 25 40% 255s
8 36 cross-2 2 3 22 68% 193s
9 54 diagonal-diamonds 2 4 21 52% 228s
10 35 six-diamonds 2 5 25 48% 301s
11 4 triple-slalom 3 1 31 32% 281s
12 74 turning-in-square 3 2 20 25% 417s
13 77 letter-d 3 3 21 33% 357s
14 39 meteoroids-on-left 3 4 26 54% 320s
15 62 two-bit-instructions 3 5 23 35% 1233s
<matplotlib.axes._subplots.AxesSubplot at 0x7f3912cf25c0>
<matplotlib.axes._subplots.AxesSubplot at 0x7f391297df98>


In [ ]:


In [ ]:


In [ ]:


In [ ]:


In [ ]:


In [ ]: