stat_row = (svg, data, statName, statFunction, statXPosition, xScale, xLabel, tickValues) => {
svg.append("g")
.attr("transform", `translate(0,${y(statName)+y.bandwidth()/6})`)
.call(d3.axisBottom(xScale).ticks(null, data.format).tickValues(tickValues))
.call(g => g.selectAll(".tick line").clone().attr("stroke-opacity", 0.1)
.attr("transform", `translate(0,${-y.bandwidth()/6})`).attr("y2", y.bandwidth()/6))
.call(g => g.selectAll(".domain").remove());
const g = svg.append("g")
g.append("line")
.attr("stroke", "#aaa")
.attr("x1", xScale(0))
.attr("x2", xScale(d3.max(data, statFunction)))
.attr("y1", y(statName))
.attr("y2", y(statName))
.style("stroke-dasharray", ("1,1"));
g.selectAll("circle")
.data(data)
.join("circle")
.attr("id", "dotsPlayers")
.attr("cx", statXPosition)
.attr("cy", y(statName))
.attr("fill", d => colorDots(d,player))
.attr("stroke", d => strokeDots(d,player))
.attr("stroke-width",d => (d.name === player) ? 3 : 0)
.attr("r", 10)
.append("title")
.text((d,i) => `${d.name}: ${game_stats.map(statFunction)[i]}`);
g.append("text")
.attr("dy", "0.35em")
.attr("x", 0)
.attr("y", y(statName))
.text(d=> `${statName}${(statName === "efficiency") ? "*" : ""}`)
.style("text-transform", "capitalize")
g.append("text")
.attr("dy", "0.35em")
.attr("text-anchor", "end")
.attr("text-align", "right")
.attr("x", xStat)
.attr("y", y(statName))
.text(d=> `${game_stats.filter(d=>d.name === player).map(statFunction)[0]}`);
return svg.node();
}