Filter data by searching. Results match all terms.
Select individual rows with floating checkboxes next to the first column. Sort the table by clicking column heads.
Filter data by searching. Results match all terms.
Select individual rows with floating checkboxes next to the first column. Sort the table by clicking column heads.
Plot.plot({
facet: {
data: filtered,
x: scatterFacetX,
y: scatterFacetY,
marginRight: 80
},
grid: false,
symbol: ((scatterFill !== "") && (fillType === 'string')) ?
{
legend: true,
tickFormat: formatLabel,
label: formatLabel(scatterFill),
} : [],
color: ((scatterFill !== "") && (fillType === 'number')) ?
{
legend: true,
tickFormat: formatLabel,
label: formatLabel(scatterFill),
} : [],
marginTop: 36, // more room for facets
marginBottom: 48,
marks: [
Plot.axisX({ // Axis with just the ticks in the default fontSize
label: null,
// ticks: (scatterFacetX !== "") ? 4 : 8,
}),
Plot.axisX({ // Axis with just the label in custom fontSize
label: formatLabel(scatterX),
fontSize: largeFontSize,
labelOffset: 36,
ticks: [],
}),
(scatterFacetX !== "") ? Plot.axisFx({ // Facet axis with just the ticks
label: null,
tickFormat: formatLabel,
}) : [],
(scatterFacetX !== "") ? Plot.axisFx({ // Facet axis with just the label
label: formatLabel(scatterFacetX),
fontSize: largeFontSize,
ticks: [ ],
}) : [],
Plot.axisY({ // Axis with just the ticks in the default fontSize
label: null,
// ticks: (scatterFacetX !== "") ? 4 : 8,
}),
Plot.axisY({ // Axis with just the label in the custom fontSize
label: formatLabel(scatterY),
fontSize: largeFontSize,
labelOffset: 36,
ticks: [],
}),
(scatterFacetY !== "") ? Plot.axisFy({ // Facet axis with just the ticks
label: null,
tickFormat: formatLabel,
}) : [],
(scatterFacetY !== "") ? Plot.axisFy({ // Facet axis with just the label
label: formatLabel(scatterFacetY),
labelAnchor: "top",
fontSize: largeFontSize,
ticks: [ ],
}) : [],
(scatterRegr=="Line")?Plot.linearRegressionY(
filtered, {
x: scatterX,
y: scatterY,
stroke: scatterRegrFill,
ci: 0}):[],
(scatterRegr=="± 95% CI")?Plot.linearRegressionY(
filtered, {
x: scatterX,
y: scatterY,
stroke: scatterRegrFill,
ci: 0.95}):[],
(scatterGrpRegr=="Line")?Plot.linearRegressionY(
filtered, {
x: scatterX,
y: scatterY,
stroke: scatterFill,
ci: 0}):[],
(scatterGrpRegr=="± 95% CI")?Plot.linearRegressionY(
filtered, {
x: scatterX,
y: scatterY,
stroke: scatterFill,
ci: 0.95}):[],
Plot.dot(
filtered, {
x: scatterX,
y: scatterY,
fill: (scatterFill !== "") ? scatterFill : "steelblue",
opacity: scatterOpacity,
symbol: ((scatterFill !== "") && (fillType === 'string')) ? scatterFill : "steelblue"}),
(scatterFacetX !== "" || scatterFacetY !== "") ?
Plot.frame() : null,
],
height: scatterHeight,
width: scatterWidth,
marginLeft: 60
});
html
`<div id="scatterEditor" autocorrect="off" spellcheck="false">
<p>Figure #. <b>Title.</b></p><p>Caption.</p>
</div>`
myHisto = Plot.plot({
height: histoHeight,
width: histoWidth,
y: {grid: true},
// figure: true,
facet: {
data: filtered,
x: histFacetX,
y: histFacetY,
marginRight: 80
},
color: {
legend: true,
label: formatLabel(histoFill),
tickFormat: formatLabel,
},
marginTop: 36, // more room for facets
marginBottom: 48,
marks: [
Plot.axisX({ // Axis with just the ticks in the default fontSize
label: null,
}),
Plot.axisX({ // Axis with just the label in custom fontSize
label: formatLabel(histoX),
fontSize: largeFontSize,
labelOffset: 36,
ticks: [],
}),
(histFacetX !== "") ? Plot.axisFx({ // Facet axis with just the ticks
label: null,
tickFormat: formatLabel,
}) : [],
(histFacetX !== "") ? Plot.axisFx({ // Facet axis with just the label
label: formatLabel(histFacetX),
fontSize: largeFontSize,
ticks: [ ],
}) : [],
Plot.axisY({ // Axis with just the ticks in the default fontSize
label: null,
}),
Plot.axisY({ // Axis with just the label in the custom fontSize
label: formatLabel(histoY),
fontSize: largeFontSize,
labelOffset: 36,
ticks: [],
}),
(histFacetY !== "") ? Plot.axisFy({ // Facet axis with just the ticks
label: null,
tickFormat: formatLabel,
}) : [],
(histFacetY !== "") ? Plot.axisFy({ // Facet axis with just the label
label: formatLabel(histFacetY),
labelAnchor: "top",
fontSize: largeFontSize,
ticks: [ ],
}) : [],
Plot.rectY(filtered,
Plot.binX({y: histoY},
{x: histoX,
fill: (histoFill !== "") ? histoFill : "steelblue",
opacity: histoOpacity,
thresholds: 20}
)
),
// Mean and SE marks
( (histoStats == "± SE") || (histoStats == "± 95% CI") )?
Plot.dot(filtered,
Plot.groupY(
{x: "mean"},
{x: histoX,
y: 0,
fill: (histoFill !== "") ? histoFill : "black",
r: 5}
)) : [],
(histoStats == "± SE") ?
Plot.link(filtered,
Plot.groupY({
x1: (filtered) => d3.mean(filtered)
- d3.deviation(filtered)/Math.sqrt(d3.count(filtered)),
x2: (filtered) => d3.mean(filtered)
+ d3.deviation(filtered)/Math.sqrt(d3.count(filtered))
},
{x: histoX,
y: 0,
stroke: (histoFill !== "") ? histoFill : "black",
strokeWidth: 3}
)) : [],
(histoStats == "± 95% CI") ?
Plot.link(filtered,
Plot.groupY({
x1: (filtered) => d3.mean(filtered)
- 1.96*d3.deviation(filtered)/Math.sqrt(d3.count(filtered)),
x2: (filtered) => d3.mean(filtered)
+ 1.96*d3.deviation(filtered)/Math.sqrt(d3.count(filtered))
},
{x: histoX,
y: 0,
stroke: (histoFill !== "") ? histoFill : "black",
strokeWidth: 3}
)) : [],
// Plot.ruleY([0])
]
});
html
`<div id="histoEditor" autocorrect="off" spellcheck="false">
<p>Figure #. <b>Title.</b></p><p>Caption.</p>
</div>`
( ((stripOrient == "Vertical ┋") && (stripX == stripDotFill)) ||
((stripOrient == "Horizontal ┉") && (stripY == stripDotFill)) ) ?
// Big IF stripDotFill is the same as the main x or y variable
// No subplots needed
Plot.plot({
axis: null, // Will specify these in detail with axis marks
symbol:
{
legend: true,
tickFormat: formatLabel,
label: formatLabel(stripDotFill),
},
facet: {
marginRight: (stripOrient == "Horizontal ┉") ? 90 : [],
},
height: stripHeight,
insetTop: ((stripOrient == "Horizontal ┉") &&
(dotsJitterOrDodge == "Jitter")) ?
10 : [],
insetBottom: ((stripOrient == "Horizontal ┉") &&
(dotsJitterOrDodge == "Jitter")) ?
10 : [],
insetLeft: ((stripOrient == "Vertical ┋") &&
(dotsJitterOrDodge == "Jitter")) ?
10 : [],
insetRight: ((stripOrient == "Vertical ┋") &&
(dotsJitterOrDodge == "Jitter")) ?
10 : [],
// marginTop: 36, // more room for facets
marginBottom: 42,
marks: [
// Axis marks
(stripOrient == "Vertical ┋") ? // Main axis w/o label
Plot.axisY({
label: null,
}) :
Plot.axisX({
label: null,
}),
(stripOrient == "Vertical ┋") ? // Main axis label, large font
Plot.axisY({
label: formatLabel(stripY),
fontSize: largeFontSize,
labelOffset: 36,
ticks: [],
}) :
Plot.axisX({
label: formatLabel(stripX),
fontSize: largeFontSize,
labelOffset: 36,
ticks: [],
}),
(stripOrient == "Vertical ┋") ? // Facet axis w/o label
Plot.axisFx({
anchor: "bottom",
label: null,
tickFormat: formatLabel,
}) :
Plot.axisFy({
label: null,
tickFormat: formatLabel,
}),
(stripOrient == "Vertical ┋") ? // Facet axis label, large font
Plot.axisFx({
anchor: "bottom",
label: formatLabel(stripX),
fontSize: largeFontSize,
ticks: [],
}) :
Plot.axisFy({
label: formatLabel(stripY),
labelAnchor: "top",
fontSize: largeFontSize,
ticks: [],
}),
// Grid marks
(stripOrient == "Vertical ┋") ?
Plot.gridY({}) :
Plot.gridX({}),
// Box marks
((stripOrient == "Vertical ┋") && (stripStats == "BoxPlot")) ?
Plot.boxY(filtered,
{fx: stripX,
y: stripY,
fill: "gray",
fillOpacity: 0.35,
stroke: "gray"}) : [],
((stripOrient == "Horizontal ┉") && (stripStats == "BoxPlot")) ?
Plot.boxX(filtered,
{fy: stripY,
x: stripX,
fill: "gray",
fillOpacity: 0.35,
stroke: "gray"}) : [],
// Jitter marks
((stripOrient == "Vertical ┋") && (dotsJitterOrDodge == "Jitter")) ?
Plot.dot(filtered, {
fx: stripX,
x: Math.random,
y: stripY,
fill: stripDotFill,
opacity: dotsOpacity,
symbol: stripDotFill,
}) : [],
((stripOrient == "Horizontal ┉") && (dotsJitterOrDodge == "Jitter")) ?
Plot.dot(filtered, {
axis: null,
x: stripX,
fy: stripY,
y: Math.random,
fill: stripDotFill,
opacity: dotsOpacity,
symbol: stripDotFill,
}) : [],
// Dodge marks
((stripOrient == "Vertical ┋") && (dotsJitterOrDodge == "Dodge")) ?
Plot.dot(filtered,
Plot.dodgeX("middle", {
fx: stripX,
y: stripY,
fill: stripDotFill,
opacity: dotsOpacity,
symbol: stripDotFill,})) : [],
((stripOrient == "Horizontal ┉") && (dotsJitterOrDodge == "Dodge")) ?
Plot.dot(filtered, // Horizontal
Plot.dodgeY("middle", {
fy: stripY,
x: stripX,
fill: stripDotFill,
opacity: dotsOpacity,
symbol: stripDotFill,})) : [],
// Mean and SE marks
((stripOrient == "Vertical ┋") && (stripStats == "Mean ± SE")) ?
Plot.dot(
filtered,
Plot.groupX(
{y: "mean"},
{y: stripY,
fx: stripX,
x: 0.5,
fill: "black",
r: 5}
)) : [],
((stripOrient == "Vertical ┋") && (stripStats == "Mean ± SE")) ?
Plot.link(filtered,
Plot.groupX({
y1: (filtered) => d3.mean(filtered)
- d3.deviation(filtered)/Math.sqrt(d3.count(filtered)),
y2: (filtered) => d3.mean(filtered)
+ d3.deviation(filtered)/Math.sqrt(d3.count(filtered))
},
{y: stripY,
fx: stripX,
x: 0.5,
stroke: "black",
strokeWidth: 2}
)) : [],
((stripOrient == "Horizontal ┉") && (stripStats == "Mean ± SE")) ?
Plot.dot(filtered,
Plot.groupY(
{x: "mean"},
{x: stripX,
fy: stripY,
y: 0.5,
fill: "black",
r: 5}
)) : [],
((stripOrient == "Horizontal ┉") && (stripStats == "Mean ± SE")) ?
Plot.link(filtered,
Plot.groupY({
x1: (filtered) => d3.mean(filtered)
- d3.deviation(filtered)/Math.sqrt(d3.count(filtered)),
x2: (filtered) => d3.mean(filtered)
+ d3.deviation(filtered)/Math.sqrt(d3.count(filtered))
},
{x: stripX,
fy: stripY,
y: 0.5,
stroke: "black",
strokeWidth: 3}
)) : [],
// Mean and confidence interval marks
((stripOrient == "Vertical ┋") && (stripStats == "Mean ± 95% CI")) ?
Plot.dot(
filtered,
Plot.groupX(
{y: "mean"},
{y: stripY,
fx: stripX,
x: 0.5,
fill: "black",
r: 5}
)) : [],
((stripOrient == "Vertical ┋") && (stripStats == "Mean ± 95% CI")) ?
Plot.link(filtered,
Plot.groupX({
y1: (filtered) => d3.mean(filtered)
- 1.96*d3.deviation(filtered)/Math.sqrt(d3.count(filtered)),
y2: (filtered) => d3.mean(filtered)
+ 1.96*d3.deviation(filtered)/Math.sqrt(d3.count(filtered))
},
{y: stripY,
fx: stripX,
x: 0.5,
stroke: "black",
strokeWidth: 2}
)) : [],
((stripOrient == "Horizontal ┉") && (stripStats == "Mean ± 95% CI")) ?
Plot.dot(filtered,
Plot.groupY(
{x: "mean"},
{x: stripX,
fy: stripY,
y: 0.5,
fill: "black",
r: 5}
)) : [],
((stripOrient == "Horizontal ┉") && (stripStats == "Mean ± 95% CI")) ?
Plot.link(filtered,
Plot.groupY({
x1: (filtered) => d3.mean(filtered)
- 1.96*d3.deviation(filtered)/Math.sqrt(d3.count(filtered)),
x2: (filtered) => d3.mean(filtered)
+ 1.96*d3.deviation(filtered)/Math.sqrt(d3.count(filtered))
},
{x: stripX,
fy: stripY,
y: 0.5,
stroke: "black",
strokeWidth: 3}
)) : [],
],
width: stripWidth
})
// Big ELSE stripDotFill is the NOT same as the main x or y variable
// Subplots needed. Subplots implemented using undocumented render
// transform, as demonstrated by the extraordinary Fil:
// https://observablehq.com/@fil/subplots-1870
// see also: https://observablehq.com/@observablehq/plot-of-plots
:
Plot.plot({
height: stripHeight,
width: stripWidth,
marginLeft: (stripOrient == "Horizontal ┉") ? 80 : 40,
marginRight: (stripOrient == "Horizontal ┉") ? 80 : [],
marginBottom: 36,
marginTop: 36,
symbol:
{ legend: true,
tickFormat: formatLabel,
label: formatLabel(stripDotFill),
},
x: (stripOrient == "Horizontal ┉") ?
{ domain: [Math.min(...Plot.valueof(filtered, stripX)),
Math.max(...Plot.valueof(filtered, stripX))],
} : [],
y: (stripOrient == "Vertical ┋") ?
{ domain: [Math.min(...Plot.valueof(filtered, stripY)),
Math.max(...Plot.valueof(filtered, stripY))],
} : [],
fx: (stripOrient == "Horizontal ┉") ?
{ axis: null } : [], // Will set with axis mark
fy: (stripOrient == "Vertical ┋") ?
{ axis: null } : [], // Will set with axis mark
marks: [
// Grid and axis marks
(stripOrient == "Vertical ┋") ? Plot.gridY() : Plot.gridX(),
(stripOrient == "Horizontal ┉") ?
Plot.axisFy({
label: formatLabel(stripY),
fontSize: largeFontSize,
labelAnchor: "top",
ticks: [],
}) : [],
(stripOrient == "Vertical ┋") ?
Plot.axisFx({
label: formatLabel(stripX),
fontSize: largeFontSize,
ticks: [],
}) : [],
(stripOrient == "Horizontal ┉") ?
Plot.axisFy({
label: null,
tickFormat: formatLabel,
}) : [],
(stripOrient == "Vertical ┋") ?
Plot.axisFx({
label: null,
tickFormat: formatLabel,
}) : [],
(stripOrient == "Horizontal ┉") ?
Plot.axisX({
label: formatLabel(stripX),
fontSize: largeFontSize,
labelOffset: 36,
ticks: [],
}) : [],
(stripOrient == "Vertical ┋") ?
Plot.axisY({
label: formatLabel(stripY),
fontSize: largeFontSize,
labelOffset: 36,
ticks: [],
}) : [],
(stripOrient == "Horizontal ┉") ?
Plot.axisX({
label: null,
tickFormat: formatLabel,
}) : [],
(stripOrient == "Vertical ┋") ?
Plot.axisY({
label: null,
tickFormat: formatLabel,
}) : [],
// This Kluge puts symbols in the color legend
Plot.dot(filtered, {
fill: stripDotFill,
symbol: stripDotFill,
}),
// Text marks - Where the subplots are
(stripOrient == "Horizontal ┉") ?
Plot.text(getUniqueValsOfColumn(filtered, stripY), {
frameAnchor: "middle",
text: Plot.identity,
fy: Plot.identity, // facets vertically by stripY
render([i], { scales }, { channels }, dimensions) {
return svg`<g>${
Plot.plot({
...dimensions,
...scales,
x: { ...scales.x, axis: null },
y: { axis: null },
fy: { axis: null },
marks:[
// Axis marks
Plot.axisFy({
anchor: "left",
tickFormat: formatLabel,
label: formatLabel(stripDotFill),
}),
// Box marks
(stripStats == "BoxPlot") ?
Plot.boxX(filtered, {
filter: (d) => d[stripY] === channels.text.value[i],
fy: stripDotFill,
x: stripX,
// fill: stripStatsColor,
fill: "gray",
fillOpacity: 0.35,
stroke: "gray"}) : [],
// Dot marks -- Jitter
(dotsJitterOrDodge == "Jitter") ?
Plot.dot(filtered, {
filter: (d) => d[stripY] === channels.text.value[i],
fy: stripDotFill,
y: Math.random,
x: stripX,
fill: stripDotFill,
opacity: dotsOpacity,
symbol: stripDotFill,
}) : [],
// Dot marks -- Dodge
(dotsJitterOrDodge == "Dodge") ?
Plot.dot(filtered,
Plot.dodgeY("middle", {
filter: (d) => d[stripY] === channels.text.value[i],
fy: stripDotFill,
x: stripX,
fill: stripDotFill,
opacity: dotsOpacity,
symbol: stripDotFill,
})) : [],
// Mean marks
((stripStats == "Mean ± SE") || (stripStats == "Mean ± 95% CI")) ?
Plot.dot(
filtered,
Plot.groupY(
{x: "mean"},
{
filter: (d) => d[stripY] === channels.text.value[i],
x: stripX,
fy: stripDotFill,
y: 0.5,
fill: "black",
r: 5
}
)) : [],
// SE marks
(stripStats == "Mean ± SE") ?
Plot.link(filtered,
Plot.groupY({
x1: (filtered) => d3.mean(filtered)
- d3.deviation(filtered)/Math.sqrt(d3.count(filtered)),
x2: (filtered) => d3.mean(filtered)
+ d3.deviation(filtered)/Math.sqrt(d3.count(filtered))
},
{
filter: (d) => d[stripY] === channels.text.value[i],
x: stripX,
fy: stripDotFill,
y: 0.5,
stroke: "black",
strokeWidth: 2}
)) : [],
// 95% CI marks
(stripStats == "Mean ± 95% CI") ?
Plot.link(filtered,
Plot.groupY({
x1: (filtered) => d3.mean(filtered)
- 1.96*d3.deviation(filtered)/Math.sqrt(d3.count(filtered)),
x2: (filtered) => d3.mean(filtered)
+ 1.96*d3.deviation(filtered)/Math.sqrt(d3.count(filtered))
},
{
filter: (d) => d[stripY] === channels.text.value[i],
x: stripX,
fy: stripDotFill,
y: 0.5,
stroke: "black",
strokeWidth: 2}
)) : [],
]
})
}`;
}
}) : [],
// Text marks - Where the subplots are
(stripOrient == "Vertical ┋") ?
Plot.text(getUniqueValsOfColumn(filtered, stripX), {
frameAnchor: "middle",
text: Plot.identity,
fx: Plot.identity, // facets vertically by stripX
render([i], { scales }, { channels }, dimensions) {
return svg`<g>${
Plot.plot({
...dimensions,
...scales,
insetLeft: 4,
insetRight: 4,
y: { ...scales.y, axis: null },
x: { axis: null },
fx: { axis: null },
marks:[
// Axis marks
Plot.axisFx({
anchor: "bottom",
label: formatLabel(stripDotFill),
tickFormat: formatLabel,
}),
// Box marks
(stripStats == "BoxPlot") ?
Plot.boxY(filtered, {
filter: (d) => d[stripX] === channels.text.value[i],
fx: stripDotFill,
y: stripY,
fill: "gray",
fillOpacity: 0.35,
stroke: "gray"}) : [],
// Dot marks -- Jitter
(dotsJitterOrDodge == "Jitter") ?
Plot.dot(filtered, {
filter: (d) => d[stripX] === channels.text.value[i],
fx: stripDotFill,
x: Math.random,
y: stripY,
fill: stripDotFill,
opacity: dotsOpacity,
symbol: stripDotFill,
}) : [],
// Dot marks -- Dodge
(dotsJitterOrDodge == "Dodge") ?
Plot.dot(filtered,
Plot.dodgeX("middle", {
filter: (d) => d[stripX] === channels.text.value[i],
fx: stripDotFill,
y: stripY,
fill: stripDotFill,
opacity: dotsOpacity,
symbol: stripDotFill,
})) : [],
// Mean marks
((stripStats == "Mean ± SE") || (stripStats == "Mean ± 95% CI")) ?
Plot.dot(
filtered,
Plot.groupX(
{y: "mean"},
{
filter: (d) => d[stripX] === channels.text.value[i],
y: stripY,
fx: stripDotFill,
x: 0.5,
fill: "black",
r: 5
}
)) : [],
// SE marks
(stripStats == "Mean ± SE") ?
Plot.link(filtered,
Plot.groupX({
y1: (filtered) => d3.mean(filtered)
- d3.deviation(filtered)/Math.sqrt(d3.count(filtered)),
y2: (filtered) => d3.mean(filtered)
+ d3.deviation(filtered)/Math.sqrt(d3.count(filtered))
},
{
filter: (d) => d[stripX] === channels.text.value[i],
y: stripY,
fx: stripDotFill,
x: 0.5,
stroke: "black",
strokeWidth: 2}
)) : [],
// 95% CI marks
(stripStats == "Mean ± 95% CI") ?
Plot.link(filtered,
Plot.groupX({
y1: (filtered) => d3.mean(filtered)
- 1.96*d3.deviation(filtered)/Math.sqrt(d3.count(filtered)),
y2: (filtered) => d3.mean(filtered)
+ 1.96*d3.deviation(filtered)/Math.sqrt(d3.count(filtered))
},
{
filter: (d) => d[stripX] === channels.text.value[i],
y: stripY,
fx: stripDotFill,
x: 0.5,
stroke: "black",
strokeWidth: 2}
)) : [],
]
})
}`;
}
}) : [],
]
})
;
html
`<div id="stripEditor" autocorrect="off" spellcheck="false">
<p>Figure #. <b>Title.</b></p><p>Caption.</p>
</div>`
chart = {
const mData = getMarimekkoData(filtered, barXVar, barFill, barFacetX, barFacetY);
// From https://observablehq.com/@observablehq/plot-marimekko
const xy = (options) => marimekko({...options,
x: "mXVar",
y: "mYVar",
value: "mVal"});
// THE BIG IF ELSE
// Bar chart or marimekko
return (barCountsOrPercentages == "Bar") ? // THE BIG IF - Bar chart
Plot.plot({
// marginLeft: 60,
// x: {label: barXVar},
// y: {label: "Count"},
facet: {
data: filtered,
x: barFacetX,
y: barFacetY,
marginRight: 80,
// marginTop: 36,
},
fx: {
label: formatLabel(barFacetX),
},
fy: {
label: formatLabel(barFacetY),
},
color: {legend: true, tickFormat: formatLabel},
marginTop: 35, // more room for facets
marginBottom: 48,
marks: [
// Axis marks
Plot.axisX({ // Axis with just the ticks in the default fontSize
label: null,
tickFormat: formatLabel,
}),
Plot.axisX({ // Axis with just the label in custom fontSize
label: formatLabel(barXVar),
fontSize: largeFontSize,
labelOffset: 36,
ticks: [],
}),
(barFacetX !== "") ? Plot.axisFx({ // Facet axis with just the ticks
label: null,
tickFormat: formatLabel,
}) : [],
(barFacetX !== "") ? Plot.axisFx({ // Facet axis with just the label
label: formatLabel(barFacetX),
fontSize: largeFontSize,
ticks: [ ],
}) : [],
Plot.axisY({ // Axis with just the ticks in the default fontSize
label: null,
}),
Plot.axisY({ // Axis with just the label in the custom fontSize
label: "Count",
fontSize: largeFontSize,
labelOffset: 36,
ticks: [],
}),
(barFacetY !== "") ? Plot.axisFy({ // Facet axis with just the ticks
label: null,
tickFormat: formatLabel,
}) : [],
(barFacetY !== "") ? Plot.axisFy({ // Facet axis with just the label
label: formatLabel(barFacetY),
labelAnchor: "top",
fontSize: largeFontSize,
ticks: [ ],
}) : [],
// Bars
Plot.barY(
filtered,
Plot.groupX({y: "count"},
{x: barXVar, fill: barFill, opacity: barOpacity}
)),
],
height: barChartHeight,
width: barChartWidth,
})
: // The big ELSE - marimekko
Plot.plot({
width: barChartWidth,
height: barChartHeight,
label: null,
facet: {data: mData,
x: "mFXVar",
y: "mFYVar",
marginRight: 80},
fx: {padding: 0.12},
fy: {padding: 0.12},
color: {legend: true, tickFormat: formatLabel},
marginTop: 35,
marginBottom: 48,
x: {percent: true},
y: {percent: true, ticks: 0, tickFormat: (d) => d === 100 ? `100%` : d},
marks: [
Plot.frame({opacity: 0.25}),
// Added these
Plot.axisX({ // Axis with just the ticks in the default fontSize
label: null,
ticks: (barFacetX == "") ? 10 : 5,
tickFormat: (d) => d === 100 ? `100%` : d
}),
Plot.axisX({ // Axis with just the label in custom fontSize
label: formatLabel(barXVar),
fontSize: largeFontSize,
labelOffset: 36,
ticks: [],
}),
(barFacetX !== "") ? Plot.axisFx({ // Facet axis with just the ticks
label: null,
tickFormat: formatLabel,
}) : [],
(barFacetX !== "") ? Plot.axisFx({ // Facet axis with just the label
label: formatLabel(barFacetX),
fontSize: largeFontSize,
ticks: [ ],
}) : [],
(barXVar !== barFill) ?
Plot.axisY({ // Axis with just the ticks in the default fontSize
label: null,
ticks: (barFacetY == "") ? 10 : 5,
tickFormat: (d) => d === 100 ? `100%` : d
}) : [],
(barXVar !== barFill) ?
Plot.axisY({ // Axis with just the label in the custom fontSize
label: formatLabel(barFill),
fontSize: largeFontSize,
labelOffset: 36,
ticks: [],
}) : [],
(barFacetY !== "") ? Plot.axisFy({ // Facet axis with just the ticks
label: null,
tickFormat: formatLabel,
}) : [],
(barFacetY !== "") ? Plot.axisFy({ // Facet axis with just the label
label: formatLabel(barFacetY),
labelAnchor: "top",
fontSize: largeFontSize,
ticks: [ ],
}) : [],
Plot.rect(mData, xy({fill: "mYVar", fillOpacity: barOpacity})),
// Added 'formatLabel' ×3; made conditional on d.mVal > 0; conditional on barFill ≠ barXVar
Plot.text(mData, xy({text: d => (d.mVal > 0) ?
[formatLabel(d.mVal.toLocaleString("en")),
(barFill !== barXVar) ?
"y: " + formatLabel(d.mYVar) : formatLabel(d.mYVar),
(barFill !== barXVar) ?
"x: " + formatLabel(d.mXVar)
:
""
].join("\n") : "" })),
// Plot.text(mData, Plot.selectMaxX(xy({z: "mYVar", text: "mYVar", anchor: "right", textAnchor: "middle", lineAnchor: "bottom", rotate: 90, dx: 6}))),
// Made conditional on mData.mYVar !== mData.mXVar -- but it's redunant, because axis label is handled elsewhere.
// (mData.mYVar !== mData.mXVar) ? Plot.text(mData, Plot.selectMaxY(xy({z: "mXVar", text: "mXVar", anchor: "top", lineAnchor: "bottom", dy: -6}))) : [],
]
});
};
html
`<div id="barEditor" autocorrect="off" spellcheck="false">
<p>Figure #. <b>Title.</b></p><p>Caption.</p>
</div>`
ardeaPlot is inspired by SimBio’s GraphSmarts Assessements and by easyPlot. It is made with:
Sources for built-in datasets:
Palmer Penguins — observations with missing data (NA) have been removed.
Elephants: Mduduzi Ndlovu et al. 2018
Primates and carnivores: Daniel L. Bowling et al. 2020
Hurricane lizards one: Colin M. Donihue et al. 2018
Hurricane lizards two: Colin M. Donihue et al. 2020
d3 = require("d3@7");
Quill = require("https://cdn.jsdelivr.net/npm/quill@2.0.3/dist/quill.js");
// Global variables
largeFontSize = 13;
myColors = ["black", "gray", "lightgray", "steelblue", "darkseagreen"];
// Functions used across pages
function formatLabel(myString) {
if ((typeof myString !== "string") || (myString === "pH")){
return myString;
} else if ( (myString == null) || (myString.length === 0) ) {
return "";
} else {
myString = myString.replaceAll("_", " ");
return myString.charAt(0).toUpperCase() + myString.slice(1);
};
};
/* Old versions of getCategoricalColumns and getNumericalColumns
function getCategoricalColumns(data) {
const categoricalColumns = [];
if (data.length > 0) {
const firstRow = data[0];
for (const columnName in firstRow) {
if (typeof firstRow[columnName] === 'string') {
categoricalColumns.push(columnName);
}
}
}
return categoricalColumns;
};
function getNumericalColumns(data) {
if (!data || data.length === 0) {
return [];
}
const numericalColumns = [];
const firstRow = data[0];
for (const key in firstRow) {
if (typeof firstRow[key] === 'number') {
numericalColumns.push(key);
}
}
return numericalColumns;
};
*/
function getCategoricalColumns(data) {
if (!data || data.length === 0) {
return [];
};
const categoricalColumns = [];
const dataKeys = Object.keys(data[0]);
for (let i = 0; i < dataKeys.length; i++) {
let j = 0;
let myType = undefined;
while ( (j < data.length) && (myType !== 'string' ) && (myType !== 'number') ) {
myType = typeof data[j][dataKeys[i]];
j++;
};
if (myType === 'string') {
categoricalColumns.push(dataKeys[i]);
};
};
return categoricalColumns;
};
function getNumericalColumns(data) {
if (!data || data.length === 0) {
return [];
};
const numericalColumns = [];
const dataKeys = Object.keys(data[0]);
for (let i = 0; i < dataKeys.length; i++) {
let j = 0;
let myType = undefined;
while ( (j < data.length) && (myType !== 'string' ) && (myType !== 'number') ) {
myType = typeof data[j][dataKeys[i]];
j++;
};
if (myType === 'number') {
numericalColumns.push(dataKeys[i]);
};
};
return numericalColumns;
};
// May replicate Plot.valueof
function columnToArray(data, column) {
return data.map((row) => row[column]);
};
function getUniqueVals(array) {
return array.filter((value, index, self) => self.indexOf(value) === index);
};
function getUniqueValsOfColumn(data, column) {
return getUniqueVals(columnToArray(data, column));
};
function set(input, value) {
input.value = value;
input.dispatchEvent(new Event("input", {bubbles: true}));
};
populateWithOptions = function(myArray, defIndex) {
const returnArray = [];
for (let i = 0; i < myArray.length; i++) {
if (i == defIndex) {
returnArray.push("<option value='" + myArray[i] + "' selected>" + formatLabel(myArray[i]) + "</option>")
} else {
returnArray.push("<option value='" + myArray[i] + "'>" + formatLabel(myArray[i]) + "</option>")
};
};
return returnArray;
};
function quillDisplay(myBoolean, myElement) {
const elem = document.getElementById(myElement);
if (myBoolean == true) {
elem.style.display = "block";
} else {
elem.style.display = "none";
};
};
function quillResetText(myQuill) {
myQuill.setContents([
{ insert: 'Figure #. ' },
{ insert: 'Title', attributes: { bold: true } },
{ insert: '\n' },
{ insert: 'Caption.' },
{ insert: '\n' },
]);
};
function quillSetWidth(myNum, myElement) {
const elem = document.getElementById(myElement);
const myString = myNum.toString().concat("px");
elem.style.width = myString;
};