Skip to content

Commit

Permalink
adds scatter plots
Browse files Browse the repository at this point in the history
  • Loading branch information
jadiehm committed Sep 23, 2024
1 parent 1271838 commit a9c3d95
Show file tree
Hide file tree
Showing 10 changed files with 241 additions and 54 deletions.
6 changes: 6 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"dependencies": {
"@leveluptuts/svelte-fit": "^1.0.3",
"axios": "^1.6.7",
"d3-regression": "^1.3.10",
"fs": "^0.0.1-security",
"image-download": "^2.1.0",
"image-downloader": "^4.3.0",
Expand Down
3 changes: 0 additions & 3 deletions src/components/Distribution.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@
export let data;
$: console.log({data})
data.forEach(d => {
d[yKey] = +d[yKey];
d[yKey] = +d[yKey];
Expand All @@ -34,7 +32,6 @@
const allWineData = findMatch("all", groupedData)
const onlyAnimalWineData = findMatch("animal wine", groupedData)
console.log(onlyAnimalWineData)
const lineData = allWineData;
const endObj = {animalGroup: "end", category: "end", bucket: "end", percent: 0, count: 0};
Expand Down
87 changes: 46 additions & 41 deletions src/components/Index.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,56 +2,61 @@
import { getContext } from "svelte";
import { animalSelect, metricSelect } from "$stores/misc.js";
import Intro from "$components/Intro.svelte";
// import PhotoTest from "$components/PhotoTest.svelte";
// import Distribution from "$components/Distribution.svelte";
// import Select from "$components/helpers/Select.svelte";
import PhotoTest from "$components/PhotoTest.svelte";
import Distribution from "$components/Distribution.svelte";
import Scatter from "$components/Scatter.svelte";
import Select from "$components/helpers/Select.svelte";
// import wineData_summary from "$data/wineData_summary.csv";
// import wineData_catSummary from "$data/wineData_catSummary.csv";
// import wineData_birdSummary from "$data/wineData_birdSummary.csv";
// import WIP from "$components/helpers/WIP.svelte";
// import Footer from "$components/Footer.svelte";
import allWineData from "$data/wineData.csv"
import wineData_summary from "$data/wineData_summary.csv";
import wineData_catSummary from "$data/wineData_catSummary.csv";
import wineData_birdSummary from "$data/wineData_birdSummary.csv";
import WIP from "$components/helpers/WIP.svelte";
import Footer from "$components/Footer.svelte";
// const copy = getContext("copy");
// const data = getContext("data");
const copy = getContext("copy");
const data = getContext("data");
// let optionsMetric = ["price", "rating"];
// let optionsAnimal = ["all", "cats", "birds"];
let optionsMetric = ["price", "rating"];
let optionsAnimal = ["all", "cats", "birds"];
// function setData($animalSelect, $metricSelect) {
// if ($animalSelect == "birds") {
// if ($metricSelect == "price") {
// return wineData_birdSummary.filter((d) => d.category == "price");
// } else if ($metricSelect == "rating") {
// return wineData_birdSummary.filter((d) => d.category == "rating");
// }
// } else if ($animalSelect == "cats") {
// if ($metricSelect == "price") {
// return wineData_catSummary.filter((d) => d.category == "price");
// } else if ($metricSelect == "rating") {
// return wineData_catSummary.filter((d) => d.category == "rating");
// }
// } else {
// if ($metricSelect == "price") {
// return wineData_summary.filter((d) => d.category == "price");
// } else if ($metricSelect == "rating") {
// return wineData_summary.filter((d) => d.category == "rating");
// }
// }
// }
function setData($animalSelect, $metricSelect) {
if ($animalSelect == "birds") {
if ($metricSelect == "price") {
return wineData_birdSummary.filter((d) => d.category == "price");
} else if ($metricSelect == "rating") {
return wineData_birdSummary.filter((d) => d.category == "rating");
}
} else if ($animalSelect == "cats") {
if ($metricSelect == "price") {
return wineData_catSummary.filter((d) => d.category == "price");
} else if ($metricSelect == "rating") {
return wineData_catSummary.filter((d) => d.category == "rating");
}
} else {
if ($metricSelect == "price") {
return wineData_summary.filter((d) => d.category == "price");
} else if ($metricSelect == "rating") {
return wineData_summary.filter((d) => d.category == "rating");
}
}
}
// $: dataSet = setData($animalSelect, $metricSelect)
$: dataSet = setData($animalSelect, $metricSelect)
// $: dataSet = $animalSelect == "all"
// ? wineData_summary
// : $animalSelect == "cats"
// ? wineData_catSummary
// : wineData_birdSummary;
// $: console.log(dataSet)
</script>

<!-- <div class="selects">
{#if dataSet.length > 0}
{#key dataSet}
<Scatter data={allWineData} />
{/key}
{/if}
<div class="selects">
<Select options={optionsAnimal} id={"id-animalSelect"}/>
<Select options={optionsMetric} id={"id-metricSelect"}/>
</div>
Expand All @@ -61,11 +66,11 @@
{/key}
{/if}

<PhotoTest /> -->
<!-- <WIP />
<Demo /> -->
<PhotoTest />
<WIP />
<!-- <Demo /> -->
<!-- <Footer /> -->
<Intro />
<!-- <Intro /> -->

<style>
.selects {
Expand Down
147 changes: 147 additions & 0 deletions src/components/Scatter.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
<script>
import { onMount } from "svelte";
import { LayerCake, Svg, Html } from 'layercake';
import ScatterSvg from "$components/layercake/Scatter.svg.svelte";
import AxisX from "$components/layercake/AxisX.svg.svelte";
import AxisY from "$components/layercake/AxisY.svg.svelte";
import * as d3 from "d3";
import * as d3Regression from 'd3-regression';
import { tweened } from 'svelte/motion';
import * as eases from 'svelte/easing';
export let data;
const topgroups = ["amphibian/reptile", "bat", "bear", "bird", "camelus", "cat", "cattle",
"deer-like", "dog", "elephant", "fish", "hippo", "horse", "human", "insect",
"marine invertebrate", "marsupial", "monkey", "mustelid-like", "mythical", "none",
"rabbit", "ram-like", "rhino", "rodent-like", "suid", "whale/shark/dolphin"
];
function filterData(animal) {
let filteredData = animal !== "cat"
? data.filter(d => d.topgroup.includes(animal))
: data.filter(d => d.topgroup.includes(animal) && !d.topgroup.includes("cattle"));
return filteredData;
}
const curve = d3.curveLinear;
const yKey = 'price';
const xKey = 'rating';
const xKeyReg = d => +d.rating;
const yKeyReg = d => +d.price;
data.forEach(d => {
d[xKey] = +d[xKey];
d[yKey] = +d[yKey];
});
const r = 4;
const padding = 10;
const color = '#d0c8a8';
const tweenOptions = {
duration: 300,
easing: eases.cubicInOut
};
const xDomain = tweened(undefined, tweenOptions);
const yDomain = tweened(undefined, tweenOptions);
yDomain.set([0,500]);
xDomain.set([2,5]);
// Regression Line
const regression = d3Regression.regressionLinear()
.x(d => xKeyReg(d)) // Define the x accessor
.y(d => yKeyReg(d)); // Define the y accessor
function calcSlope(data) {
let deltaX = data[1].x - data[0].x;
let deltaY = data[1].y - data[0].y;
let slope = deltaY / deltaX;
return slope
}
</script>

<section id="scatter">
{#each topgroups as animal, i}
{@const animalData = filterData(animal)}
{@const trendLine = regression(animalData)}
{@const trendLineData = [
{ x: trendLine[0][0], y: trendLine[0][1] },
{ x: trendLine[1][0], y: trendLine[1][1] }
]}
{@const slope = calcSlope(trendLineData)}
<div class="chart-wrapper">
<h3>{animal}</h3>
<p class="tot-count">{animalData.length} wines</p>
<p class="tot-count">{Math.round(slope)} slope</p>
<div class="chart-container" id="scatterplot" style="pointer-events:none">
<LayerCake
padding={{ top: 10, right: 5, bottom: 20, left: 5 }}
x={xKey}
y={yKey}
xPadding={[padding, padding]}
yPadding={[padding, padding]}
data={[animalData, trendLineData]}
xDomain={$xDomain}
yDomain={$yDomain}
>
<Svg>
<AxisX
gridlines={true}
/>
<AxisY
gridlines={true}
ticks={5} />
<ScatterSvg {r} fill={color} />
</Svg>
</LayerCake>
</div>
</div>
{/each}
</section>

<style>
#scatter {
width: 100%;
height: auto;
display: flex;
flex-direction: row;
flex-wrap: wrap;
margin-bottom: 5rem;
}
.chart-wrapper {
width: 100%;
max-width: 250px;
display: flex;
flex-direction: column;
position: relative;
margin: 2rem;
}
h3 {
font-family: var(--sans);
font-size: var(--14px);
font-weight: 700;
text-align: center;
margin: 0;
}
.tot-count {
font-family: var(--sans);
font-size: var(--14px);
text-align: center;
margin: 0 0;
font-size: 0.8rem;
}
.chart-container {
width: 100%;
height: 250px;
overflow: hidden;
}
</style>
9 changes: 5 additions & 4 deletions src/components/layercake/AxisX.svg.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,14 @@
transform="translate({tickCheck(tick, i, $width)},{$yRange[0]})"
>
{#if gridlines !== false}
<line class="gridline" y1={$height * -1} y2="0" x1="0" x2="0" />
<line class="gridline" y1="{$height * -1}" y2="0" x1="0" x2="0" />
{/if}
{#if tickMarks === true}
<line class="tick-mark" y1={0} y2={6} x1={0} x2={0} />
{/if}
<!-- <text x={0} y={yTick} dx="" dy="" text-anchor={textAnchor(i)}
<text x={0} y={yTick} dx="" dy="" text-anchor={textAnchor(i)}
>{formatTick(tick)}</text
> -->
>
</g>
{/each}
{#if baseline === true}
Expand All @@ -75,11 +75,12 @@
line,
.tick line {
stroke: var(--color-gray-300);
stroke-dasharray: 2;
stroke-dasharray: 2px 2px;
}
.tick text {
fill: var(--color-gray-600);
font-family: var(--sans);
}
.tick .tick-mark,
Expand Down
3 changes: 2 additions & 1 deletion src/components/layercake/AxisY.svg.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,11 @@
stroke: var(--color-gray-300);
}
.tick .gridline {
stroke-dasharray: 4px 4px;
stroke-dasharray: 2px 2px;
}
.tick text {
fill: var(--color-gray-600);
font-family: var(--sans);
}
</style>
3 changes: 1 addition & 2 deletions src/components/layercake/Line.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@
import { getContext } from "svelte";
import { line, curveLinear, curveStepAfter } from "d3";
const { data, xGet, yGet } = getContext("LayerCake");
const { data, xGet, yGet, xScale, } = getContext("LayerCake");
export let stroke = "#000000";
export let curve = curveStepAfter;
$: path = line().x($xGet).y($yGet).curve(curve);
$: pathD = path($data);
</script>
Expand Down
Loading

0 comments on commit a9c3d95

Please sign in to comment.