Example for d3-star-plot with interaction
Data source: https://www.mathstat.strath.ac.uk/outreach/nessie/nessie_whisky.html
Example for d3-star-plot with interaction
Data source: https://www.mathstat.strath.ac.uk/outreach/nessie/nessie_whisky.html
| d3.starPlot = function() { | |
| var width = 200, | |
| margin = { | |
| top: 0, | |
| right: 0, | |
| bottom: 0, | |
| left: 0 | |
| }, | |
| labelMargin = 20, | |
| includeGuidelines = true, | |
| includeLabels = true, | |
| properties = [], | |
| scales = [], | |
| labels = [], | |
| title = nop, | |
| g, | |
| datum, | |
| radius = width / 2, | |
| origin = [radius, radius], | |
| radii = properties.length, | |
| radians = 2 * Math.PI / radii, | |
| scale = d3.scale.linear() | |
| .domain([0, 100]) | |
| .range([0, radius]) | |
| function chart(selection) { | |
| datum = selection.datum(); | |
| g = selection | |
| .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')') | |
| if (includeGuidelines) { | |
| drawGuidelines(); | |
| } | |
| if (includeLabels) { | |
| drawLabels(); | |
| } | |
| drawChart(); | |
| } | |
| function drawGuidelines() { | |
| var r = 0; | |
| properties.forEach(function(d, i) { | |
| var l, x, y; | |
| l = radius; | |
| x = l * Math.cos(r); | |
| y = l * Math.sin(r); | |
| g.append('line') | |
| .attr('class', 'star-axis') | |
| .attr('x1', origin[0]) | |
| .attr('y1', origin[1]) | |
| .attr('x2', origin[0] + x) | |
| .attr('y2', origin[1] + y) | |
| r += radians; | |
| }) | |
| } | |
| function drawLabels() { | |
| var r = 0; | |
| properties.forEach(function(d, i) { | |
| var l, x, y; | |
| l = radius; | |
| x = (l + labelMargin) * Math.cos(r); | |
| y = (l + labelMargin) * Math.sin(r); | |
| g.append('text') | |
| .attr('class', 'star-label') | |
| .attr('x', origin[0] + x) | |
| .attr('y', origin[1] + y) | |
| .text(labels[i]) | |
| .style('text-anchor', 'middle') | |
| .style('dominant-baseline', 'central') | |
| r += radians; | |
| }) | |
| } | |
| function drawChart() { | |
| g.append('circle') | |
| .attr('class', 'star-origin') | |
| .attr('cx', origin[0]) | |
| .attr('cy', origin[1]) | |
| .attr('r', 2) | |
| var path = d3.svg.line.radial() | |
| var pathData = []; | |
| var r = Math.PI / 2; | |
| properties.forEach(function(d, i) { | |
| var userScale = scales[i] || scales[0]; | |
| pathData.push([ | |
| scale(userScale(datum[d])), | |
| r | |
| ]) | |
| r += radians; | |
| }); | |
| g.append('path') | |
| .attr('class', 'star-path') | |
| .attr('transform', 'translate(' + origin[0] + ',' + origin[1] + ')') | |
| .attr('d', path(pathData) + 'Z'); | |
| g.append('text') | |
| .attr('class', 'star-title') | |
| .attr('x', origin[0]) | |
| .attr('y', -(margin.top / 2)) | |
| .text(title(datum)) | |
| .style('text-anchor', 'middle') | |
| } | |
| function drawInteraction() { | |
| var path = d3.svg.line.radial(); | |
| // `*Interaction` variables are used to build the interaction layer. | |
| // `*Extent` variables are used to compute (and return) the x,y | |
| // positioning of the attribute extents. `*Value` variables are used | |
| // for the attribute values. | |
| var rInteraction = Math.PI / 2; | |
| var rExtent = 0; | |
| properties.forEach(function(d, i) { | |
| var lInteraction, xInteraction, yInteraction; | |
| var lExtent, xExtent, yExtent; | |
| lInteraction = radius; | |
| xInteraction = lInteraction * Math.cos(rInteraction); | |
| yInteraction = lInteraction * Math.sin(rInteraction); | |
| lExtent = radius + labelMargin; | |
| xExtent = lExtent * Math.cos(rExtent) + origin[0] + margin.left; | |
| yExtent = lExtent * Math.sin(rExtent) + origin[1] + margin.top; | |
| var userScale = scales[i] || scales[0]; | |
| lValue = scale(userScale(datum[d])); | |
| x = lValue * Math.cos(rExtent) + origin[0] + margin.left; | |
| y = lValue * Math.sin(rExtent) + origin[1] + margin.top; | |
| var halfRadians = radians / 2; | |
| var pathData = [ | |
| [0, rInteraction - halfRadians], | |
| [lInteraction, rInteraction - halfRadians], | |
| [lInteraction, rInteraction + halfRadians] | |
| ]; | |
| var datumToBind = { | |
| xExtent: xExtent, | |
| yExtent: yExtent, | |
| x: x, | |
| y: y, | |
| key: properties[i], | |
| datum: datum | |
| }; | |
| g.append('path') | |
| .datum(datumToBind) | |
| .attr('class', 'star-interaction') | |
| .attr('transform', 'translate(' + origin[0] + ',' + origin[1] + ')') | |
| .attr('d', path(pathData) + 'Z'); | |
| rInteraction += radians; | |
| rExtent += radians; | |
| }) | |
| } | |
| function nop() { | |
| return; | |
| } | |
| chart.interaction = function() { | |
| drawInteraction(); | |
| }; | |
| chart.properties = function(_) { | |
| if (!arguments.length) return properties; | |
| properties = _; | |
| radii = properties.length; | |
| radians = 2 * Math.PI / radii; | |
| return chart; | |
| }; | |
| chart.scales = function(_) { | |
| if (!arguments.length) return scales; | |
| if (Array.isArray(_)) { | |
| scales = _; | |
| } else { | |
| scales = [_]; | |
| } | |
| return chart; | |
| }; | |
| chart.width = function(_) { | |
| if (!arguments.length) return width; | |
| width = _; | |
| radius = width / 2; | |
| origin = [radius, radius]; | |
| scale.range([0, radius]) | |
| return chart; | |
| }; | |
| chart.margin = function(_) { | |
| if (!arguments.length) return margin; | |
| margin = _; | |
| origin = [radius, radius]; | |
| return chart; | |
| }; | |
| chart.labelMargin = function(_) { | |
| if (!arguments.length) return labelMargin; | |
| labelMargin = _; | |
| return chart; | |
| }; | |
| chart.title = function(_) { | |
| if (!arguments.length) return title; | |
| title = _; | |
| return chart; | |
| }; | |
| chart.labels = function(_) { | |
| if (!arguments.length) return labels; | |
| labels = _; | |
| return chart; | |
| }; | |
| chart.includeGuidelines = function(_) { | |
| if (!arguments.length) return includeGuidelines; | |
| includeGuidelines = _; | |
| return chart; | |
| }; | |
| chart.includeLabels = function(_) { | |
| if (!arguments.length) return includeLabels; | |
| includeLabels = _; | |
| return chart; | |
| }; | |
| return chart; | |
| } | |
| <!DOCTYPE> | |
| <meta charset="utf-8"> | |
| <style> | |
| body { | |
| width: 960px; | |
| margin: auto; | |
| font-family: Arial; | |
| } | |
| #target { | |
| margin: 40px 0; | |
| } | |
| .wrapper { | |
| position: relative; | |
| display: inline-block; | |
| } | |
| .chart { | |
| margin-bottom: 40px; | |
| } | |
| .star-title { | |
| font-size: 14px; | |
| } | |
| .star-label { | |
| font-size: 11px; | |
| pointer-events: none; | |
| } | |
| .star-origin { | |
| fill: #333; | |
| } | |
| .star-axis { | |
| stroke: #ccc; | |
| stroke-width: 2px; | |
| stroke-dasharray: 4 5; | |
| } | |
| .star-path { | |
| stroke: #444; | |
| stroke-width: 2px; | |
| fill: #709CB1; | |
| fill-opacity: 0.6; | |
| } | |
| .star-interaction { | |
| opacity: 0; | |
| } | |
| .interaction { | |
| pointer-events: none; | |
| } | |
| .interaction.label { | |
| position: absolute; | |
| font-size: 11px; | |
| text-shadow: 0 1px 0 #FFF, 0 -1px 0 #FFF, 1px 0 #FFF, -1px 0 #FFF; | |
| } | |
| .interaction.circle { | |
| fill: #444; | |
| fill-opacity: 0.6; | |
| stroke: #444; | |
| } | |
| </style> | |
| <body> | |
| <script src="http://d3js.org/d3.v3.min.js"></script> | |
| <script src="http://code.jquery.com/jquery-1.11.0.min.js"></script> | |
| <script src="d3-starPlot.js"></script> | |
| <script> | |
| var margin = { | |
| top: 32, | |
| right: 50, | |
| bottom: 20, | |
| left: 50 | |
| }; | |
| var width = 240 - margin.left - margin.right; | |
| var height = 240 - margin.top - margin.bottom; | |
| var labelMargin = 8; | |
| var scale = d3.scale.linear() | |
| .domain([0, 4]) | |
| .range([0, 100]) | |
| d3.csv('whiskies.csv') | |
| .row(function(d) { | |
| d.Body = +d.Body; | |
| d.Sweetness = +d.Sweetness; | |
| d.Smoky = +d.Smoky; | |
| d.Medicinal = +d.Medicinal; | |
| d.Tobacco = +d.Tobacco; | |
| d.Honey = +d.Honey; | |
| d.Spicy = +d.Spicy; | |
| d.Winey = +d.Winey; | |
| d.Nutty = +d.Nutty; | |
| d.Malty = +d.Malty; | |
| d.Fruity = +d.Fruity; | |
| d.Floral = +d.Floral; | |
| return d; | |
| }) | |
| .get(function(error, rows) { | |
| var star = d3.starPlot() | |
| .width(width) | |
| .properties([ | |
| 'Body', | |
| 'Sweetness', | |
| 'Smoky', | |
| 'Honey', | |
| 'Spicy', | |
| 'Nutty', | |
| 'Malty', | |
| 'Fruity', | |
| 'Floral' | |
| ]) | |
| .scales(scale) | |
| .labels([ | |
| 'Body', | |
| 'Sweetness', | |
| 'Smoky', | |
| 'Honey', | |
| 'Spicy', | |
| 'Nutty', | |
| 'Malty', | |
| 'Fruity', | |
| 'Floral' | |
| ]) | |
| .title(function(d) { return d.Distillery; }) | |
| .margin(margin) | |
| .labelMargin(labelMargin) | |
| rows.forEach(function(d, i) { | |
| star.includeLabels(i % 4 === 0 ? true : false); | |
| var wrapper = d3.select('#target').append('div') | |
| .attr('class', 'wrapper') | |
| var svg = wrapper.append('svg') | |
| .attr('class', 'chart') | |
| .attr('width', width + margin.left + margin.right) | |
| .attr('height', width + margin.top + margin.bottom) | |
| var starG = svg.append('g') | |
| .datum(d) | |
| .call(star) | |
| .call(star.interaction) | |
| var interactionLabel = wrapper.append('div') | |
| .attr('class', 'interaction label') | |
| var circle = svg.append('circle') | |
| .attr('class', 'interaction circle') | |
| .attr('r', 5) | |
| var interaction = wrapper.selectAll('.interaction') | |
| .style('display', 'none'); | |
| svg.selectAll('.star-interaction') | |
| .on('mouseover', function(d) { | |
| svg.selectAll('.star-label') | |
| .style('display', 'none') | |
| interaction | |
| .style('display', 'block') | |
| circle | |
| .attr('cx', d.x) | |
| .attr('cy', d.y) | |
| $interactionLabel = $(interactionLabel.node()); | |
| interactionLabel | |
| .text(d.key + ': ' + d.datum[d.key]) | |
| .style('left', d.xExtent - ($interactionLabel.width() / 2)) | |
| .style('top', d.yExtent - ($interactionLabel.height() / 2)) | |
| }) | |
| .on('mouseout', function(d) { | |
| interaction | |
| .style('display', 'none') | |
| svg.selectAll('.star-label') | |
| .style('display', 'block') | |
| }) | |
| }); | |
| }); | |
| </script> | |
| <div id='target'></div> | |
| </body> | |
| RowID | Distillery | Body | Sweetness | Smoky | Medicinal | Tobacco | Honey | Spicy | Winey | Nutty | Malty | Fruity | Floral | Postcode | Latitude | Longitude | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 01 | Aberfeldy | 2 | 2 | 2 | 0 | 0 | 2 | 1 | 2 | 2 | 2 | 2 | 2 | PH15 2EB | 286580 | 749680 | |
| 02 | Aberlour | 3 | 3 | 1 | 0 | 0 | 4 | 3 | 2 | 2 | 3 | 3 | 2 | AB38 9PJ | 326340 | 842570 | |
| 03 | AnCnoc | 1 | 3 | 2 | 0 | 0 | 2 | 0 | 0 | 2 | 2 | 3 | 2 | AB5 5LI | 352960 | 839320 | |
| 04 | Ardbeg | 4 | 1 | 4 | 4 | 0 | 0 | 2 | 0 | 1 | 2 | 1 | 0 | PA42 7EB | 141560 | 646220 | |
| 05 | Ardmore | 2 | 2 | 2 | 0 | 0 | 1 | 1 | 1 | 2 | 3 | 1 | 1 | AB54 4NH | 355350 | 829140 | |
| 06 | ArranIsleOf | 2 | 3 | 1 | 1 | 0 | 1 | 1 | 1 | 0 | 1 | 1 | 2 | KA27 8HJ | 194050 | 649950 | |
| 07 | Auchentoshan | 0 | 2 | 0 | 0 | 0 | 1 | 1 | 0 | 2 | 2 | 3 | 3 | G81 4SJ | 247670 | 672610 | |
| 08 | Auchroisk | 2 | 3 | 1 | 0 | 0 | 2 | 1 | 2 | 2 | 2 | 2 | 1 | AB55 3XS | 340754 | 848623 | |
| 09 | Aultmore | 2 | 2 | 1 | 0 | 0 | 1 | 0 | 0 | 2 | 2 | 2 | 2 | AB55 3QY | 340754 | 848623 | |
| 10 | Balblair | 2 | 3 | 2 | 1 | 0 | 0 | 2 | 0 | 2 | 1 | 2 | 1 | IV19 1LB | 270820 | 885770 | |
| 11 | Balmenach | 4 | 3 | 2 | 0 | 0 | 2 | 1 | 3 | 3 | 0 | 1 | 2 | PH26 3PF | 307750 | 827170 | |
| 12 | Belvenie | 3 | 2 | 1 | 0 | 0 | 3 | 2 | 1 | 0 | 2 | 2 | 2 | AB55 4DH | 332680 | 840840 | |
| 13 | BenNevis | 4 | 2 | 2 | 0 | 0 | 2 | 2 | 0 | 2 | 2 | 2 | 2 | PH33 6TJ | 212600 | 775710 | |
| 14 | Benriach | 2 | 2 | 1 | 0 | 0 | 2 | 2 | 0 | 0 | 2 | 3 | 2 | IV30 8SJ | 323450 | 858380 | |
| 15 | Benrinnes | 3 | 2 | 2 | 0 | 0 | 3 | 1 | 1 | 2 | 3 | 2 | 2 | AB38 9NN | 325800 | 839920 | |
| 16 | Benromach | 2 | 2 | 2 | 0 | 0 | 2 | 2 | 1 | 2 | 2 | 2 | 2 | IV36 3EB | 303330 | 859350 | |
| 17 | Bladnoch | 1 | 2 | 1 | 0 | 0 | 0 | 1 | 1 | 0 | 2 | 2 | 3 | DG8 9AB | 242260 | 554260 | |
| 18 | BlairAthol | 2 | 2 | 2 | 0 | 0 | 1 | 2 | 2 | 2 | 2 | 2 | 2 | PH16 5LY | 294860 | 757580 | |
| 19 | Bowmore | 2 | 2 | 3 | 1 | 0 | 2 | 2 | 1 | 1 | 1 | 1 | 2 | PA43 7GS | 131330 | 659720 | |
| 20 | Bruichladdich | 1 | 1 | 2 | 2 | 0 | 2 | 2 | 1 | 2 | 2 | 2 | 2 | PA49 7UN | 126680 | 661400 | |
| 21 | Bunnahabhain | 1 | 2 | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 2 | 2 | 3 | PA46 7RR | 142210 | 673170 | |
| 22 | Caol Ila | 3 | 1 | 4 | 2 | 1 | 0 | 2 | 0 | 2 | 1 | 1 | 1 | PA46 7RL | 142920 | 670040 | |
| 23 | Cardhu | 1 | 3 | 1 | 0 | 0 | 1 | 1 | 0 | 2 | 2 | 2 | 2 | AB38 7RY | 318790 | 843090 | |
| 24 | Clynelish | 3 | 2 | 3 | 3 | 1 | 0 | 2 | 0 | 1 | 1 | 2 | 0 | KW9 6LB | 290250 | 904230 | |
| 25 | Craigallechie | 2 | 2 | 2 | 0 | 1 | 2 | 2 | 1 | 2 | 2 | 1 | 4 | AB38 9ST | 328920 | 844920 | |
| 26 | Craigganmore | 2 | 3 | 2 | 1 | 0 | 0 | 1 | 0 | 2 | 2 | 2 | 2 | AB37 9AB | 316600 | 836370 | |
| 27 | Dailuaine | 4 | 2 | 2 | 0 | 0 | 1 | 2 | 2 | 2 | 2 | 2 | 1 | AB38 7RE | 323520 | 841010 | |
| 28 | Dalmore | 3 | 2 | 2 | 1 | 0 | 1 | 2 | 2 | 1 | 2 | 3 | 1 | IV17 0UT | 266610 | 868730 | |
| 29 | Dalwhinnie | 2 | 2 | 2 | 0 | 0 | 2 | 1 | 0 | 1 | 2 | 2 | 2 | PH19 1AB | 263670 | 785270 | |
| 30 | Deanston | 2 | 2 | 1 | 0 | 0 | 2 | 1 | 1 | 1 | 3 | 2 | 1 | FK16 6AG | 271570 | 701570 | |
| 31 | Dufftown | 2 | 3 | 1 | 1 | 0 | 0 | 0 | 0 | 1 | 2 | 2 | 2 | AB55 4BR | 332360 | 839200 | |
| 32 | Edradour | 2 | 3 | 1 | 0 | 0 | 2 | 1 | 1 | 4 | 2 | 2 | 2 | PH16 5JP | 295960 | 757940 | |
| 33 | GlenDeveronMacduff | 2 | 3 | 1 | 1 | 1 | 1 | 1 | 2 | 0 | 2 | 0 | 1 | AB4 3JT | 372120 | 860400 | |
| 34 | GlenElgin | 2 | 3 | 1 | 0 | 0 | 2 | 1 | 1 | 1 | 1 | 2 | 3 | IV30 3SL | 322640 | 861040 | |
| 35 | GlenGarioch | 2 | 1 | 3 | 0 | 0 | 0 | 3 | 1 | 0 | 2 | 2 | 2 | AB51 0ES | 381020 | 827590 | |
| 36 | GlenGrant | 1 | 2 | 0 | 0 | 0 | 1 | 0 | 1 | 2 | 1 | 2 | 1 | AB38 7BS | 327610 | 849570 | |
| 37 | GlenKeith | 2 | 3 | 1 | 0 | 0 | 1 | 2 | 1 | 2 | 1 | 2 | 1 | AB55 3BU | 340754 | 848623 | |
| 38 | GlenMoray | 1 | 2 | 1 | 0 | 0 | 1 | 2 | 1 | 2 | 2 | 2 | 4 | IV30 1YE | 319820 | 862320 | |
| 39 | GlenOrd | 3 | 2 | 1 | 0 | 0 | 1 | 2 | 1 | 1 | 2 | 2 | 2 | IV6 7UJ | 251810 | 850860 | |
| 40 | GlenScotia | 2 | 2 | 2 | 2 | 0 | 1 | 0 | 1 | 2 | 2 | 1 | 1 | PA28 6DS | 172090 | 621010 | |
| 41 | GlenSpey | 1 | 3 | 1 | 0 | 0 | 0 | 1 | 1 | 1 | 2 | 0 | 2 | AB38 7AU | 327760 | 849140 | |
| 42 | Glenallachie | 1 | 3 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | 2 | 2 | 2 | AB38 9LR | 326490 | 841240 | |
| 43 | Glendronach | 4 | 2 | 2 | 0 | 0 | 2 | 1 | 4 | 2 | 2 | 2 | 0 | AB54 6DA | 361200 | 844930 | |
| 44 | Glendullan | 3 | 2 | 1 | 0 | 0 | 2 | 1 | 2 | 1 | 2 | 3 | 2 | AB55 4DJ | 333000 | 840300 | |
| 45 | Glenfarclas | 2 | 4 | 1 | 0 | 0 | 1 | 2 | 3 | 2 | 3 | 2 | 2 | AB37 9BD | 320950 | 838160 | |
| 46 | Glenfiddich | 1 | 3 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 2 | 2 | 2 | AB55 4DH | 332680 | 840840 | |
| 47 | Glengoyne | 1 | 2 | 0 | 0 | 0 | 1 | 1 | 1 | 2 | 2 | 3 | 2 | G63 9LB | 252810 | 682750 | |
| 48 | Glenkinchie | 1 | 2 | 1 | 0 | 0 | 1 | 2 | 0 | 0 | 2 | 2 | 2 | EH34 5ET | 344380 | 666690 | |
| 49 | Glenlivet | 2 | 3 | 1 | 0 | 0 | 2 | 2 | 2 | 1 | 2 | 2 | 3 | AB37 9DB | 319560 | 828780 | |
| 50 | Glenlossie | 1 | 2 | 1 | 0 | 0 | 1 | 2 | 0 | 1 | 2 | 2 | 2 | IV30 3SS | 322640 | 861040 | |
| 51 | Glenmorangie | 2 | 2 | 1 | 1 | 0 | 1 | 2 | 0 | 2 | 1 | 2 | 2 | IV19 1PZ | 276750 | 883450 | |
| 52 | Glenrothes | 2 | 3 | 1 | 0 | 0 | 1 | 1 | 2 | 1 | 2 | 2 | 0 | AB38 7AA | 327650 | 849170 | |
| 53 | Glenturret | 2 | 3 | 1 | 0 | 0 | 2 | 2 | 2 | 2 | 2 | 1 | 2 | PH7 4HA | 285630 | 723580 | |
| 54 | Highland Park | 2 | 2 | 3 | 1 | 0 | 2 | 1 | 1 | 1 | 2 | 1 | 1 | KW15 1SU | 345340 | 1009260 | |
| 55 | Inchgower | 1 | 3 | 1 | 1 | 0 | 2 | 2 | 0 | 1 | 2 | 1 | 2 | AB56 5AB | 342610 | 863970 | |
| 56 | Isle of Jura | 2 | 1 | 2 | 2 | 0 | 1 | 1 | 0 | 2 | 1 | 1 | 1 | PA60 7XT | 152660 | 667040 | |
| 57 | Knochando | 2 | 3 | 1 | 0 | 0 | 2 | 2 | 1 | 2 | 1 | 2 | 2 | AB38 7RT | 319470 | 841570 | |
| 58 | Lagavulin | 4 | 1 | 4 | 4 | 1 | 0 | 1 | 2 | 1 | 1 | 1 | 0 | PA42 7DZ | 140430 | 645730 | |
| 59 | Laphroig | 4 | 2 | 4 | 4 | 1 | 0 | 0 | 1 | 1 | 1 | 0 | 0 | PA42 7DU | 138680 | 645160 | |
| 60 | Linkwood | 2 | 3 | 1 | 0 | 0 | 1 | 1 | 2 | 0 | 1 | 3 | 2 | IV30 3RD | 322640 | 861040 | |
| 61 | Loch Lomond | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 0 | 1 | 2 | 1 | 2 | G83 0TL | 239370 | 680920 | |
| 62 | Longmorn | 3 | 2 | 1 | 0 | 0 | 1 | 1 | 1 | 3 | 3 | 2 | 3 | IV30 3SJ | 322640 | 861040 | |
| 63 | Macallan | 4 | 3 | 1 | 0 | 0 | 2 | 1 | 4 | 2 | 2 | 3 | 1 | AB38 9RX | 327710 | 844480 | |
| 64 | Mannochmore | 2 | 1 | 1 | 0 | 0 | 1 | 1 | 1 | 2 | 1 | 2 | 2 | IV30 3SS | 322640 | 861040 | |
| 65 | Miltonduff | 2 | 4 | 1 | 0 | 0 | 1 | 0 | 0 | 2 | 1 | 1 | 2 | IV30 3TQ | 322640 | 861040 | |
| 66 | Mortlach | 3 | 2 | 2 | 0 | 0 | 2 | 3 | 3 | 2 | 1 | 2 | 2 | AB55 4AQ | 332950 | 839850 | |
| 67 | Oban | 2 | 2 | 2 | 2 | 0 | 0 | 2 | 0 | 2 | 2 | 2 | 0 | PA34 5NH | 185940 | 730190 | |
| 68 | OldFettercairn | 1 | 2 | 2 | 0 | 1 | 2 | 2 | 1 | 2 | 3 | 1 | 1 | AB30 1YE | 370860 | 772900 | |
| 69 | OldPulteney | 2 | 1 | 2 | 2 | 1 | 0 | 1 | 1 | 2 | 2 | 2 | 2 | KW1 5BA | 336730 | 950130 | |
| 70 | RoyalBrackla | 2 | 3 | 2 | 1 | 1 | 1 | 2 | 1 | 0 | 2 | 3 | 2 | IV12 5QY | 286040 | 851320 | |
| 71 | RoyalLochnagar | 3 | 2 | 2 | 0 | 0 | 2 | 2 | 2 | 2 | 2 | 3 | 1 | AB35 5TB | 326140 | 794370 | |
| 72 | Scapa | 2 | 2 | 1 | 1 | 0 | 2 | 1 | 1 | 2 | 2 | 2 | 2 | KW15 1SE | 342850 | 1008930 | |
| 73 | Speyburn | 2 | 4 | 1 | 0 | 0 | 2 | 1 | 0 | 0 | 2 | 1 | 2 | AB38 7AG | 326930 | 851430 | |
| 74 | Speyside | 2 | 2 | 1 | 0 | 0 | 1 | 0 | 1 | 2 | 2 | 2 | 2 | PH21 1NS | 278740 | 800600 | |
| 75 | Springbank | 2 | 2 | 2 | 2 | 0 | 2 | 2 | 1 | 2 | 1 | 0 | 1 | PA28 6EJ | 172280 | 620910 | |
| 76 | Strathisla | 2 | 2 | 1 | 0 | 0 | 2 | 2 | 2 | 3 | 3 | 3 | 2 | AB55 3BS | 340754 | 848623 | |
| 77 | Strathmill | 2 | 3 | 1 | 0 | 0 | 0 | 2 | 0 | 2 | 1 | 3 | 2 | AB55 5DQ | 342650 | 850500 | |
| 78 | Talisker | 4 | 2 | 3 | 3 | 0 | 1 | 3 | 0 | 1 | 2 | 2 | 0 | IV47 8SR | 137950 | 831770 | |
| 79 | Tamdhu | 1 | 2 | 1 | 0 | 0 | 2 | 0 | 1 | 1 | 2 | 2 | 2 | AB38 7RP | 319210 | 841760 | |
| 80 | Tamnavulin | 1 | 3 | 2 | 0 | 0 | 0 | 2 | 0 | 2 | 1 | 2 | 3 | AB37 9JA | 321180 | 826110 | |
| 81 | Teaninich | 2 | 2 | 2 | 1 | 0 | 0 | 2 | 0 | 0 | 0 | 2 | 2 | IV17 0XB | 265360 | 869120 | |
| 82 | Tobermory | 1 | 1 | 1 | 0 | 0 | 1 | 0 | 0 | 1 | 2 | 2 | 2 | PA75 6NR | 150450 | 755070 | |
| 83 | Tomatin | 2 | 3 | 2 | 0 | 0 | 2 | 2 | 1 | 1 | 2 | 0 | 1 | IV13 7YT | 279120 | 829630 | |
| 84 | Tomintoul | 0 | 3 | 1 | 0 | 0 | 2 | 2 | 1 | 1 | 2 | 1 | 2 | AB37 9AQ | 315100 | 825560 | |
| 85 | Tormore | 2 | 2 | 1 | 0 | 0 | 1 | 0 | 1 | 2 | 1 | 0 | 0 | PH26 3LR | 315180 | 834960 | |
| 86 | Tullibardine | 2 | 3 | 0 | 0 | 1 | 0 | 2 | 1 | 1 | 2 | 2 | 1 | PH4 1QG | 289690 | 708850 |