{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Driver Splits\n", "\n", "Script to rebase the split times for a stage and display them relative to a specified driver.\n", "\n", "The intention is to generate a report on a stage that is meaningful to a specified driver.\n", "\n", "Ideally the report should:\n", "\n", "- show where the driver finished on the stage (stage rank)\n", "- show the running stage delta at each split compared to each other driver\n", "- show the extent to which a driver gained or lost time on each split compared to each other driver\n", "- show the start order (so that this can be related to stage rank)\n", "- identify the overall position at the end of the stage for each driver\n", "- show whether overall positions were gained or lost after the stage (not implemented yet; need a +=- column)\n", "\n", "\n", "Ideally, we'd use drivercodes, but these are not necessarily unique. For example, there are duplicates in RC2." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "if __name__=='__main__':\n", " %load_ext autoreload\n", " %autoreload 2" ] }, { "cell_type": "code", "execution_count": 59, "metadata": {}, "outputs": [], "source": [ "import notebookimport\n", "\n", "if __name__=='__main__':\n", " typ = 'overall' #this defines ???\n", " #rebase='overallleader' #TO DO\n", " rebase='OGI'#'PAD'\n", " MAXINSPLITDELTA=20 #set xlim on the within split delta\n", " ss='SS3'\n", " \n", " #The drivercode inbuilds some intelligence\n", " drivercode=rebase" ] }, { "cell_type": "code", "execution_count": 60, "metadata": {}, "outputs": [], "source": [ "sr = __import__(\"Charts - Stage Results\")\n", "ssd = __import__(\"Charts - Split Sector Delta\")" ] }, { "cell_type": "code", "execution_count": 61, "metadata": {}, "outputs": [], "source": [ "#!pip3 install pytablewriter" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Set up a connection to a simple SQLite database, and specify some metadata relating to the actual rally we are interested in." ] }, { "cell_type": "code", "execution_count": 113, "metadata": {}, "outputs": [], "source": [ "import os\n", "import sqlite3\n", "import pandas as pd\n", "import pytablewriter\n", "import six\n", "from numpy import NaN\n", "\n", "#dbname='wrc18.db'\n", "#dbname='france18.db'\n", "#conn = sqlite3.connect(dbname)\n", "\n", "if __name__=='__main__':\n", " #dbname='wrc18.db'\n", " dbname='sweden19.db'\n", " conn = sqlite3.connect(dbname)\n", " rally='Sweden'\n", " rc='RC1'\n", " year=2019\n", " #ss='SS4'" ] }, { "cell_type": "code", "execution_count": 63, "metadata": {}, "outputs": [], "source": [ "if __name__=='__main__':\n", " #This doesn't appear to be used elsewhere in this notebook\n", " #May support logic for checking stage status?\n", " stagedetails = sr.dbGetRallyStages(conn, rally).sort_values('number')\n", " stagedetails.head()" ] }, { "cell_type": "code", "execution_count": 64, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Index(['diffFirst', 'diffFirstMs', 'diffPrev', 'diffPrevMs', 'entryId',\n", " 'penaltyTime', 'penaltyTimeMs', 'position', 'stageTime', 'stageTimeMs',\n", " 'totalTime', 'totalTimeMs', 'stageId', 'class', 'code', 'distance',\n", " 'name', 'snum', 'drivercode', 'entrant.name', 'classrank',\n", " 'gainedClassPos', 'gainedClassLead', 'classPosDiff', 'lostClassLead',\n", " 'retainedClassLead', 'gainedTime', 'gainedOverallPos',\n", " 'gainedOverallLead', 'overallPosDiff', 'lostOverallLead',\n", " 'retainedOverallLead', 'firstinarow'],\n", " dtype='object')\n" ] }, { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
diffFirstdiffFirstMsdiffPrevdiffPrevMsentryIdpenaltyTimepenaltyTimeMspositionstageTimestageTimeMs...classPosDifflostClassLeadretainedClassLeadgainedTimegainedOverallPosgainedOverallLeadoverallPosDifflostOverallLeadretainedOverallLeadfirstinarow
0PT0S0PT0S03533PT0S01PT1M34.9S94900...0.0FalseFalseFalseFalseFalse0.0FalseFalse1
1PT0.8S800PT0.8S8003526PT0S02PT1M35.7S95700...0.0FalseFalseFalseFalseFalse0.0FalseFalse0
2PT1.1S1100PT0.3S3003538PT0S03PT1M36S96000...0.0FalseFalseFalseFalseFalse0.0FalseFalse0
3PT1.9S1900PT0.8S8003531PT0S04PT1M36.8S96800...0.0FalseFalseFalseFalseFalse0.0FalseFalse0
4PT2S2000PT0.1S1003532PT0S05PT1M36.9S96900...0.0FalseFalseFalseFalseFalse0.0FalseFalse0
\n", "

5 rows × 33 columns

\n", "
" ], "text/plain": [ " diffFirst diffFirstMs diffPrev diffPrevMs entryId penaltyTime \\\n", "0 PT0S 0 PT0S 0 3533 PT0S \n", "1 PT0.8S 800 PT0.8S 800 3526 PT0S \n", "2 PT1.1S 1100 PT0.3S 300 3538 PT0S \n", "3 PT1.9S 1900 PT0.8S 800 3531 PT0S \n", "4 PT2S 2000 PT0.1S 100 3532 PT0S \n", "\n", " penaltyTimeMs position stageTime stageTimeMs ... classPosDiff \\\n", "0 0 1 PT1M34.9S 94900 ... 0.0 \n", "1 0 2 PT1M35.7S 95700 ... 0.0 \n", "2 0 3 PT1M36S 96000 ... 0.0 \n", "3 0 4 PT1M36.8S 96800 ... 0.0 \n", "4 0 5 PT1M36.9S 96900 ... 0.0 \n", "\n", " lostClassLead retainedClassLead gainedTime gainedOverallPos \\\n", "0 False False False False \n", "1 False False False False \n", "2 False False False False \n", "3 False False False False \n", "4 False False False False \n", "\n", " gainedOverallLead overallPosDiff lostOverallLead retainedOverallLead \\\n", "0 False 0.0 False False \n", "1 False 0.0 False False \n", "2 False 0.0 False False \n", "3 False 0.0 False False \n", "4 False 0.0 False False \n", "\n", " firstinarow \n", "0 1 \n", "1 0 \n", "2 0 \n", "3 0 \n", "4 0 \n", "\n", "[5 rows x 33 columns]" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "if __name__=='__main__':\n", " #Let's see what data is available to us in the stagerank_overall table\n", " stagerank_overall = sr.getEnrichedStageRank(conn, rally, rc=rc, typ='overall')\n", " print(stagerank_overall.columns)\n", " display(stagerank_overall.head())" ] }, { "cell_type": "code", "execution_count": 65, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'SS1': 95700,\n", " 'SS2': 708900,\n", " 'SS3': 1483400,\n", " 'SS4': 2010900,\n", " 'SS5': 2642200,\n", " 'SS6': 3826100,\n", " 'SS7': 4767800,\n", " 'SS8': 5538100,\n", " 'SS9': 6227000,\n", " 'SS10': 6980100,\n", " 'SS11': 7475000,\n", " 'SS12': 8315400,\n", " 'SS13': 9081300,\n", " 'SS14': 9581400,\n", " 'SS15': 9678400,\n", " 'SS16': 9797400,\n", " 'SS17': 10463900}" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "if __name__=='__main__':\n", " #Get the total stage time for specified driver on each stage\n", " #We can then subtract this from each driver's time to get their times as rebased delta times\n", " # compared to the the specified driver\n", " rebaser = stagerank_overall[stagerank_overall['drivercode']==drivercode][['code','totalTimeMs']].set_index('code').to_dict(orient='dict')['totalTimeMs']\n", " display(rebaser)" ] }, { "cell_type": "code", "execution_count": 66, "metadata": {}, "outputs": [], "source": [ "def rebaseOverallRallyTime(stagerank_overall, drivercode):\n", " ''' Rebase overall stage rank relative to a specified driver. '''\n", " #Get the time for each stage for a particular driver\n", " rebaser = stagerank_overall[stagerank_overall['drivercode']==drivercode][['code','totalTimeMs']].set_index('code').to_dict(orient='dict')['totalTimeMs']\n", " #The stagerank_overall['code'].map(rebaser) returns the total time for each stage achieved by the rebase driver\n", " # stagerank_overall['code'] identifies the stage\n", " #Subtract this rebase time from the overall stage time for each driver by stage\n", " stagerank_overall['rebased'] = stagerank_overall['totalTimeMs'] - stagerank_overall['code'].map(rebaser)\n", " return stagerank_overall" ] }, { "cell_type": "code", "execution_count": 67, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
drivercodepositiontotalTimeMscode
28TÄN11474000SS3
29SUN21477500SS3
30NEU31478200SS3
31LAT41479400SS3
32OGI51483400SS3
33LAP61486500SS3
34MIK71488600SS3
35MEE81495600SS3
36LOE91509100SS3
37EVA101518000SS3
38TID111522600SS3
39TUO221585400SS3
40BER241607200SS3
41GRÖ251610400SS3
\n", "
" ], "text/plain": [ " drivercode position totalTimeMs code\n", "28 TÄN 1 1474000 SS3\n", "29 SUN 2 1477500 SS3\n", "30 NEU 3 1478200 SS3\n", "31 LAT 4 1479400 SS3\n", "32 OGI 5 1483400 SS3\n", "33 LAP 6 1486500 SS3\n", "34 MIK 7 1488600 SS3\n", "35 MEE 8 1495600 SS3\n", "36 LOE 9 1509100 SS3\n", "37 EVA 10 1518000 SS3\n", "38 TID 11 1522600 SS3\n", "39 TUO 22 1585400 SS3\n", "40 BER 24 1607200 SS3\n", "41 GRÖ 25 1610400 SS3" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "if __name__=='__main__':\n", " #Preview the stagerank_overall contents for a particular stage\n", " display(stagerank_overall[stagerank_overall['code']==ss][['drivercode','position','totalTimeMs','code']])" ] }, { "cell_type": "code", "execution_count": 68, "metadata": {}, "outputs": [], "source": [ "def rebased_stage_stagerank(conn,rally,ss,drivercode,rc='RC1',typ='overall'):\n", " ''' Calculate the rebased time for each driver, in a specified stage (ss),\n", " relative to a specified driver (drivercode).\n", " Returns columns: ['position','totalTimeMs','code','rebased','Overall Time']\n", " '''\n", " stagerank_overall = sr.getEnrichedStageRank(conn, rally, rc=rc, typ=typ)\n", " zz=rebaseOverallRallyTime(stagerank_overall, drivercode)#, ss)\n", " #Get the rebased times for a particular stage\n", " #The position corresponds to either overall or stage pos\n", " zz=zz[zz['code']==ss][['drivercode','position','totalTimeMs','code', 'rebased']].set_index('drivercode')\n", " #Scale down the time from milliseconds to seconds\n", " zz['Overall Time']=-zz['rebased']/1000\n", " return zz" ] }, { "cell_type": "code", "execution_count": 69, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
positiontotalTimeMscoderebasedOverall Time
drivercode
TÄN11474000SS3-94009.4
SUN21477500SS3-59005.9
NEU31478200SS3-52005.2
LAT41479400SS3-40004.0
OGI51483400SS300.0
LAP61486500SS33100-3.1
MIK71488600SS35200-5.2
MEE81495600SS312200-12.2
LOE91509100SS325700-25.7
EVA101518000SS334600-34.6
TID111522600SS339200-39.2
TUO221585400SS3102000-102.0
BER241607200SS3123800-123.8
GRÖ251610400SS3127000-127.0
\n", "
" ], "text/plain": [ " position totalTimeMs code rebased Overall Time\n", "drivercode \n", "TÄN 1 1474000 SS3 -9400 9.4\n", "SUN 2 1477500 SS3 -5900 5.9\n", "NEU 3 1478200 SS3 -5200 5.2\n", "LAT 4 1479400 SS3 -4000 4.0\n", "OGI 5 1483400 SS3 0 0.0\n", "LAP 6 1486500 SS3 3100 -3.1\n", "MIK 7 1488600 SS3 5200 -5.2\n", "MEE 8 1495600 SS3 12200 -12.2\n", "LOE 9 1509100 SS3 25700 -25.7\n", "EVA 10 1518000 SS3 34600 -34.6\n", "TID 11 1522600 SS3 39200 -39.2\n", "TUO 22 1585400 SS3 102000 -102.0\n", "BER 24 1607200 SS3 123800 -123.8\n", "GRÖ 25 1610400 SS3 127000 -127.0" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "if __name__=='__main__':\n", " zz=rebased_stage_stagerank(conn,rally,ss, drivercode, rc)\n", " display(zz)" ] }, { "cell_type": "code", "execution_count": 70, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Index(['diffFirst', 'diffFirstMs', 'diffPrev', 'diffPrevMs', 'entryId',\n", " 'penaltyTime', 'penaltyTimeMs', 'position', 'stageTime', 'stageTimeMs',\n", " 'totalTime', 'totalTimeMs', 'stageId', 'class', 'code', 'distance',\n", " 'name', 'snum', 'drivercode', 'entrant.name', 'classrank',\n", " 'gainedClassPos', 'gainedClassLead', 'classPosDiff', 'lostClassLead',\n", " 'retainedClassLead', 'gainedTime', 'gainedOverallPos',\n", " 'gainedOverallLead', 'overallPosDiff', 'lostOverallLead',\n", " 'retainedOverallLead', 'firstinarow'],\n", " dtype='object')" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "if __name__=='__main__':\n", " display(stagerank_overall.columns)" ] }, { "cell_type": "code", "execution_count": 71, "metadata": {}, "outputs": [], "source": [ "if __name__=='__main__':\n", " #Preview a long format dataframe describing position and stage code for a specified driver\n", " #This appears not be be referenced anywhere else in this notebook\n", " stagerank_stage = sr.getEnrichedStageRank(conn, rally, rc=rc, typ='stage')\n", " stagerank_stage[stagerank_stage['drivercode']==rebase][['position','code']]" ] }, { "cell_type": "code", "execution_count": 72, "metadata": {}, "outputs": [], "source": [ "if __name__=='__main__':\n", " sr.dbGetStageRank(conn, rally, rc, 'overall', stages='SS8').columns" ] }, { "cell_type": "raw", "metadata": {}, "source": [ "'elapsedDuration', 'elapsedDurationMs', 'entryId', 'splitDateTime',\n", " 'splitDateTimeLocal', 'splitPointId', 'splitPointTimeId',\n", " 'stageTimeDuration', 'stageTimeDurationMs', 'startDateTime',\n", " 'startDateTimeLocal', 'stageId', 'class', 'code', 'distance', 'name',\n", " 'drivercode', 'elapsedDurationS'" ] }, { "cell_type": "code", "execution_count": 73, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
drivercodeelapsedDurationSstartDateTimesection
0OGI194.22019-02-15T08:08:001
1OGI379.52019-02-15T08:08:002
2OGI450.62019-02-15T08:08:003
3OGI668.12019-02-15T08:08:004
65OGI774.52019-02-15T08:08:005
\n", "
" ], "text/plain": [ " drivercode elapsedDurationS startDateTime section\n", "0 OGI 194.2 2019-02-15T08:08:00 1\n", "1 OGI 379.5 2019-02-15T08:08:00 2\n", "2 OGI 450.6 2019-02-15T08:08:00 3\n", "3 OGI 668.1 2019-02-15T08:08:00 4\n", "65 OGI 774.5 2019-02-15T08:08:00 5" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "if __name__=='__main__':\n", " #If there are no splits, ssd.dbGetSplits should optionally get the overall times from elsewhere as a single split\n", " splits = ssd.dbGetSplits(conn,rally,ss,rc)#, forcesingle=True)\n", "\n", " elapseddurations=ssd.getElapsedDurations(splits)\n", " display(elapseddurations.head())" ] }, { "cell_type": "code", "execution_count": 74, "metadata": {}, "outputs": [], "source": [ "def getRoadPosition(conn,rally,rc='RC1',stages=None):\n", " ''' Get road position for each driver for a given stage.\n", " \n", " NOTE:\n", " The start time is only available from stages with split times recorded.\n", " We can't get road position for stages with no splits.\n", " \n", " '''\n", " \n", " #TO DO - this doesn't seem to work on stage with no splits?\n", " roadPos=sr.dbGetStageStart(conn, rally, rc, stages)\n", " roadPos=roadPos[['drivercode','startDateTime','startpos']]\n", " roadPos.columns=['drivercode','startDateTime','Road Position']\n", " roadPos = roadPos.set_index('drivercode')\n", " return roadPos\n" ] }, { "cell_type": "code", "execution_count": 75, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
startDateTimeRoad Position
drivercode
OGI2019-02-15T08:08:001
NEU2019-02-15T08:10:002
TÄN2019-02-15T08:12:003
MEE2019-02-15T08:14:004
LOE2019-02-15T08:16:005
LAT2019-02-15T08:18:006
SUN2019-02-15T08:20:007
TID2019-02-15T08:22:008
MIK2019-02-15T08:24:009
LAP2019-02-15T08:26:0010
EVA2019-02-15T08:28:0011
GRÖ2019-02-15T08:30:0012
BER2019-02-15T08:32:0013
TUO2019-02-15T08:34:0014
\n", "
" ], "text/plain": [ " startDateTime Road Position\n", "drivercode \n", "OGI 2019-02-15T08:08:00 1\n", "NEU 2019-02-15T08:10:00 2\n", "TÄN 2019-02-15T08:12:00 3\n", "MEE 2019-02-15T08:14:00 4\n", "LOE 2019-02-15T08:16:00 5\n", "LAT 2019-02-15T08:18:00 6\n", "SUN 2019-02-15T08:20:00 7\n", "TID 2019-02-15T08:22:00 8\n", "MIK 2019-02-15T08:24:00 9\n", "LAP 2019-02-15T08:26:00 10\n", "EVA 2019-02-15T08:28:00 11\n", "GRÖ 2019-02-15T08:30:00 12\n", "BER 2019-02-15T08:32:00 13\n", "TUO 2019-02-15T08:34:00 14" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "if __name__=='__main__':\n", " roadPos = getRoadPosition(conn,rally,rc,ss)\n", " display(roadPos)" ] }, { "cell_type": "raw", "metadata": {}, "source": [ "if __name__=='__main__':\n", " #Preview splits for a couple of drivers\n", " display(splits[splits['drivercode'].isin(['PAD','NEU'])])" ] }, { "cell_type": "code", "execution_count": 76, "metadata": {}, "outputs": [], "source": [ "def waypoint_rank(splitdurations, on='section',by='elapsedDurationS'):\n", " ''' Return rank at each waypoint. '''\n", " splitdurations['split_pos'] = splitdurations.groupby(on)[by].rank(method='min',na_option='keep')#.astype(int)\n", " \n", " #For diff to first, do we want first at each waypoint or first at end of stage?\n", " #Use diff to driver in first at each waypoint\n", " splitdurations['gapToStageLeader'] = splitdurations[by] - splitdurations.groupby(on)[by].transform('min')\n", " #For each group, rebase relative to that time\n", " return splitdurations\n" ] }, { "cell_type": "code", "execution_count": 77, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
drivercodeelapsedDurationSstartDateTimesectionrebasedsplit_posgapToStageLeader
0OGI194.22019-02-15T08:08:0010.07.02.2
1OGI379.52019-02-15T08:08:0020.07.05.7
2OGI450.62019-02-15T08:08:0030.07.05.1
3OGI668.12019-02-15T08:08:0040.07.08.6
65OGI774.52019-02-15T08:08:0050.07.07.5
\n", "
" ], "text/plain": [ " drivercode elapsedDurationS startDateTime section rebased \\\n", "0 OGI 194.2 2019-02-15T08:08:00 1 0.0 \n", "1 OGI 379.5 2019-02-15T08:08:00 2 0.0 \n", "2 OGI 450.6 2019-02-15T08:08:00 3 0.0 \n", "3 OGI 668.1 2019-02-15T08:08:00 4 0.0 \n", "65 OGI 774.5 2019-02-15T08:08:00 5 0.0 \n", "\n", " split_pos gapToStageLeader \n", "0 7.0 2.2 \n", "1 7.0 5.7 \n", "2 7.0 5.1 \n", "3 7.0 8.6 \n", "65 7.0 7.5 " ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "if __name__=='__main__':\n", " rebasedelapseddurations = ssd.rebaseElapsedDurations(elapseddurations, drivercode)\n", " #This returns columns of the form: drivercode\telapsedDurationS\tstartDateTime\tsection\trebased\n", " #If there are no splits, this is currently an empty dataframe\n", " rebasedelapseddurations = waypoint_rank(rebasedelapseddurations,by = 'elapsedDurationS')\n", " display(rebasedelapseddurations.head())" ] }, { "cell_type": "code", "execution_count": 78, "metadata": {}, "outputs": [], "source": [ "if __name__=='__main__':\n", " rebasedelapseddurations" ] }, { "cell_type": "code", "execution_count": 79, "metadata": {}, "outputs": [], "source": [ "from dakar_utils import sparklineStep, sparkline2, moveColumn\n", "\n", "def pivotRebasedElapsedDurations(rebasedelapseddurations, ss):\n", " ''' Pivot rebased elapsed durations (that is, deltas relative target).\n", " Rows give stage delta at each split for a specific driver.\n", " \n", " Returns columns of the form: ['1','2','3','SS9 Overall']\n", " '''\n", " if rebasedelapseddurations.empty:\n", " return pd.DataFrame(columns=['drivercode']).set_index('drivercode')\n", " \n", " rbe=-rebasedelapseddurations.pivot('drivercode','section','rebased')\n", " \n", " \n", " #TO DO: DRY stuff here - mungeForSparkLine function, maybe?\n", " #Add in a bar chart to identify evolving gap at each waypoint\n", " #Gap refers to the difference between driver\n", " col='Rebase Gap'\n", " rbe[col] = rbe[[c for c in rbe.columns ]].values.tolist()\n", " rbe[col] = rbe[col].apply(lambda x: [-y for y in x])\n", " rbe[col] = rbe[col].apply(sparkline2, typ='bar', dot=False)\n", " \n", " rbe.columns=list(rbe.columns)[:-2]+['{} Overall'.format(ss), 'Rebase Gap']\n", " rbe=rbe.sort_values(rbe.columns[-2],ascending = False)\n", " \n", " rbe2=rebasedelapseddurations.pivot('drivercode','section','split_pos')\n", " rbe2.columns=['{}_pos'.format(i) for i in rbe2.columns]\n", " col='Waypoint Rank'\n", " rbe2[col] = rbe2[[c for c in rbe2.columns ]].values.tolist()\n", " rbe2[col] = rbe2[col].apply(lambda x: [-y for y in x])\n", " rbe2[col] = rbe2[col].apply(sparklineStep)\n", " rbe = pd.merge(rbe,rbe2[col],left_index=True,right_index=True)\n", " \n", " rbe2=rebasedelapseddurations.pivot('drivercode','section','gapToStageLeader')\n", " rbe2.columns=['{}_pos'.format(i) for i in rbe2.columns]\n", " col='gapToStageLeader'\n", " rbe2[col] = rbe2[[c for c in rbe2.columns ]].values.tolist()\n", " rbe2[col] = rbe2[col].apply(lambda x: [-y for y in x])\n", " rbe2[col] = rbe2[col].apply(sparkline2, typ='bar', dot=True)\n", " rbe = pd.merge(rbe,rbe2[col],left_index=True,right_index=True)\n", "\n", " return rbe\n", "\n", "if __name__=='__main__':\n", " rbe = pivotRebasedElapsedDurations(rebasedelapseddurations, ss)" ] }, { "cell_type": "code", "execution_count": 80, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
1234SS3 OverallRebase GapWaypoint RankgapToStageLeader
drivercode
SUN2.25.75.18.67.5<img src=\"data:image/png;base64,iVBORw0KGgoAAA...<img src=\"data:image/png;base64,iVBORw0KGgoAAA...<img src=\"data:image/png;base64,iVBORw0KGgoAAA...
TÄN1.64.13.86.96.4<img src=\"data:image/png;base64,iVBORw0KGgoAAA...<img src=\"data:image/png;base64,iVBORw0KGgoAAA...<img src=\"data:image/png;base64,iVBORw0KGgoAAA...
NEU0.33.53.76.76.0<img src=\"data:image/png;base64,iVBORw0KGgoAAA...<img src=\"data:image/png;base64,iVBORw0KGgoAAA...<img src=\"data:image/png;base64,iVBORw0KGgoAAA...
LAT0.82.93.06.05.1<img src=\"data:image/png;base64,iVBORw0KGgoAAA...<img src=\"data:image/png;base64,iVBORw0KGgoAAA...<img src=\"data:image/png;base64,iVBORw0KGgoAAA...
LAP0.72.82.25.12.9<img src=\"data:image/png;base64,iVBORw0KGgoAAA...<img src=\"data:image/png;base64,iVBORw0KGgoAAA...<img src=\"data:image/png;base64,iVBORw0KGgoAAA...
MIK0.82.01.12.80.2<img src=\"data:image/png;base64,iVBORw0KGgoAAA...<img src=\"data:image/png;base64,iVBORw0KGgoAAA...<img src=\"data:image/png;base64,iVBORw0KGgoAAA...
OGI-0.0-0.0-0.0-0.0-0.0<img src=\"data:image/png;base64,iVBORw0KGgoAAA...<img src=\"data:image/png;base64,iVBORw0KGgoAAA...<img src=\"data:image/png;base64,iVBORw0KGgoAAA...
MEE-0.1-0.7-2.3-1.9-4.5<img src=\"data:image/png;base64,iVBORw0KGgoAAA...<img src=\"data:image/png;base64,iVBORw0KGgoAAA...<img src=\"data:image/png;base64,iVBORw0KGgoAAA...
LOE-1.6-2.2-3.0-3.9-6.6<img src=\"data:image/png;base64,iVBORw0KGgoAAA...<img src=\"data:image/png;base64,iVBORw0KGgoAAA...<img src=\"data:image/png;base64,iVBORw0KGgoAAA...
EVA-4.3-2.7-4.7-5.0-8.8<img src=\"data:image/png;base64,iVBORw0KGgoAAA...<img src=\"data:image/png;base64,iVBORw0KGgoAAA...<img src=\"data:image/png;base64,iVBORw0KGgoAAA...
TID-5.9-8.4-9.2-12.8-16.4<img src=\"data:image/png;base64,iVBORw0KGgoAAA...<img src=\"data:image/png;base64,iVBORw0KGgoAAA...<img src=\"data:image/png;base64,iVBORw0KGgoAAA...
TUO-10.3-17.7-22.7-33.7-41.5<img src=\"data:image/png;base64,iVBORw0KGgoAAA...<img src=\"data:image/png;base64,iVBORw0KGgoAAA...<img src=\"data:image/png;base64,iVBORw0KGgoAAA...
BER-10.0-18.1-21.4-60.4-68.5<img src=\"data:image/png;base64,iVBORw0KGgoAAA...<img src=\"data:image/png;base64,iVBORw0KGgoAAA...<img src=\"data:image/png;base64,iVBORw0KGgoAAA...
GRÖ-9.0-15.9-19.3-28.0-73.5<img src=\"data:image/png;base64,iVBORw0KGgoAAA...<img src=\"data:image/png;base64,iVBORw0KGgoAAA...<img src=\"data:image/png;base64,iVBORw0KGgoAAA...
\n", "
" ], "text/plain": [ " 1 2 3 4 SS3 Overall \\\n", "drivercode \n", "SUN 2.2 5.7 5.1 8.6 7.5 \n", "TÄN 1.6 4.1 3.8 6.9 6.4 \n", "NEU 0.3 3.5 3.7 6.7 6.0 \n", "LAT 0.8 2.9 3.0 6.0 5.1 \n", "LAP 0.7 2.8 2.2 5.1 2.9 \n", "MIK 0.8 2.0 1.1 2.8 0.2 \n", "OGI -0.0 -0.0 -0.0 -0.0 -0.0 \n", "MEE -0.1 -0.7 -2.3 -1.9 -4.5 \n", "LOE -1.6 -2.2 -3.0 -3.9 -6.6 \n", "EVA -4.3 -2.7 -4.7 -5.0 -8.8 \n", "TID -5.9 -8.4 -9.2 -12.8 -16.4 \n", "TUO -10.3 -17.7 -22.7 -33.7 -41.5 \n", "BER -10.0 -18.1 -21.4 -60.4 -68.5 \n", "GRÖ -9.0 -15.9 -19.3 -28.0 -73.5 \n", "\n", " Rebase Gap \\\n", "drivercode \n", "SUN 0 else 'black'\n", " else:\n", " color='white'\n", " return 'color: %s' % color" ] }, { "cell_type": "code", "execution_count": 82, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
1 2 3 4 SS3 Overall Rebase Gap Waypoint Rank gapToStageLeader
drivercode
SUN2.25.75.18.67.5
TÄN1.64.13.86.96.4
NEU0.33.53.76.76
LAT0.82.9365.1
LAP0.72.82.25.12.9
MIK0.821.12.80.2
OGI-0-0-0-0-0
MEE-0.1-0.7-2.3-1.9-4.5
LOE-1.6-2.2-3-3.9-6.6
EVA-4.3-2.7-4.7-5-8.8
TID-5.9-8.4-9.2-12.8-16.4
TUO-10.3-17.7-22.7-33.7-41.5
BER-10-18.1-21.4-60.4-68.5
GRÖ-9-15.9-19.3-28-73.5
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "if __name__=='__main__':\n", " #test of applying style to pandas dataframe\n", " #Is this really fown to pandas to fail gracefully if df is empty??\n", " s = rbe.style.applymap(color_negative)\n", " display(s)" ] }, { "cell_type": "code", "execution_count": 83, "metadata": {}, "outputs": [], "source": [ "# TO DO:\n", "# - calculate stage position at each split\n", "# - calculate rank within that sector" ] }, { "cell_type": "code", "execution_count": 84, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
drivercodesplitDurationSstartDateTimestageTimeDurationMssection
0OGI194.22019-02-15T08:08:00774500.01
1OGI185.32019-02-15T08:08:00774500.02
2OGI71.12019-02-15T08:08:00774500.03
3OGI217.52019-02-15T08:08:00774500.04
65OGI106.42019-02-15T08:08:00774500.05
4NEU193.92019-02-15T08:10:00768500.01
5NEU182.12019-02-15T08:10:00768500.02
6NEU70.92019-02-15T08:10:00768500.03
7NEU214.52019-02-15T08:10:00768500.04
64NEU107.12019-02-15T08:10:00768500.05
8TÄN192.62019-02-15T08:12:00768100.01
9TÄN182.82019-02-15T08:12:00768100.02
10TÄN71.42019-02-15T08:12:00768100.03
11TÄN214.42019-02-15T08:12:00768100.04
69TÄN106.92019-02-15T08:12:00768100.05
12MEE194.32019-02-15T08:14:00779000.01
13MEE185.92019-02-15T08:14:00779000.02
14MEE72.72019-02-15T08:14:00779000.03
15MEE217.12019-02-15T08:14:00779000.04
62MEE109.02019-02-15T08:14:00779000.05
16LOE195.82019-02-15T08:16:00781100.01
17LOE185.92019-02-15T08:16:00781100.02
18LOE71.92019-02-15T08:16:00781100.03
19LOE218.42019-02-15T08:16:00781100.04
61LOE109.12019-02-15T08:16:00781100.05
20LAT193.42019-02-15T08:18:00769400.01
21LAT183.22019-02-15T08:18:00769400.02
22LAT71.02019-02-15T08:18:00769400.03
23LAT214.52019-02-15T08:18:00769400.04
60LAT107.32019-02-15T08:18:00769400.05
..................
32MIK193.42019-02-15T08:24:00774300.01
33MIK184.12019-02-15T08:24:00774300.02
34MIK72.02019-02-15T08:24:00774300.03
35MIK215.82019-02-15T08:24:00774300.04
63MIK109.02019-02-15T08:24:00774300.05
36LAP193.52019-02-15T08:26:00771600.01
37LAP183.22019-02-15T08:26:00771600.02
38LAP71.72019-02-15T08:26:00771600.03
39LAP214.62019-02-15T08:26:00771600.04
59LAP108.62019-02-15T08:26:00771600.05
40EVA198.52019-02-15T08:28:00783300.01
41EVA183.72019-02-15T08:28:00783300.02
42EVA73.12019-02-15T08:28:00783300.03
43EVA217.82019-02-15T08:28:00783300.04
57EVA110.22019-02-15T08:28:00783300.05
44GRÖ203.22019-02-15T08:30:00848000.01
45GRÖ192.22019-02-15T08:30:00848000.02
46GRÖ74.52019-02-15T08:30:00848000.03
47GRÖ226.22019-02-15T08:30:00848000.04
58GRÖ151.92019-02-15T08:30:00848000.05
48BER204.22019-02-15T08:32:00843000.01
49BER193.42019-02-15T08:32:00843000.02
50BER74.42019-02-15T08:32:00843000.03
51BER256.52019-02-15T08:32:00843000.04
56BER114.52019-02-15T08:32:00843000.05
52TUO204.52019-02-15T08:34:00816000.01
53TUO192.72019-02-15T08:34:00816000.02
54TUO76.12019-02-15T08:34:00816000.03
55TUO228.52019-02-15T08:34:00816000.04
68TUO114.22019-02-15T08:34:00816000.05
\n", "

70 rows × 5 columns

\n", "
" ], "text/plain": [ " drivercode splitDurationS startDateTime stageTimeDurationMs \\\n", "0 OGI 194.2 2019-02-15T08:08:00 774500.0 \n", "1 OGI 185.3 2019-02-15T08:08:00 774500.0 \n", "2 OGI 71.1 2019-02-15T08:08:00 774500.0 \n", "3 OGI 217.5 2019-02-15T08:08:00 774500.0 \n", "65 OGI 106.4 2019-02-15T08:08:00 774500.0 \n", "4 NEU 193.9 2019-02-15T08:10:00 768500.0 \n", "5 NEU 182.1 2019-02-15T08:10:00 768500.0 \n", "6 NEU 70.9 2019-02-15T08:10:00 768500.0 \n", "7 NEU 214.5 2019-02-15T08:10:00 768500.0 \n", "64 NEU 107.1 2019-02-15T08:10:00 768500.0 \n", "8 TÄN 192.6 2019-02-15T08:12:00 768100.0 \n", "9 TÄN 182.8 2019-02-15T08:12:00 768100.0 \n", "10 TÄN 71.4 2019-02-15T08:12:00 768100.0 \n", "11 TÄN 214.4 2019-02-15T08:12:00 768100.0 \n", "69 TÄN 106.9 2019-02-15T08:12:00 768100.0 \n", "12 MEE 194.3 2019-02-15T08:14:00 779000.0 \n", "13 MEE 185.9 2019-02-15T08:14:00 779000.0 \n", "14 MEE 72.7 2019-02-15T08:14:00 779000.0 \n", "15 MEE 217.1 2019-02-15T08:14:00 779000.0 \n", "62 MEE 109.0 2019-02-15T08:14:00 779000.0 \n", "16 LOE 195.8 2019-02-15T08:16:00 781100.0 \n", "17 LOE 185.9 2019-02-15T08:16:00 781100.0 \n", "18 LOE 71.9 2019-02-15T08:16:00 781100.0 \n", "19 LOE 218.4 2019-02-15T08:16:00 781100.0 \n", "61 LOE 109.1 2019-02-15T08:16:00 781100.0 \n", "20 LAT 193.4 2019-02-15T08:18:00 769400.0 \n", "21 LAT 183.2 2019-02-15T08:18:00 769400.0 \n", "22 LAT 71.0 2019-02-15T08:18:00 769400.0 \n", "23 LAT 214.5 2019-02-15T08:18:00 769400.0 \n", "60 LAT 107.3 2019-02-15T08:18:00 769400.0 \n", ".. ... ... ... ... \n", "32 MIK 193.4 2019-02-15T08:24:00 774300.0 \n", "33 MIK 184.1 2019-02-15T08:24:00 774300.0 \n", "34 MIK 72.0 2019-02-15T08:24:00 774300.0 \n", "35 MIK 215.8 2019-02-15T08:24:00 774300.0 \n", "63 MIK 109.0 2019-02-15T08:24:00 774300.0 \n", "36 LAP 193.5 2019-02-15T08:26:00 771600.0 \n", "37 LAP 183.2 2019-02-15T08:26:00 771600.0 \n", "38 LAP 71.7 2019-02-15T08:26:00 771600.0 \n", "39 LAP 214.6 2019-02-15T08:26:00 771600.0 \n", "59 LAP 108.6 2019-02-15T08:26:00 771600.0 \n", "40 EVA 198.5 2019-02-15T08:28:00 783300.0 \n", "41 EVA 183.7 2019-02-15T08:28:00 783300.0 \n", "42 EVA 73.1 2019-02-15T08:28:00 783300.0 \n", "43 EVA 217.8 2019-02-15T08:28:00 783300.0 \n", "57 EVA 110.2 2019-02-15T08:28:00 783300.0 \n", "44 GRÖ 203.2 2019-02-15T08:30:00 848000.0 \n", "45 GRÖ 192.2 2019-02-15T08:30:00 848000.0 \n", "46 GRÖ 74.5 2019-02-15T08:30:00 848000.0 \n", "47 GRÖ 226.2 2019-02-15T08:30:00 848000.0 \n", "58 GRÖ 151.9 2019-02-15T08:30:00 848000.0 \n", "48 BER 204.2 2019-02-15T08:32:00 843000.0 \n", "49 BER 193.4 2019-02-15T08:32:00 843000.0 \n", "50 BER 74.4 2019-02-15T08:32:00 843000.0 \n", "51 BER 256.5 2019-02-15T08:32:00 843000.0 \n", "56 BER 114.5 2019-02-15T08:32:00 843000.0 \n", "52 TUO 204.5 2019-02-15T08:34:00 816000.0 \n", "53 TUO 192.7 2019-02-15T08:34:00 816000.0 \n", "54 TUO 76.1 2019-02-15T08:34:00 816000.0 \n", "55 TUO 228.5 2019-02-15T08:34:00 816000.0 \n", "68 TUO 114.2 2019-02-15T08:34:00 816000.0 \n", "\n", " section \n", "0 1 \n", "1 2 \n", "2 3 \n", "3 4 \n", "65 5 \n", "4 1 \n", "5 2 \n", "6 3 \n", "7 4 \n", "64 5 \n", "8 1 \n", "9 2 \n", "10 3 \n", "11 4 \n", "69 5 \n", "12 1 \n", "13 2 \n", "14 3 \n", "15 4 \n", "62 5 \n", "16 1 \n", "17 2 \n", "18 3 \n", "19 4 \n", "61 5 \n", "20 1 \n", "21 2 \n", "22 3 \n", "23 4 \n", "60 5 \n", ".. ... \n", "32 1 \n", "33 2 \n", "34 3 \n", "35 4 \n", "63 5 \n", "36 1 \n", "37 2 \n", "38 3 \n", "39 4 \n", "59 5 \n", "40 1 \n", "41 2 \n", "42 3 \n", "43 4 \n", "57 5 \n", "44 1 \n", "45 2 \n", "46 3 \n", "47 4 \n", "58 5 \n", "48 1 \n", "49 2 \n", "50 3 \n", "51 4 \n", "56 5 \n", "52 1 \n", "53 2 \n", "54 3 \n", "55 4 \n", "68 5 \n", "\n", "[70 rows x 5 columns]" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "if __name__=='__main__':\n", " #splitdurations are the time in each sector (time take to get from one split to the next)\n", " #But what if there are no splits? We get an empty dataframe...\n", " splitdurations = ssd.getSplitDurationsFromSplits(conn,rally,ss,rc)\n", " #splitdurations = waypoint_rank(splitdurations, 'section','stageTimeDurationMs' )\n", " display(splitdurations)#.head()" ] }, { "cell_type": "code", "execution_count": 85, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
drivercodesplitDurationSstartDateTimestageTimeDurationMssectionrebased
0OGI194.22019-02-15T08:08:00774500.010.0
1OGI185.32019-02-15T08:08:00774500.020.0
2OGI71.12019-02-15T08:08:00774500.030.0
3OGI217.52019-02-15T08:08:00774500.040.0
65OGI106.42019-02-15T08:08:00774500.050.0
\n", "
" ], "text/plain": [ " drivercode splitDurationS startDateTime stageTimeDurationMs \\\n", "0 OGI 194.2 2019-02-15T08:08:00 774500.0 \n", "1 OGI 185.3 2019-02-15T08:08:00 774500.0 \n", "2 OGI 71.1 2019-02-15T08:08:00 774500.0 \n", "3 OGI 217.5 2019-02-15T08:08:00 774500.0 \n", "65 OGI 106.4 2019-02-15T08:08:00 774500.0 \n", "\n", " section rebased \n", "0 1 0.0 \n", "1 2 0.0 \n", "2 3 0.0 \n", "3 4 0.0 \n", "65 5 0.0 " ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "if __name__=='__main__':\n", " #This will be an empty dataframe if there are no splits\n", " rebasedSplits = ssd.rebaseSplitDurations(splitdurations, drivercode)\n", " display(rebasedSplits.head())" ] }, { "cell_type": "code", "execution_count": 86, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
drivercodesplitDurationSstartDateTimestageTimeDurationMssectionrebased
4NEU193.92019-02-15T08:10:00768500.01-0.3
5NEU182.12019-02-15T08:10:00768500.02-3.2
6NEU70.92019-02-15T08:10:00768500.03-0.2
7NEU214.52019-02-15T08:10:00768500.04-3.0
64NEU107.12019-02-15T08:10:00768500.050.7
\n", "
" ], "text/plain": [ " drivercode splitDurationS startDateTime stageTimeDurationMs \\\n", "4 NEU 193.9 2019-02-15T08:10:00 768500.0 \n", "5 NEU 182.1 2019-02-15T08:10:00 768500.0 \n", "6 NEU 70.9 2019-02-15T08:10:00 768500.0 \n", "7 NEU 214.5 2019-02-15T08:10:00 768500.0 \n", "64 NEU 107.1 2019-02-15T08:10:00 768500.0 \n", "\n", " section rebased \n", "4 1 -0.3 \n", "5 2 -3.2 \n", "6 3 -0.2 \n", "7 4 -3.0 \n", "64 5 0.7 " ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "if __name__=='__main__':\n", " #preview what's available as a splitduration\n", " display(splitdurations[splitdurations['drivercode'].isin( ['PAD','NEU'])])" ] }, { "cell_type": "code", "execution_count": 87, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
D1D2D3D4D5
drivercode
BER-10.0-8.1-3.3-39.0-8.1
EVA-4.31.6-2.0-0.3-3.8
GRÖ-9.0-6.9-3.4-8.7-45.5
LAP0.72.1-0.62.9-2.2
LAT0.82.10.13.0-0.9
LOE-1.6-0.6-0.8-0.9-2.7
MEE-0.1-0.6-1.60.4-2.6
MIK0.81.2-0.91.7-2.6
NEU0.33.20.23.0-0.7
OGI-0.0-0.0-0.0-0.0-0.0
SUN2.23.5-0.63.5-1.1
TID-5.9-2.5-0.8-3.6-3.6
TUO-10.3-7.4-5.0-11.0-7.8
TÄN1.62.5-0.33.1-0.5
\n", "
" ], "text/plain": [ " D1 D2 D3 D4 D5\n", "drivercode \n", "BER -10.0 -8.1 -3.3 -39.0 -8.1\n", "EVA -4.3 1.6 -2.0 -0.3 -3.8\n", "GRÖ -9.0 -6.9 -3.4 -8.7 -45.5\n", "LAP 0.7 2.1 -0.6 2.9 -2.2\n", "LAT 0.8 2.1 0.1 3.0 -0.9\n", "LOE -1.6 -0.6 -0.8 -0.9 -2.7\n", "MEE -0.1 -0.6 -1.6 0.4 -2.6\n", "MIK 0.8 1.2 -0.9 1.7 -2.6\n", "NEU 0.3 3.2 0.2 3.0 -0.7\n", "OGI -0.0 -0.0 -0.0 -0.0 -0.0\n", "SUN 2.2 3.5 -0.6 3.5 -1.1\n", "TID -5.9 -2.5 -0.8 -3.6 -3.6\n", "TUO -10.3 -7.4 -5.0 -11.0 -7.8\n", "TÄN 1.6 2.5 -0.3 3.1 -0.5" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "def pivotRebasedSplits(rebasedSplits):\n", " ''' For each driver row, find the split. '''\n", " \n", " #If there are no splits...\n", " if rebasedSplits.empty:\n", " return pd.DataFrame(columns=['drivercode']).set_index('drivercode')\n", " \n", " rbp=-rebasedSplits.pivot('drivercode','section','rebased')\n", " rbp.columns=['D{}'.format(c) for c in rbp.columns]\n", " rbp.sort_values(rbp.columns[-1],ascending =True)\n", " return rbp\n", "\n", "if __name__=='__main__':\n", " rbp = pivotRebasedSplits(rebasedSplits)\n", " display(rbp)" ] }, { "cell_type": "code", "execution_count": 88, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
startDateTimeRoad Position
drivercode
OGI2019-02-15T08:08:001
NEU2019-02-15T08:10:002
TÄN2019-02-15T08:12:003
MEE2019-02-15T08:14:004
LOE2019-02-15T08:16:005
LAT2019-02-15T08:18:006
SUN2019-02-15T08:20:007
TID2019-02-15T08:22:008
MIK2019-02-15T08:24:009
LAP2019-02-15T08:26:0010
EVA2019-02-15T08:28:0011
GRÖ2019-02-15T08:30:0012
BER2019-02-15T08:32:0013
TUO2019-02-15T08:34:0014
\n", "
" ], "text/plain": [ " startDateTime Road Position\n", "drivercode \n", "OGI 2019-02-15T08:08:00 1\n", "NEU 2019-02-15T08:10:00 2\n", "TÄN 2019-02-15T08:12:00 3\n", "MEE 2019-02-15T08:14:00 4\n", "LOE 2019-02-15T08:16:00 5\n", "LAT 2019-02-15T08:18:00 6\n", "SUN 2019-02-15T08:20:00 7\n", "TID 2019-02-15T08:22:00 8\n", "MIK 2019-02-15T08:24:00 9\n", "LAP 2019-02-15T08:26:00 10\n", "EVA 2019-02-15T08:28:00 11\n", "GRÖ 2019-02-15T08:30:00 12\n", "BER 2019-02-15T08:32:00 13\n", "TUO 2019-02-15T08:34:00 14" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "if __name__=='__main__':\n", " #Just remind ourselves of what is available in the road position data\n", " display(roadPos)" ] }, { "cell_type": "code", "execution_count": 89, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Road PositionPreviousWaypoint RankRebase Gap1234SS3 OverallStage RankOverall PositionOverall TimegapToStageLeaderD1D2D3D4D5
drivercode
SUN7-1.6<img src=\"data:image/png;base64,iVBORw0KGgoAAA...<img src=\"data:image/png;base64,iVBORw0KGgoAAA...2.25.75.18.67.5125.9<img src=\"data:image/png;base64,iVBORw0KGgoAAA...2.23.5-0.63.5-1.1
TÄN33.0<img src=\"data:image/png;base64,iVBORw0KGgoAAA...<img src=\"data:image/png;base64,iVBORw0KGgoAAA...1.64.13.86.96.4219.4<img src=\"data:image/png;base64,iVBORw0KGgoAAA...1.62.5-0.33.1-0.5
NEU2-0.8<img src=\"data:image/png;base64,iVBORw0KGgoAAA...<img src=\"data:image/png;base64,iVBORw0KGgoAAA...0.33.53.76.76.0335.2<img src=\"data:image/png;base64,iVBORw0KGgoAAA...0.33.20.23.0-0.7
LAT6-1.1<img src=\"data:image/png;base64,iVBORw0KGgoAAA...<img src=\"data:image/png;base64,iVBORw0KGgoAAA...0.82.93.06.05.1444.0<img src=\"data:image/png;base64,iVBORw0KGgoAAA...0.82.10.13.0-0.9
LAP10-6.0<img src=\"data:image/png;base64,iVBORw0KGgoAAA...<img src=\"data:image/png;base64,iVBORw0KGgoAAA...0.72.82.25.12.956-3.1<img src=\"data:image/png;base64,iVBORw0KGgoAAA...0.72.1-0.62.9-2.2
MIK9-5.4<img src=\"data:image/png;base64,iVBORw0KGgoAAA...<img src=\"data:image/png;base64,iVBORw0KGgoAAA...0.82.01.12.80.267-5.2<img src=\"data:image/png;base64,iVBORw0KGgoAAA...0.81.2-0.91.7-2.6
OGI10.0<img src=\"data:image/png;base64,iVBORw0KGgoAAA...<img src=\"data:image/png;base64,iVBORw0KGgoAAA...-0.0-0.0-0.0-0.0-0.0750.0<img src=\"data:image/png;base64,iVBORw0KGgoAAA...-0.0-0.0-0.0-0.0-0.0
MEE4-7.7<img src=\"data:image/png;base64,iVBORw0KGgoAAA...<img src=\"data:image/png;base64,iVBORw0KGgoAAA...-0.1-0.7-2.3-1.9-4.588-12.2<img src=\"data:image/png;base64,iVBORw0KGgoAAA...-0.1-0.6-1.60.4-2.6
LOE5-19.1<img src=\"data:image/png;base64,iVBORw0KGgoAAA...<img src=\"data:image/png;base64,iVBORw0KGgoAAA...-1.6-2.2-3.0-3.9-6.699-25.7<img src=\"data:image/png;base64,iVBORw0KGgoAAA...-1.6-0.6-0.8-0.9-2.7
EVA11-25.8<img src=\"data:image/png;base64,iVBORw0KGgoAAA...<img src=\"data:image/png;base64,iVBORw0KGgoAAA...-4.3-2.7-4.7-5.0-8.81010-34.6<img src=\"data:image/png;base64,iVBORw0KGgoAAA...-4.31.6-2.0-0.3-3.8
TID8-22.8<img src=\"data:image/png;base64,iVBORw0KGgoAAA...<img src=\"data:image/png;base64,iVBORw0KGgoAAA...-5.9-8.4-9.2-12.8-16.41111-39.2<img src=\"data:image/png;base64,iVBORw0KGgoAAA...-5.9-2.5-0.8-3.6-3.6
TUO14-60.5<img src=\"data:image/png;base64,iVBORw0KGgoAAA...<img src=\"data:image/png;base64,iVBORw0KGgoAAA...-10.3-17.7-22.7-33.7-41.51822-102.0<img src=\"data:image/png;base64,iVBORw0KGgoAAA...-10.3-7.4-5.0-11.0-7.8
BER13-55.3<img src=\"data:image/png;base64,iVBORw0KGgoAAA...<img src=\"data:image/png;base64,iVBORw0KGgoAAA...-10.0-18.1-21.4-60.4-68.52624-123.8<img src=\"data:image/png;base64,iVBORw0KGgoAAA...-10.0-8.1-3.3-39.0-8.1
GRÖ12-53.5<img src=\"data:image/png;base64,iVBORw0KGgoAAA...<img src=\"data:image/png;base64,iVBORw0KGgoAAA...-9.0-15.9-19.3-28.0-73.52925-127.0<img src=\"data:image/png;base64,iVBORw0KGgoAAA...-9.0-6.9-3.4-8.7-45.5
\n", "
" ], "text/plain": [ " Road Position Previous \\\n", "drivercode \n", "SUN 7 -1.6 \n", "TÄN 3 3.0 \n", "NEU 2 -0.8 \n", "LAT 6 -1.1 \n", "LAP 10 -6.0 \n", "MIK 9 -5.4 \n", "OGI 1 0.0 \n", "MEE 4 -7.7 \n", "LOE 5 -19.1 \n", "EVA 11 -25.8 \n", "TID 8 -22.8 \n", "TUO 14 -60.5 \n", "BER 13 -55.3 \n", "GRÖ 12 -53.5 \n", "\n", " Waypoint Rank \\\n", "drivercode \n", "SUN \n", " #T_76386a6e_3292_11e9_896f_645aede917f3row0_col4 {\n", " color: red;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row0_col5 {\n", " color: red;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row0_col6 {\n", " color: red;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row0_col7 {\n", " color: red;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row1_col4 {\n", " color: red;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row1_col5 {\n", " color: red;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row1_col6 {\n", " color: red;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row1_col7 {\n", " color: red;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row2_col4 {\n", " color: red;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row2_col5 {\n", " color: red;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row2_col6 {\n", " color: red;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row2_col7 {\n", " color: red;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row3_col4 {\n", " color: red;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row3_col5 {\n", " color: red;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row3_col6 {\n", " color: red;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row3_col7 {\n", " color: red;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row4_col4 {\n", " color: red;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row4_col5 {\n", " color: red;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row4_col6 {\n", " color: red;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row4_col7 {\n", " color: red;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row5_col4 {\n", " color: red;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row5_col5 {\n", " color: red;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row5_col6 {\n", " color: red;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row5_col7 {\n", " color: red;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row7_col4 {\n", " color: green;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row7_col5 {\n", " color: green;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row7_col6 {\n", " color: green;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row7_col7 {\n", " color: green;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row8_col4 {\n", " color: green;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row8_col5 {\n", " color: green;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row8_col6 {\n", " color: green;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row8_col7 {\n", " color: green;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row9_col4 {\n", " color: green;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row9_col5 {\n", " color: green;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row9_col6 {\n", " color: green;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row9_col7 {\n", " color: green;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row10_col4 {\n", " color: green;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row10_col5 {\n", " color: green;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row10_col6 {\n", " color: green;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row10_col7 {\n", " color: green;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row11_col4 {\n", " color: green;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row11_col5 {\n", " color: green;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row11_col6 {\n", " color: green;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row11_col7 {\n", " color: green;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row12_col4 {\n", " color: green;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row12_col5 {\n", " color: green;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row12_col6 {\n", " color: green;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row12_col7 {\n", " color: green;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row13_col4 {\n", " color: green;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row13_col5 {\n", " color: green;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row13_col6 {\n", " color: green;\n", " } #T_76386a6e_3292_11e9_896f_645aede917f3row13_col7 {\n", " color: green;\n", " }\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
SS3: running split times and deltas within each split.
Road Position Previous Waypoint Rank Rebase Gap 1 2 3 4 SS3 Overall Stage Rank Overall Position Overall Time gapToStageLeader D1 D2 D3 D4 D5
drivercode
SUN7-1.62.25.75.18.67.5125.92.23.5-0.63.5-1.1
TÄN331.64.13.86.96.4219.41.62.5-0.33.1-0.5
NEU2-0.80.33.53.76.76335.20.33.20.23-0.7
LAT6-1.10.82.9365.14440.82.10.13-0.9
LAP10-60.72.82.25.12.956-3.10.72.1-0.62.9-2.2
MIK9-5.40.821.12.80.267-5.20.81.2-0.91.7-2.6
OGI175
MEE4-7.7-0.1-0.7-2.3-1.9-4.588-12.2-0.1-0.6-1.60.4-2.6
LOE5-19.1-1.6-2.2-3-3.9-6.699-25.7-1.6-0.6-0.8-0.9-2.7
EVA11-25.8-4.3-2.7-4.7-5-8.81010-34.6-4.31.6-2-0.3-3.8
TID8-22.8-5.9-8.4-9.2-12.8-16.41111-39.2-5.9-2.5-0.8-3.6-3.6
TUO14-60.5-10.3-17.7-22.7-33.7-41.51822-102-10.3-7.4-5-11-7.8
BER13-55.3-10-18.1-21.4-60.4-68.52624-123.8-10-8.1-3.3-39-8.1
GRÖ12-53.5-9-15.9-19.3-28-73.52925-127-9-6.9-3.4-8.7-45.5
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from IPython.core.display import HTML\n", "\n", "if __name__=='__main__':\n", " html=s.render()\n", " display(HTML(html))" ] }, { "cell_type": "code", "execution_count": 93, "metadata": {}, "outputs": [], "source": [ "from math import nan\n", "def bg_color(s):\n", " ''' Set background colour sensitive to time gained or lost.\n", " '''\n", " attrs=[]\n", " for _s in s:\n", " if _s < 0:\n", " attr = 'background-color: green; color: white'\n", " elif _s > 0: \n", " attr = 'background-color: red; color: white'\n", " else:\n", " attr = ''\n", " attrs.append(attr)\n", " return attrs" ] }, { "cell_type": "code", "execution_count": 94, "metadata": { "scrolled": false }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Road Position Previous Waypoint Rank Rebase Gap 1 2 3 4 SS3 Overall Stage Rank Overall Position Overall Time gapToStageLeader D1 D2 D3 D4 D5
drivercode
SUN7-1.62.25.75.18.67.5125.92.23.5-0.63.5-1.1
TÄN331.64.13.86.96.4219.41.62.5-0.33.1-0.5
NEU2-0.80.33.53.76.76335.20.33.20.23-0.7
LAT6-1.10.82.9365.14440.82.10.13-0.9
LAP10-60.72.82.25.12.956-3.10.72.1-0.62.9-2.2
MIK9-5.40.821.12.80.267-5.20.81.2-0.91.7-2.6
OGI175
MEE4-7.7-0.1-0.7-2.3-1.9-4.588-12.2-0.1-0.6-1.60.4-2.6
LOE5-19.1-1.6-2.2-3-3.9-6.699-25.7-1.6-0.6-0.8-0.9-2.7
EVA11-25.8-4.3-2.7-4.7-5-8.81010-34.6-4.31.6-2-0.3-3.8
TID8-22.8-5.9-8.4-9.2-12.8-16.41111-39.2-5.9-2.5-0.8-3.6-3.6
TUO14-60.5-10.3-17.7-22.7-33.7-41.51822-102-10.3-7.4-5-11-7.8
BER13-55.3-10-18.1-21.4-60.4-68.52624-123.8-10-8.1-3.3-39-8.1
GRÖ12-53.5-9-15.9-19.3-28-73.52925-127-9-6.9-3.4-8.7-45.5
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import seaborn as sns\n", "\n", "def moreStyleDriverSplitReportBaseDataframe(rb2,ss, caption=None):\n", " ''' Style the driver split report dataframe. '''\n", " \n", " if rb2.empty: return ''\n", " \n", " def _subsetter(cols, items):\n", " ''' Generate a subset of valid columns from a list. '''\n", " return [c for c in cols if c in items]\n", " \n", " \n", " #https://community.modeanalytics.com/gallery/python_dataframe_styling/\n", " # Set CSS properties for th elements in dataframe\n", " th_props = [\n", " ('font-size', '11px'),\n", " ('text-align', 'center'),\n", " ('font-weight', 'bold'),\n", " ('color', '#6d6d6d'),\n", " ('background-color', '#f7f7f9')\n", " ]\n", "\n", " # Set CSS properties for td elements in dataframe\n", " td_props = [\n", " ('font-size', '11px')\n", " ]\n", "\n", " # Set table styles\n", " styles = [\n", " dict(selector=\"th\", props=th_props),\n", " dict(selector=\"td\", props=td_props)\n", " ]\n", " \n", " #Define colour palettes\n", " #cmg = sns.light_palette(\"green\", as_cmap=True)\n", " #The blue palette helps us scale the Road Position column\n", " # This may help us to help identify any obvious road position effect when sorting stage times by stage rank\n", " cm=sns.light_palette((210, 90, 60), input=\"husl\",as_cmap=True)\n", "\n", " s2=(rb2.style\n", " .background_gradient(cmap=cm, subset=_subsetter(rb2.columns, ['Road Position']))\n", " .applymap(color_negative,\n", " subset=[c for c in rb2.columns if isinstance(c, int) and c not in ['Overall Position', 'Road Position']])\n", " .highlight_min(subset=_subsetter(rb2.columns, ['Overall Position']), color='lightgrey')\n", " .highlight_max(subset=_subsetter(rb2.columns, ['Overall Time']), color='lightgrey')\n", " .highlight_max(subset=_subsetter(rb2.columns, ['Previous']), color='lightgrey')\n", " .apply(bg_color,subset=_subsetter(rb2.columns, ['{} Overall'.format(ss),'{} Overall*'.format(ss), 'Overall Time', 'Previous']))\n", " .bar(subset=[c for c in rb2.columns if str(c).startswith('D')], align='zero', color=[ '#5fba7d','#d65f5f'])\n", " .set_table_styles(styles)\n", " \n", " #.format({'total_amt_usd_pct_diff': \"{:.2%}\"})\n", " )\n", " \n", " if caption is not None:\n", " s2.set_caption(caption)\n", "\n", " #nan issue: https://github.com/pandas-dev/pandas/issues/21527\n", " return s2.render().replace('nan','')\n", "\n", "if __name__=='__main__':\n", " rb2c = cleanDriverSplitReportBaseDataframe(rb2.copy(), ss)\n", " s2 = moreStyleDriverSplitReportBaseDataframe(rb2c, ss)\n", " display(HTML(s2))" ] }, { "cell_type": "code", "execution_count": 95, "metadata": {}, "outputs": [], "source": [ "if __name__=='__main__':\n", " sr.dbGetStageRank(conn, rally, rc, typ='stage', stages=ss)[['position','drivercode','classrank']]\n", "#'overall':'stage_times_overall', 'stage_times_overall':'stage_times_overall',\n", "# 'stage':'stage_times_stage', 'stage_times_stage':'stage_times_stage'\n", "#sr.getEnrichedStageRank(conn, rally, typ=typ)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": 96, "metadata": {}, "outputs": [], "source": [ "if __name__=='__main__':\n", " sr.getDriverCodeBy(conn, rally, ss,'stage')" ] }, { "cell_type": "code", "execution_count": 97, "metadata": {}, "outputs": [], "source": [ "if __name__=='__main__':\n", " ss" ] }, { "cell_type": "code", "execution_count": 98, "metadata": {}, "outputs": [], "source": [ "if __name__=='__main__':\n", " sr.getEnrichedStageRank(conn, rally, stages=ss,rc=rc,typ='stage')" ] }, { "cell_type": "code", "execution_count": 99, "metadata": {}, "outputs": [], "source": [ "if __name__=='__main__':\n", " rebased_stage_stagerank(conn,rally,ss,drivercode,rc=rc, typ='overall')" ] }, { "cell_type": "code", "execution_count": 100, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Previous Stage Rank SS3 Time SS3 Overall Overall Position Overall Time
drivercode
TÄN3200:12:48.106.419.4
SUN-1.6100:12:477.525.9
NEU-0.8300:12:48.50635.2
LAT-1.1400:12:49.405.144
OGI700:12:54.505
LAP-6500:12:51.602.96-3.1
MIK-5.4600:12:54.300.27-5.2
MEE-7.7800:12:59-4.58-12.2
LOE-19.1900:13:01.10-6.69-25.7
EVA-25.81000:13:03.30-8.810-34.6
TID-22.81100:13:10.90-16.411-39.2
TUO-60.51800:13:36-41.522-102
BER-55.32600:14:03-68.524-123.8
GRÖ-53.52900:14:08-73.525-127
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "def getDriverStageReport(conn, rally, ss, drivercode, rc='RC1', typ='overall', order=None, caption=None):\n", " ''' Generate a dataframe to report overall stage result. '''\n", " #'Previous',' SS9 Overall', 'Overall Position'\t'Overall Time'; stage position by sort order\n", " \n", " if order is None: order='stage'\n", " #change cols depending on what report / sort order ie. remove redundant col\n", " \n", " #Get the overall results, rebased\n", " zz = rebased_stage_stagerank(conn,rally,ss,drivercode,rc=rc, typ='overall')\n", " zz.rename(columns={'position':'Overall Position'}, inplace=True)\n", " \n", " #Get stage result - does it need to be enriched?\n", " stageresult=sr.getEnrichedStageRank(conn, rally, stages=ss,rc=rc, typ='stage')\n", "\n", " stagerebaser = stageresult[stageresult['drivercode']==drivercode][['code','elapsedDurationMs']].set_index('code').to_dict(orient='dict')['elapsedDurationMs']\n", " #The stagerank_overall['code'].map(rebaser) returns the total time for each stage achieved by the rebase driver\n", " # stagerank_overall['code'] identifies the stage\n", " #Subtract this rebase time from the overall stage time for each driver by stage\n", "\n", " stcol='{} Time'.format(ss)\n", " sdeltacol='{} Overall'.format(ss)\n", " stageresult[sdeltacol] = -(stageresult['elapsedDurationMs'] - stageresult['code'].map(stagerebaser))\n", " stageresult=stageresult[['drivercode', 'position','elapsedDuration', sdeltacol,'elapsedDurationMs']]\n", " stageresult.columns=['drivercode', 'Stage Rank',stcol, sdeltacol,'stageDurationMs']\n", " stageresult[stcol] = stageresult[stcol].str.replace('00000','')\n", " \n", " combined = pd.merge(zz,stageresult, on='drivercode' )\n", " \n", " combined[sdeltacol] = combined[sdeltacol]/1000\n", " combined['Previous'] = (combined['Overall Time']-combined[sdeltacol])\n", " \n", " _tmp=combined[['drivercode','Previous','Stage Rank',stcol,sdeltacol,'Overall Position','Overall Time']].replace(0,NaN).set_index('drivercode')\n", "\n", " if order=='overall':\n", " combined=combined.sort_values('Overall Position', ascending=True)\n", " elif order=='previous':\n", " combined=combined.fillna(0).sort_values('Previous', ascending=False).replace(0,NaN)\n", " elif order=='stage':\n", " combined=combined.sort_values('Stage Rank', ascending=True)\n", " else:\n", " #Default is stage order\n", " combined=combined.sort_values('Stage Rank', ascending=True)\n", " \n", " s2 = moreStyleDriverSplitReportBaseDataframe(_tmp, ss, caption)\n", " return s2\n", "\n", "if __name__=='__main__':\n", " s2=getDriverStageReport(conn, rally, ss, drivercode)\n", " display(HTML(s2))" ] }, { "cell_type": "code", "execution_count": 101, "metadata": { "scrolled": false }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Road Position Previous Waypoint Rank Rebase Gap 1 2 3 4 SS3 Overall* Overall Position Overall Time gapToStageLeader D1 D2 D3 D4 D5
drivercode
SUN7-1.62.25.75.18.67.525.92.23.5-0.63.5-1.1
TÄN331.64.13.86.96.419.41.62.5-0.33.1-0.5
NEU2-0.80.33.53.76.7635.20.33.20.23-0.7
LAT6-1.10.82.9365.1440.82.10.13-0.9
LAP10-60.72.82.25.12.96-3.10.72.1-0.62.9-2.2
MIK9-5.40.821.12.80.27-5.20.81.2-0.91.7-2.6
OGI15
MEE4-7.7-0.1-0.7-2.3-1.9-4.58-12.2-0.1-0.6-1.60.4-2.6
LOE5-19.1-1.6-2.2-3-3.9-6.69-25.7-1.6-0.6-0.8-0.9-2.7
EVA11-25.8-4.3-2.7-4.7-5-8.810-34.6-4.31.6-2-0.3-3.8
TID8-22.8-5.9-8.4-9.2-12.8-16.411-39.2-5.9-2.5-0.8-3.6-3.6
TUO14-60.5-10.3-17.7-22.7-33.7-41.522-102-10.3-7.4-5-11-7.8
BER13-55.3-10-18.1-21.4-60.4-68.524-123.8-10-8.1-3.3-39-8.1
GRÖ12-53.5-9-15.9-19.3-28-73.525-127-9-6.9-3.4-8.7-45.5
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "def getDriverSplitsReport(conn, rally, ss, drivercode, rc='RC1', typ='overall', \n", " order=None, caption=None, bars=True, dropcols=None):\n", " ''' Generate dataframe report relative to a given driver on a given stage.\n", " order: sorts table according to: overall | previous | roadpos\n", " \n", " At the moment, the splits reporter doesn't report anything if there are no splits.\n", " In this case, default to a simple overal stage (without splits) reporter table.\n", " '''\n", " \n", " dropcols = [] if dropcols is None else dropcols\n", " #TO DO - this needs to fail gracefully if there are no splits\n", " \n", " #Allow the drivercode to be relative to a position\n", " #if drivercode=='firstonroad':\n", " #allow things like onroad1, onroad2?\n", " # drivercode=\n", " #elif drivercode=='previousfirst':\n", " #allow things like previous1, previous2?\n", " # drivercode = \n", " #elif drivercode = 'stagewinner':\n", " #allowthings like stage1, stage2?\n", " # drivercode = \n", " \n", " \n", " #Get the overall results, rebased\n", " zz = rebased_stage_stagerank(conn,rally,ss,drivercode,rc=rc, typ=typ)\n", " \n", " #Get the road position\n", " roadPos = getRoadPosition(conn,rally,rc,ss)\n", " if roadPos.empty:\n", " #Should we automatically offer the stagetable report as an alternative\n", " return getDriverStageReport(conn, rally, ss, drivercode, rc=rc, order=order, caption=caption)\n", " \n", " #Get the splits\n", " splits = ssd.dbGetSplits(conn,rally,ss,rc)\n", " elapseddurations=ssd.getElapsedDurations(splits)\n", " \n", " #Rebase the split elapsed durations\n", " rebasedelapseddurations = ssd.rebaseElapsedDurations(elapseddurations, drivercode)\n", " rebasedelapseddurations = waypoint_rank(rebasedelapseddurations,by = 'elapsedDurationS')\n", " rbe = pivotRebasedElapsedDurations(rebasedelapseddurations, ss)\n", " \n", " #splitdurations are the time in each sector (time take to get from one split to the next)\n", " splitdurations = ssd.getSplitDurationsFromSplits(conn,rally,ss,rc)\n", " rebasedSplits = ssd.rebaseSplitDurations(splitdurations, drivercode)\n", "\n", " rbp = pivotRebasedSplits(rebasedSplits)\n", "\n", " #Get stage result to merge in stage position\n", " stageresult=sr.getEnrichedStageRank(conn, rally, rc=rc, stages=ss,typ='stage')[['drivercode','position']]\n", "\n", " rb2=getDriverSplitReportBaseDataframe(rbe, rbp, zz, roadPos, stageresult, ss)\n", " rb2 = cleanDriverSplitReportBaseDataframe(rb2, ss)\n", " if not bars:\n", " rb2=rb2.drop([c for c in rb2.columns if str(c).startswith('D')], axis=1)\n", " \n", " if ss=='SS1':\n", " rb2['Previous']=NaN\n", "\n", " if order=='overall':\n", " rb2=rb2.sort_values('Overall Position', ascending=True)\n", " #Remove the redundant column\n", " rb2=rb2.drop(['Overall Position'], axis=1)\n", " #rb2=rb2.rename(columns={'Overall Position':'{} Overall*'.format(ss)})\n", " elif order=='previous':\n", " rb2=rb2.fillna(0).sort_values('Previous', ascending=False).replace(0,NaN)\n", " #rb2 = rb2.rename(columns={'Previous':'Previous*'})\n", " elif order=='roadpos':\n", " rb2=rb2.sort_values('Road Position', ascending=True)\n", " #rb2 = rb2.rename(columns={'Road Position':'Road Position*'})\n", " elif order=='stage':\n", " rb2.sort_values('Stage Rank', ascending=True)\n", " #Remove the redundant column\n", " rb2=rb2.drop(['Stage Rank'], axis=1)\n", " else:\n", " #Default is stage order\n", " rb2.sort_values('Stage Rank', ascending=True)\n", " #Remove the redundant column\n", " rb2=rb2.drop(['Stage Rank'], axis=1)\n", " rb2 = rb2.rename(columns={'{} Overall'.format(ss):'{} Overall*'.format(ss)})\n", "\n", " if caption =='auto':\n", " caption = 'Rebased stage split times for {}{}.'.format('{}, '.format(drivercode), ss)\n", "\n", " dc = [c for c in dropcols if c in rb2.columns]\n", " rb2 = rb2.drop(columns=dc)\n", " \n", " #s = styleDriverSplitReportBaseDataframe(rb2, ss)\n", " s2 = moreStyleDriverSplitReportBaseDataframe(rb2,ss, caption)\n", " return s2\n", "\n", "if __name__=='__main__':\n", " s2 = getDriverSplitsReport(conn, rally, ss, drivercode, rc, typ)#, caption='auto')\n", " display(HTML(s2))" ] }, { "cell_type": "code", "execution_count": 114, "metadata": { "scrolled": false }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Road Position Previous Waypoint Rank Rebase Gap 1 2 SS19 Overall* Overall Position Overall Time gapToStageLeader D1 D2 D3
drivercode
TÄN131
NEU11-53.1-2-2.9-3.63-56.7-2-0.9-0.7
EVA9-63.7-2.5-4-4.55-68.2-2.5-1.5-0.5
OGI2-1454.3-0.5-3.2-4.716-1459-0.5-2.7-1.4
LAP12-48.7-4.5-7-52-53.7-4.5-2.52.1
MEE8-93.6-2.5-4.3-5.26-98.8-2.5-1.8-0.9
LAT4-878.6-4.1-4.4-5.814-884.4-4.1-0.3-1.4
LOE7-102.8-2.8-5.3-6.97-109.7-2.8-2.5-1.6
MIK10-57.3-3.6-6.5-8.14-65.4-3.6-2.9-1.6
SUN3-976.2-2.6-5.7-8.315-984.5-2.6-3.1-2.6
TID6-204.7-8.8-11.4-138-217.7-8.8-2.6-1.6
GRÖ1-2529.6-9-13.4-17.517-2547.1-9-4.4-4.1
BER5-784.4-13.3-17.9-20.913-805.3-13.3-4.6-3
TUO14-480.5-13.4-17.9-20.99-501.4-13.4-4.4-3
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "if __name__=='__main__':\n", " ss='SS19'\n", " d='TÄN'\n", " s2 = getDriverSplitsReport(conn, rally, ss, d, rc, typ)\n", " display(HTML(s2))" ] }, { "cell_type": "raw", "metadata": {}, "source": [ "if __name__=='__main__':\n", " s2 = getDriverSplitsReport(conn, rally, 'SS3', 'LAT', rc, typ, 'overall')\n", " display(HTML(s2))" ] }, { "cell_type": "raw", "metadata": {}, "source": [ "if __name__=='__main__':\n", " s2 = getDriverSplitsReport(conn, rally, 'SS11', 'PAD', rc, typ, 'previous')\n", " display(HTML(s2))" ] }, { "cell_type": "raw", "metadata": {}, "source": [ "#Replace by Dakar tools\n", "import os\n", "import time\n", "from selenium import webdriver\n", "\n", "\n", "def getTableImage(url, fn='dummy_table', basepath='.', path='.', delay=5, height=420, width=800):\n", " ''' Render HTML file in browser and grab a screenshot. '''\n", " #should be a tmp file?\n", " #fname='testmap.html'\n", " #tmpurl='file://{path}/{mapfile}'.format(path=os.getcwd(),mapfile=fn)\n", " #folium_map.save(fn)\n", " browser = webdriver.Chrome()\n", " browser.set_window_size(width, height)\n", " browser.get(url)\n", " #Give the map tiles some time to load\n", " time.sleep(delay)\n", " imgpath='{}/{}.png'.format(path,fn)\n", " imgfn = '{}/{}'.format(basepath, imgpath)\n", " imgfile = '{}/{}'.format(os.getcwd(),imgfn)\n", " browser.save_screenshot(imgfile)\n", " browser.quit()\n", " os.remove(imgfile.replace('.png','.html'))\n", " #print(imgfn)\n", " return imgpath\n", "\n", "\n", "def getTablePNG(tablehtml,basepath='.', path='testpng', fnstub='testhtml'):\n", " ''' Save HTML table as file. '''\n", " if not os.path.exists(path):\n", " os.makedirs('{}/{}'.format(basepath, path))\n", " fn='{cwd}/{basepath}/{path}/{fn}.html'.format(cwd=os.getcwd(), basepath=basepath, path=path,fn=fnstub)\n", " tmpurl='file://{fn}'.format(fn=fn)\n", " with open(fn, 'w') as out:\n", " out.write(tablehtml)\n", " return getTableImage(tmpurl, fnstub, basepath, path)\n", " #print(tmpurl)\n", "\n", " \n", "\n", "if __name__=='__main__':\n", " getTablePNG(s2)" ] }, { "cell_type": "code", "execution_count": 115, "metadata": {}, "outputs": [], "source": [ "if __name__=='__main__':\n", " from dakar_utils import getTablePNG\n", " getTablePNG(s2, fnstub='stage_{}_{}'.format(ss,d),scale_factor=5)" ] }, { "cell_type": "raw", "metadata": {}, "source": [ "if __name__=='__main__':\n", " #Testing\n", " !pip3 install renderer\n", " #!pip3 install simple-settings\n", " #!pip3 install --upgrade git+https://github.com/istresearch/phantom-snap.git\n", " #!pip3 install phantom-snap\n", "\n", " from phantom_snap.settings import PHANTOMJS\n", " from phantom_snap.phantom import PhantomJSRenderer\n", " from phantom_snap.imagetools import save_image\n", "\n", " config = {\n", " 'executable': '/usr/local/bin/phantomjs',\n", " 'args': PHANTOMJS['args'] + ['--disk-cache=false', '--load-images=true']\n", " }\n", " r = PhantomJSRenderer(config)\n", "\n", " url = 'http://raallydatajunkie.com'\n", " html = s2\n", "\n", " try:\n", " page = r.render(url=url, html=html, img_format='PNG')\n", " save_image('.', page)\n", " finally:\n", " r.shutdown(15)" ] }, { "cell_type": "code", "execution_count": 48, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Road Position Previous Waypoint Rank Rebase Gap 1 2 3 4 SS10 Overall Stage Rank Overall Position Overall Time gapToStageLeader D1 D2 D3 D4 D5
drivercode
GRÖ11050
OGI2143
LAT3527
BER42026
TUO51316
TID6119
MEE746
NEU835
LOE997
LAP1064
EVA1183
MIK1272
TÄN1321
SUN14308
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "if __name__=='__main__':\n", " s2 = getDriverSplitsReport(conn, rally, 'SS10', 'PAD', rc, typ, 'roadpos')\n", " display(HTML(s2))" ] }, { "cell_type": "code", "execution_count": 124, "metadata": {}, "outputs": [ { "ename": "TypeError", "evalue": "'NoneType' object is not callable", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0m__name__\u001b[0m\u001b[0;34m==\u001b[0m\u001b[0;34m'__main__'\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0ms2\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mgetDriverSplitsReport\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mconn\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mrally\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'SS20'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'TÄN'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mrc\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtyp\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m'stage'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 3\u001b[0m \u001b[0mdisplay\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mHTML\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ms2\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m\u001b[0m in \u001b[0;36mgetDriverSplitsReport\u001b[0;34m(conn, rally, ss, drivercode, rc, typ, order, caption, bars)\u001b[0m\n\u001b[1;32m 28\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mroadPos\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mempty\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 29\u001b[0m \u001b[0;31m#Should we automatically offer the stagetable report as an alternative\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 30\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mgetDriverStageReport\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mconn\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mrally\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mss\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdrivercode\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0morder\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0morder\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcaption\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mcaption\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 31\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 32\u001b[0m \u001b[0;31m#Get the splits\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m\u001b[0m in \u001b[0;36mgetDriverStageReport\u001b[0;34m(conn, rally, ss, drivercode, rc, typ, order, caption)\u001b[0m\n\u001b[1;32m 11\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 12\u001b[0m \u001b[0;31m#Get stage result - does it need to be enriched?\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 13\u001b[0;31m \u001b[0mstageresult\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0msr\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mgetEnrichedStageRank\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mconn\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mrally\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mstages\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mss\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mtyp\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m'stage'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 14\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 15\u001b[0m \u001b[0mstagerebaser\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mstageresult\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mstageresult\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'drivercode'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m==\u001b[0m\u001b[0mdrivercode\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'code'\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m'elapsedDurationMs'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mset_index\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'code'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mto_dict\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0morient\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m'dict'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'elapsedDurationMs'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m~/Documents/GitHub/WRC_sketches/doodles/Charts - Stage Results.ipynb\u001b[0m in \u001b[0;36mgetEnrichedStageRank\u001b[0;34m(conn, rally, rc, typ, stages)\u001b[0m\n", "\u001b[0;32m~/Documents/GitHub/WRC_sketches/doodles/Charts - Stage Results.ipynb\u001b[0m in \u001b[0;36mdbGetCombinedStageRanks\u001b[0;34m(conn, rally, rc, typ, stages)\u001b[0m\n", "\u001b[0;32m~/Documents/GitHub/WRC_sketches/doodles/Charts - Stage Results.ipynb\u001b[0m in \u001b[0;36mdbGetStageRank\u001b[0;34m(conn, rally, rc, typ, stages)\u001b[0m\n", "\u001b[0;32m/usr/local/lib/python3.7/site-packages/pandas/core/groupby/groupby.py\u001b[0m in \u001b[0;36mrank\u001b[0;34m(self, method, ascending, na_option, pct, axis)\u001b[0m\n\u001b[1;32m 1844\u001b[0m return self._cython_transform('rank', numeric_only=False,\n\u001b[1;32m 1845\u001b[0m \u001b[0mties_method\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mmethod\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mascending\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mascending\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1846\u001b[0;31m na_option=na_option, pct=pct, axis=axis)\n\u001b[0m\u001b[1;32m 1847\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1848\u001b[0m \u001b[0;34m@\u001b[0m\u001b[0mSubstitution\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m'groupby'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m/usr/local/lib/python3.7/site-packages/pandas/core/groupby/groupby.py\u001b[0m in \u001b[0;36m_cython_transform\u001b[0;34m(self, how, numeric_only, **kwargs)\u001b[0m\n\u001b[1;32m 805\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 806\u001b[0m result, names = self.grouper.transform(obj.values, how,\n\u001b[0;32m--> 807\u001b[0;31m **kwargs)\n\u001b[0m\u001b[1;32m 808\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mNotImplementedError\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 809\u001b[0m \u001b[0;32mcontinue\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m/usr/local/lib/python3.7/site-packages/pandas/core/groupby/ops.py\u001b[0m in \u001b[0;36mtransform\u001b[0;34m(self, values, how, axis, **kwargs)\u001b[0m\n\u001b[1;32m 549\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 550\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mtransform\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvalues\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mhow\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0maxis\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 551\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_cython_operation\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'transform'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvalues\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mhow\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0maxis\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 552\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 553\u001b[0m def _aggregate(self, result, counts, values, comp_ids, agg_func,\n", "\u001b[0;32m/usr/local/lib/python3.7/site-packages/pandas/core/groupby/ops.py\u001b[0m in \u001b[0;36m_cython_operation\u001b[0;34m(self, kind, values, how, axis, min_count, **kwargs)\u001b[0m\n\u001b[1;32m 509\u001b[0m result = self._transform(\n\u001b[1;32m 510\u001b[0m \u001b[0mresult\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvalues\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlabels\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mis_numeric\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mis_datetimelike\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 511\u001b[0;31m **kwargs)\n\u001b[0m\u001b[1;32m 512\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 513\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mis_integer_dtype\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mresult\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mis_datetimelike\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m/usr/local/lib/python3.7/site-packages/pandas/core/groupby/ops.py\u001b[0m in \u001b[0;36m_transform\u001b[0;34m(self, result, values, comp_ids, transform_func, is_numeric, is_datetimelike, **kwargs)\u001b[0m\n\u001b[1;32m 582\u001b[0m comp_ids, is_datetimelike, **kwargs)\n\u001b[1;32m 583\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 584\u001b[0;31m \u001b[0mtransform_func\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mresult\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvalues\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcomp_ids\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mis_datetimelike\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 585\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 586\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mresult\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m/usr/local/lib/python3.7/site-packages/pandas/core/groupby/ops.py\u001b[0m in \u001b[0;36mwrapper\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m 395\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 396\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mwrapper\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 397\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mafunc\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 398\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 399\u001b[0m \u001b[0;31m# need to curry our sub-function\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m/usr/local/lib/python3.7/site-packages/pandas/core/groupby/ops.py\u001b[0m in \u001b[0;36m\u001b[0;34m(func, a, b, c, d, **kwargs)\u001b[0m\n\u001b[1;32m 346\u001b[0m \u001b[0mkwargs\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'ascending'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;32mTrue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 347\u001b[0m \u001b[0mkwargs\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'pct'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;32mFalse\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 348\u001b[0;31m \u001b[0mkwargs\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'na_option'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'keep'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 349\u001b[0m )\n\u001b[1;32m 350\u001b[0m }\n", "\u001b[0;31mTypeError\u001b[0m: 'NoneType' object is not callable" ] } ], "source": [ "if __name__=='__main__':\n", " s2 = getDriverSplitsReport(conn, rally, 'SS20', 'TÄN', rc, typ,'stage')\n", " display(HTML(s2))" ] }, { "cell_type": "code", "execution_count": 125, "metadata": {}, "outputs": [ { "ename": "TypeError", "evalue": "'NoneType' object is not callable", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0m__name__\u001b[0m\u001b[0;34m==\u001b[0m\u001b[0;34m'__main__'\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0ms2\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mgetDriverSplitsReport\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mconn\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mrally\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'SS18'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'OGI'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mrc\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtyp\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 3\u001b[0m \u001b[0mdisplay\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mHTML\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ms2\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m\u001b[0m in \u001b[0;36mgetDriverSplitsReport\u001b[0;34m(conn, rally, ss, drivercode, rc, typ, order, caption, bars)\u001b[0m\n\u001b[1;32m 28\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mroadPos\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mempty\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 29\u001b[0m \u001b[0;31m#Should we automatically offer the stagetable report as an alternative\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 30\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mgetDriverStageReport\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mconn\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mrally\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mss\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdrivercode\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0morder\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0morder\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcaption\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mcaption\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 31\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 32\u001b[0m \u001b[0;31m#Get the splits\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m\u001b[0m in \u001b[0;36mgetDriverStageReport\u001b[0;34m(conn, rally, ss, drivercode, rc, typ, order, caption)\u001b[0m\n\u001b[1;32m 11\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 12\u001b[0m \u001b[0;31m#Get stage result - does it need to be enriched?\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 13\u001b[0;31m \u001b[0mstageresult\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0msr\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mgetEnrichedStageRank\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mconn\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mrally\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mstages\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mss\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mtyp\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m'stage'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 14\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 15\u001b[0m \u001b[0mstagerebaser\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mstageresult\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mstageresult\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'drivercode'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m==\u001b[0m\u001b[0mdrivercode\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'code'\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m'elapsedDurationMs'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mset_index\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'code'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mto_dict\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0morient\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m'dict'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'elapsedDurationMs'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m~/Documents/GitHub/WRC_sketches/doodles/Charts - Stage Results.ipynb\u001b[0m in \u001b[0;36mgetEnrichedStageRank\u001b[0;34m(conn, rally, rc, typ, stages)\u001b[0m\n", "\u001b[0;32m~/Documents/GitHub/WRC_sketches/doodles/Charts - Stage Results.ipynb\u001b[0m in \u001b[0;36mdbGetCombinedStageRanks\u001b[0;34m(conn, rally, rc, typ, stages)\u001b[0m\n", "\u001b[0;32m~/Documents/GitHub/WRC_sketches/doodles/Charts - Stage Results.ipynb\u001b[0m in \u001b[0;36mdbGetStageRank\u001b[0;34m(conn, rally, rc, typ, stages)\u001b[0m\n", "\u001b[0;32m/usr/local/lib/python3.7/site-packages/pandas/core/groupby/groupby.py\u001b[0m in \u001b[0;36mrank\u001b[0;34m(self, method, ascending, na_option, pct, axis)\u001b[0m\n\u001b[1;32m 1844\u001b[0m return self._cython_transform('rank', numeric_only=False,\n\u001b[1;32m 1845\u001b[0m \u001b[0mties_method\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mmethod\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mascending\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mascending\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1846\u001b[0;31m na_option=na_option, pct=pct, axis=axis)\n\u001b[0m\u001b[1;32m 1847\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1848\u001b[0m \u001b[0;34m@\u001b[0m\u001b[0mSubstitution\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m'groupby'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m/usr/local/lib/python3.7/site-packages/pandas/core/groupby/groupby.py\u001b[0m in \u001b[0;36m_cython_transform\u001b[0;34m(self, how, numeric_only, **kwargs)\u001b[0m\n\u001b[1;32m 805\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 806\u001b[0m result, names = self.grouper.transform(obj.values, how,\n\u001b[0;32m--> 807\u001b[0;31m **kwargs)\n\u001b[0m\u001b[1;32m 808\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mNotImplementedError\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 809\u001b[0m \u001b[0;32mcontinue\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m/usr/local/lib/python3.7/site-packages/pandas/core/groupby/ops.py\u001b[0m in \u001b[0;36mtransform\u001b[0;34m(self, values, how, axis, **kwargs)\u001b[0m\n\u001b[1;32m 549\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 550\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mtransform\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvalues\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mhow\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0maxis\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 551\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_cython_operation\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'transform'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvalues\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mhow\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0maxis\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 552\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 553\u001b[0m def _aggregate(self, result, counts, values, comp_ids, agg_func,\n", "\u001b[0;32m/usr/local/lib/python3.7/site-packages/pandas/core/groupby/ops.py\u001b[0m in \u001b[0;36m_cython_operation\u001b[0;34m(self, kind, values, how, axis, min_count, **kwargs)\u001b[0m\n\u001b[1;32m 509\u001b[0m result = self._transform(\n\u001b[1;32m 510\u001b[0m \u001b[0mresult\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvalues\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlabels\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mis_numeric\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mis_datetimelike\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 511\u001b[0;31m **kwargs)\n\u001b[0m\u001b[1;32m 512\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 513\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mis_integer_dtype\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mresult\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mis_datetimelike\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m/usr/local/lib/python3.7/site-packages/pandas/core/groupby/ops.py\u001b[0m in \u001b[0;36m_transform\u001b[0;34m(self, result, values, comp_ids, transform_func, is_numeric, is_datetimelike, **kwargs)\u001b[0m\n\u001b[1;32m 582\u001b[0m comp_ids, is_datetimelike, **kwargs)\n\u001b[1;32m 583\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 584\u001b[0;31m \u001b[0mtransform_func\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mresult\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvalues\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcomp_ids\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mis_datetimelike\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 585\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 586\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mresult\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m/usr/local/lib/python3.7/site-packages/pandas/core/groupby/ops.py\u001b[0m in \u001b[0;36mwrapper\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m 395\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 396\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mwrapper\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 397\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mafunc\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 398\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 399\u001b[0m \u001b[0;31m# need to curry our sub-function\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m/usr/local/lib/python3.7/site-packages/pandas/core/groupby/ops.py\u001b[0m in \u001b[0;36m\u001b[0;34m(func, a, b, c, d, **kwargs)\u001b[0m\n\u001b[1;32m 346\u001b[0m \u001b[0mkwargs\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'ascending'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;32mTrue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 347\u001b[0m \u001b[0mkwargs\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'pct'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;32mFalse\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 348\u001b[0;31m \u001b[0mkwargs\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'na_option'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'keep'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 349\u001b[0m )\n\u001b[1;32m 350\u001b[0m }\n", "\u001b[0;31mTypeError\u001b[0m: 'NoneType' object is not callable" ] } ], "source": [ "if __name__=='__main__':\n", " s2 = getDriverSplitsReport(conn, rally, 'SS18', 'OGI', rc, typ)\n", " display(HTML(s2))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Problem with the bars is that the range is different in each column; ideally we want the same range in each column; could do this with two dummy rows to force max and min values?" ] }, { "cell_type": "code", "execution_count": 89, "metadata": {}, "outputs": [ { "data": { "text/html": [ " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
x1y1y2
0-42-1
1-201
2142
37-31
4-700
51-3-2
6-4-3-1
75-41
8310
99-41
10-500-42
11100011
12-10001-2
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "if __name__=='__main__':\n", " #Example for pandas issue https://github.com/pandas-dev/pandas/issues/21526\n", " import pandas as pd\n", " import numpy as np\n", " \n", " df=pd.DataFrame({'x1':list(np.random.randint(-10,10,size=10))+[-500,1000, -1000],\n", " 'y1':list(np.random.randint(-5,5,size=13)),'y2':list(np.random.randint(-2,3,size=13)) })\n", " \n", " display(df.style.bar( align='zero', color=[ '#5fba7d','#d65f5f']))" ] }, { "cell_type": "code", "execution_count": 90, "metadata": {}, "outputs": [ { "data": { "text/html": [ " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
x1y1y2x2
0-42-1-4
1-201-2
21421
37-317
4-700-7
51-3-21
6-4-3-1-4
75-415
83103
99-419
10-500-42-10
1110001110
12-10001-2-10
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "if __name__=='__main__':\n", " #clip lets us set a max limiting range although it means we lose the actual value?\n", " df['x2']= df['x1'].clip(upper=10, lower=-10)\n", " display(df.style.bar( align='zero', color=[ '#d65f5f','#5fba7d']))" ] }, { "cell_type": "code", "execution_count": 91, "metadata": {}, "outputs": [], "source": [ "if __name__=='__main__':\n", " #for pandas 0.24 ? https://github.com/pandas-dev/pandas/pull/21548\n", " df['x2']= df['x1'].clip(upper=10, lower=-10)\n", " #Set axis=None for table wide range?\n", " #display(df.style.bar( align='zero', axis=None, color=[ '#d65f5f','#5fba7d']))\n", " " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.0" } }, "nbformat": 4, "nbformat_minor": 2 }