{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "### Scorecard" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import math\n", "import pandas as pd\n", "import numpy as np\n", "from PIL import Image\n", "\n", "import matplotlib\n", "import matplotlib.pyplot as plt\n", "import matplotlib.patches as patches\n", "from matplotlib.patches import FancyBboxPatch\n", "from matplotlib.offsetbox import OffsetImage, AnnotationBbox\n", "\n", "def get_colors_from_map(palette='Blues', value=1):\n", " \"\"\" Create colors from a heatmap\n", " \n", " Here, we would like to have 7 colors at most\n", " for easier visualization.\n", " \n", " However, the maximum number of crosses is 14. Therefore,\n", " I divide by 2 to get at most 7 colors.\n", " \n", " It should be based on the actual maximum value instead\n", " of manually setting the number of colors. However, these \n", " are the settings I want for my personal visualization. \n", " \n", " \"\"\"\n", " value = round(value/2)\n", " cmap = plt.cm.get_cmap(palette, 7)\n", " rgb = cmap(value)\n", " return matplotlib.colors.rgb2hex(rgb)\n", "\n", "def count_total_color(row, value):\n", " \"\"\"\n", " # Add number of times a person got a score in a row\n", " # Thus number of multipliers per game \n", " \"\"\"\n", " count = 0\n", " if sum([row.r_2, row.r_3,row.r_4,row.r_5,row.r_6,row.r_7,row.r_8,\n", " row.r_9,row.r_10,row.r_11,row.r_12,row.r_13]) == value:\n", " count += 1\n", " if sum([row.ge_2, row.ge_3,row.ge_4,row.ge_5,row.ge_6,row.ge_7,row.ge_8,\n", " row.ge_9,row.ge_10,row.ge_11,row.ge_12,row.ge_13]) == value:\n", " count += 1\n", " if sum([row.g_2, row.g_3,row.g_4,row.g_5,row.g_6,row.g_7,row.g_8,\n", " row.g_9,row.g_10,row.g_11,row.g_12,row.g_13]) == value:\n", " count += 1\n", " if sum([row.b_2, row.b_3,row.b_4,row.b_5,row.b_6,row.b_7,row.b_8,\n", " row.b_9,row.b_10,row.b_11,row.b_12,row.b_13]) == value:\n", " count += 1\n", " return count\n", "\n", "def get_crosses_color(row, color):\n", " \"\"\" Return number of crosses per color\n", " \"\"\"\n", " points = row[[color+'_{}'.format(i) for i in np.arange(2, 14, 1)]].sum()\n", " return int(points)\n", "\n", "def get_points_color(row, color):\n", " \"\"\" Get total points per color depending on the multiplier\n", " \"\"\"\n", " point_multiplier = {i:val for i,val in zip(np.arange(0, 13, 1), \n", " [0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66, 78])}\n", " points = point_multiplier[row[color+'_cross']]\n", " return points\n", "\n", "def total_points(row):\n", " \"\"\" Return total number of points\n", " \"\"\"\n", " points = row['r_points']+row['ge_points']+row['g_points']+row['b_points']-row['mislukt']\n", " return points\n", "\n", "def get_win_lose(row, df):\n", " \"\"\" If you won or lost a match\n", " \"\"\"\n", " other = df.loc[df.ID == row.ID, :]\n", " other = other.loc[other.Person != row.Person, 'total_points'].values[0]\n", " if row.total_points > other:\n", " return \"Win\"\n", " else:\n", " return \"Lose\"\n", " \n", "df = pd.read_excel('Qwixx.xlsx').fillna(0)\n", "\n", "max_val = df.groupby('Person').sum().drop(['mislukt', 'ID'], 1).values.max()\n", "# min_val = df.groupby('Person').sum().drop(['mislukt', 'ID'], 1).values.min()\n", "\n", "# vals is a dict that is used to make lookups easier in the visualization generation\n", "cols = ['r', 'ge', 'g', 'b']\n", "cols_dict = {col: [col+'_'+str(i) for i in np.arange(2, 14, 1)] for col in cols}\n", "vals = {person:{col: list(pd.DataFrame(df.loc[df.Person==person, :].sum()).T[cols_dict[col]].values[0])\n", " for col in cols} \n", " for person in ['Ilse', 'Maarten']}\n", "\n", "# Add number of times a person got a score in a row\\\n", "# Thus number of multipliers per game\n", "for i in np.arange(1, 13, 1):\n", " df['mult_{}'.format(i)] = df.apply(lambda row: count_total_color(row, i), 1)\n", "\n", "# number of crosses and points per color per game\n", "for i in ['r', 'ge', 'g', 'b']: \n", " df['{}_cross'.format(i)] = df.apply(lambda row: get_crosses_color(row, i), 1)\n", "for i in ['r', 'ge', 'g', 'b']: \n", " df['{}_points'.format(i)] = df.apply(lambda row: get_points_color(row, i), 1)\n", " \n", "# Total points\n", "df['total_points'] = df.apply(lambda row: total_points(row), 1)\n", "\n", "# Won or lost match\n", "df['win_lose'] = df.apply(lambda row: get_win_lose(row, df), 1)" ] }, { "cell_type": "code", "execution_count": 95, "metadata": {}, "outputs": [], "source": [ "# Variables\n", "palette = 'Blues' #PuBuGn or #YlGnBu or Blues or #RdYlBu\n", "person = '...'\n", "im = np.array(Image.open('qwixx_new_v2.png'), dtype=np.uint8)\n", "\n", "# Create plot and show image\n", "fig,ax = plt.subplots(1)\n", "ax.imshow(im)\n", "\n", "# Heatmap\n", "for i in range(11):\n", " color = get_colors_from_map(palette=palette, value=int(vals[person]['r'][i]))\n", " p_fancy = FancyBboxPatch((90+(i*130.8),62), 128, 128, \n", " boxstyle=\"round,pad=0.1, rounding_size=20\", \n", " ec='white',fc=color)\n", " plt.text(180+(i*130), 90, str(i+2), fontsize=14, color='white') \n", " ax.add_patch(p_fancy)\n", "\n", " color = get_colors_from_map(palette=palette, value=int(vals[person]['ge'][i]))\n", " p_fancy = FancyBboxPatch((90+(i*130.8),235), 128, 128, \n", " boxstyle=\"round,pad=0.1, rounding_size=20\", \n", " ec='white',fc=color)\n", " plt.text(180+(i*130), 260, str(i+2), fontsize=14, color='white')\n", " ax.add_patch(p_fancy)\n", " \n", " color = get_colors_from_map(palette=palette, value=int(vals[person]['g'][i]))\n", " p_fancy = FancyBboxPatch((90+(i*130.8),408.5), 128, 128, \n", " boxstyle=\"round,pad=0.1, rounding_size=20\", \n", " ec='white',fc=color)\n", " plt.text(210+(i*130), 435, str(np.arange(12, 1, -1)[i]), fontsize=14, color='white',\n", " horizontalalignment='right')\n", " ax.add_patch(p_fancy)\n", " \n", " color = get_colors_from_map(palette=palette, value=int(vals[person]['b'][i]))\n", " p_fancy = FancyBboxPatch((90+(i*130.8),581.5), 128, 128, \n", " boxstyle=\"round,pad=0.1, rounding_size=20\", \n", " ec='white',fc=color)\n", " plt.text(210+(i*130), 610, str(np.arange(12, 1, -1)[i]), fontsize=14, color='white', \n", " horizontalalignment='right')\n", " ax.add_patch(p_fancy)\n", "\n", "# Plot Circle\n", "for i,val in enumerate(['r', 'ge', 'g', 'b']):\n", " color = get_colors_from_map(palette=palette, value=int(vals[person][val][-1]))\n", " circle = plt.Circle((1596,125+(i*173.7)), 47, color=color)\n", " ax.add_artist(circle)\n", " \n", "# Set total number of crosses\n", "for i in np.arange(1, 13, 1):\n", " value = df.loc[df.Person==person, 'mult_{}'.format(i)].sum()\n", " plt.text(232+((i-1)*100), 860, str(value), fontsize=22, color='black', fontweight='bold',\n", " horizontalalignment='center')\n", "\n", "# Set average points for colors\n", "for i, color in enumerate(['r', 'ge', 'g', 'b']):\n", " val = round(df.loc[df.Person==person, '{}_points'.format(color)].mean(), 1)\n", " plt.text(258+(i*200), 995, str(val), fontsize=24, color='black', fontweight='bold',\n", " horizontalalignment='center')\n", "\n", "# Set average points for failed\n", "val = round(df.loc[df.Person==person, 'mislukt'.format(color)].mean(), 1)\n", "plt.text(1107, 995, str(val), fontsize=26, color='black', fontweight='bold',\n", " horizontalalignment='center')\n", "\n", "# Set average points total\n", "val = round(df.loc[df.Person==person, 'total_points'.format(color)].mean(), 1)\n", "plt.text(1470, 1015, str(val), fontsize=50, color='black', fontweight='bold',\n", " horizontalalignment='center')\n", "\n", "# Add keys\n", "for i, color in enumerate(['red', 'yellow', 'green', 'blue']):\n", " im = OffsetImage(plt.imread('{}_key.png'.format(color)), zoom=0.35)\n", " ab = AnnotationBbox(im, (1594, 123+(i*174)), frameon=False)\n", " ax.add_artist(ab)\n", "\n", "# remove axes for image\n", "plt.axis('off')\n", "\n", "# Add Colorbar\n", "cmap = matplotlib.colors.ListedColormap([get_colors_from_map(palette=palette, \n", " value=i) \n", " for i in [0,2,4,6,8,10,12]])\n", "bounds = np.arange(1, 9, 1)\n", "norm = matplotlib.colors.BoundaryNorm(bounds, cmap.N)\n", "# ax2 = fig.add_axes([0.17, .88, .684, .05])\n", "ax2 = fig.add_axes([0.308, .88, .532, .05])\n", "cb = matplotlib.colorbar.ColorbarBase(ax2, cmap, norm=norm, spacing='proportional',\n", " boundaries=bounds, orientation='horizontal', drawedges=True)\n", "cb.dividers.set_color('black')\n", "cb.dividers.set_linewidth(2)\n", "\n", "cb_tick_locs = np.arange(0.5, 8, 1)\n", "cb.set_ticks(cb_tick_locs)\n", "cb.set_ticklabels([\"{} - {}\".format(i, i+1) for i in np.arange(0, 16, 2)])\n", "# cb.outline.set_visible(False)\n", "cb.ax.tick_params(labelsize=12)\n", "rect1 = patches.Rectangle((-.258,0),1.283,1.3,linewidth=0,facecolor='#E3E3E3',\n", " zorder=0,clip_on=False)\n", "ax2.add_patch(rect1)\n", "plt.text(-.14, -.25, 'Number of \\nCrosses', fontsize=24, color='black', fontweight='bold',\n", " horizontalalignment='center')\n", "\n", "# Minus points\n", "val = df.loc[df.Person==person, 'mislukt'].mean()\n", "for i in range(math.floor(val)):\n", " p_fancy = FancyBboxPatch((1394+(i*71),815), 52, 64, \n", " boxstyle=\"round,pad=0.1, rounding_size=15\", \n", " ec='none',fc='#343434')\n", " ax.add_patch(p_fancy)\n", "val = val - math.floor(val)\n", "\n", "p_fancy = FancyBboxPatch((1394+((i+1)*71),815), 52*(val), 64, \n", " boxstyle=\"round,pad=0.1, rounding_size=15\", \n", " ec='none',fc='#343434')\n", "ax.add_patch(p_fancy)\n", "\n", "fig.set_size_inches(18.5, 10.5)\n", "plt.show()\n", "# plt.savefig('testing_maarten.png', dpi=600)" ] }, { "cell_type": "code", "execution_count": 252, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAh4AAABRCAYAAACdUq/aAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMi4yLCBo\ndHRwOi8vbWF0cGxvdGxpYi5vcmcvhp/UCwAACb1JREFUeJzt3XmMJGUZx/HvT1ZERIOEoMiSrAcB\njMeKRMEziuKKBvyDiEYNHonReKDxwpCY6B+K0Xjf8ViMRFFEJV5AEI8oGFZAFgERT1ZRdjQqKAvi\nPP7RtTr2TE9X7y5VNbPfTzLprqr3fevpZ6qrn6nqqUpVIUmS1IW79B2AJEnafVh4SJKkzlh4SJKk\nzlh4SJKkzlh4SJKkzlh4SJKkzlh4SJKkzlh4SJKkzlh4SJKkzqyZpfGxT9tQc3NzO7SiWvSkRds2\njYFZL766qHnL/oubTehYMw07fdQZBuo/xmo17sTlE+OqZaaWGX/5l7/sSJNe46Qe09tPeQ07OP7E\n5dvnT3iDTG7fcv1jC6rF1jT72C23p7bj1ozb0ZQGNe2XNr6eKUmsxbN23ZjTcrST4yzq1XbHvGg7\nnm0jWdS+1WdM2x1gLfWwRLOWe6S2O/eJ4017rZOWTxlvlg+d8X39rVvPq6oNkzssNlPh8ee5OX54\nyaZmlUv/Quq/0+2WL5XfSW3Gc7ijy2s8cTv5GoayvMsY5sc+EMbbz0/8HUxZ3jzOT+g3efn2/s34\nY9NTly+Rw8WvcbzvWLux6fkpr2l+Yv+x9Y3PH8/htPWOjz/++tqud0ru5hcksWr5NotyOqH9xOUT\nXsPE9U0ab9H2t3w809Y3eXq2fjvSZ0fXPT+/c+MycX2ztdvV4+yKsaa1+19S5ltOt2034/T8nbSe\nFm22XfHh/ZmRp1okSVJnLDwkSVJnLDwkSVJnLDwkSVJnLDwkSVJnLDwkSVJnLDwkSVJnLDwkSVJn\nLDwkSVJnLDwkSVJnLDwkSVJnLDwkSVJnLDwkSVJnLDwkSVJnLDwkSVJnLDwkSVJnLDwkSVJnLDwk\nSVJnLDwkSVJnLDwkSVJnLDwkSVJnLDwkSVJnLDwkSVJnLDwkSVJnLDwkSVJnLDwkSVJnLDwkSVJn\nLDwkSVJnLDwkSVJnLDwkSVJnLDwkSVJnUlXtGydXAdvuvHBWjf2Bub6DWAHMUzvmqR3z1I55asc8\n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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import matplotlib.pyplot as plt\n", "import matplotlib as mpl\n", "\n", "# Make a figure and axes with dimensions as desired.\n", "fig = plt.figure(figsize=(8, 3))\n", "ax1 = fig.add_axes([0.05, 0.80, 0.9, 0.15])\n", "\n", "# Set the colormap and norm to correspond to the data for which\n", "# the colorbar will be used.\n", "cmap = mpl.cm.cool\n", "norm = mpl.colors.Normalize(vmin=0, vmax=14)\n", "\n", "# ColorbarBase derives from ScalarMappable and puts a colorbar\n", "# in a specified axes, so it has everything needed for a\n", "# standalone colorbar. There are many more kwargs, but the\n", "# following gives a basic continuous colorbar with ticks\n", "# and labels.\n", "cb1 = mpl.colorbar.ColorbarBase(ax1, cmap='Blues',\n", " norm=norm,\n", " orientation='horizontal')\n", "cb1.set_label('Some Units')\n", "\n", "\n", "\n", "plt.show()" ] } ], "metadata": { "kernelspec": { "display_name": "Python [default]", "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.5.4" } }, "nbformat": 4, "nbformat_minor": 2 }