]> pintos-os.org Git - pspp/commitdiff
work on labeling
authorBen Pfaff <blp@cs.stanford.edu>
Fri, 15 May 2026 20:52:59 +0000 (13:52 -0700)
committerBen Pfaff <blp@cs.stanford.edu>
Fri, 15 May 2026 20:52:59 +0000 (13:52 -0700)
rust/Cargo.lock
rust/doc/src/spv/graphs.md
rust/pspp/Cargo.toml
rust/pspp/src/output/pivot/tests.rs
rust/pspp/src/spv/read/graph.rs
rust/pspp/src/spv/testdata/graph1.expected.svg
rust/pspp/src/spv/testdata/graph2.expected.svg
rust/pspp/src/spv/testdata/graph3.expected.svg
rust/pspp/src/spv/testdata/graph4.expected.svg
rust/pspp/src/spv/testdata/graph5.expected.svg

index 2e386e7ac357d0779e501c41f83f29a3bffd8bdf..4f11c99691d4759223d35f3c37832ed289d310fb 100644 (file)
@@ -284,6 +284,16 @@ dependencies = [
  "generic-array",
 ]
 
+[[package]]
+name = "bstr"
+version = "1.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab"
+dependencies = [
+ "memchr",
+ "serde",
+]
+
 [[package]]
 name = "btree_monstrousity"
 version = "0.0.5"
@@ -2521,6 +2531,7 @@ dependencies = [
  "serde",
  "serde_json",
  "serde_path_to_error",
+ "similar",
  "smallstr",
  "smallvec",
  "svg",
@@ -2981,6 +2992,15 @@ version = "0.3.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
 
+[[package]]
+name = "similar"
+version = "3.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "04d93e861ede2e497b47833469b8ec9d5c07fa4c78ce7a00f6eb7dd8168b4b3f"
+dependencies = [
+ "bstr",
+]
+
 [[package]]
 name = "siphasher"
 version = "1.0.2"
index 909db531d0c0968d0fd471a372cd3ee72ec659cd..bfc0d75348e373410acc0ec0ef5e78497ed35cf3 100644 (file)
@@ -932,3 +932,7 @@ Rotated weird text chart with multiple facetLevels:
 
 Normal-ish barchart with multiple facetLevels:
 /home/blp/pspp/spv/spv/9538e0d28ff95b21336ea19a551affca/00000000072_2564001948504162306_chart.xml
+
+# To-Do
+
+* Weighting with `weight="true"`
index 09100e97f51cea66c43d1d85183fa632e137144c..d3fbf3159bad8536bf018157454d379dbb9535f2 100644 (file)
@@ -88,3 +88,4 @@ path = "src/lib.rs"
 approx = "0.5.1"
 diff = "0.1.13"
 rand = "0.9.0"
+similar = "3.1.0"
index ea56516202e97f8d36423bcff4b0b43a1c266ca6..e772191da67836f524487a36fac076479fd125d5 100644 (file)
@@ -17,6 +17,7 @@
 use std::{fmt::Display, fs::File, path::Path, sync::Arc};
 
 use enum_map::EnumMap;
+use similar::TextDiff;
 
 use crate::{
     format::{DOLLAR40_2, F40_2, Format, PCT40_1},
@@ -131,20 +132,14 @@ where
     A: Display,
 {
     if expected != actual {
-        eprintln!("Unexpected output:\n--- {expected_name}\n+++ {actual_name}");
-        for result in diff::lines(expected, &actual) {
-            let (prefix, line) = match result {
-                diff::Result::Left(line) => ('-', line),
-                diff::Result::Both(line, _) => (' ', line),
-                diff::Result::Right(line) => ('+', line),
-            };
-            let suffix = if line.trim_end().len() != line.len() {
-                "$"
-            } else {
-                ""
-            };
-            eprintln!("{prefix}{line}{suffix}");
-        }
+        eprintln!("Unexpected output:\n");
+        let diff = TextDiff::from_lines(expected, actual);
+        eprint!(
+            "{}",
+            diff.unified_diff()
+                .context_radius(5)
+                .header(&expected_name.to_string(), &actual_name.to_string())
+        );
         panic!();
     }
 }
index c5fbba5410bcb5225a266eaa85144baaa1412657..e051e15fb44197d7530cbc57db75f7a8f014c093 100644 (file)
@@ -44,10 +44,7 @@ use serde::{Deserialize, Deserializer, de::Error as _};
 use smallvec::{SmallVec, smallvec};
 use svg::{
     Document, Node,
-    node::{
-        Comment,
-        element::{Circle, Definitions, Group, Line, Path, Polygon, Rectangle, path::Data},
-    },
+    node::element::{Circle, Definitions, Group, Line, Path, Polygon, Rectangle, path::Data},
 };
 
 use crate::{
@@ -410,7 +407,15 @@ impl Visualization {
         let elements = graph
             .elements()
             .map(|(raw, graphic)| {
-                Element::new(raw, graphic, series, bin_widths, axis_domains, styles)
+                Element::new(
+                    raw,
+                    locale,
+                    graphic,
+                    series,
+                    bin_widths,
+                    axis_domains,
+                    styles,
+                )
             })
             .collect::<Result<Vec<_>, _>>()?;
         let coordinates = graph
@@ -507,7 +512,7 @@ impl Visualization {
             axis_domains[axis] = AxisDomain {
                 domain,
                 formatter: formatter.unwrap_or_else(|| Formatter::default_for_locale(locale)),
-                label: dbg!(axis2.and_then(|axis| axis.label.as_ref())),
+                label: axis2.and_then(|axis| axis.label.as_ref()),
                 major_ticks: axis2.and_then(|axis| axis.major_ticks.as_ref()),
             };
         }
@@ -586,7 +591,9 @@ impl Visualization {
             }
         }*/
 
-        let mut document = svg::Document::new().set("style", "font-family: \"Sans Serif\"");
+        let mut document = svg::Document::new()
+            .set("xmlns:c", "http://www.example.org/")
+            .set("style", "font-family: \"Sans Serif\"");
         if let Some(left) = frames.frames[0].position[Axis2::X].start()
             && let Some(width) = frames.frames[0].position[Axis2::X].length()
             && let Some(top) = frames.frames[0].position[Axis2::Y].start()
@@ -604,8 +611,8 @@ impl Visualization {
                 && let Some(_width) = frame.position[Axis2::X].length()
                 && let Some(top) = frame.position[Axis2::Y].start()
                 && let Some(_height) = frame.position[Axis2::Y].length()
+                && let Some(text) = label_frame.text()
             {
-                let text = label_frame.text();
                 let _metrics = font_metrics.measure(&text);
                 document.append(
                     svg::node::element::Text::new(text)
@@ -747,17 +754,22 @@ impl Visualization {
                                 .set("text-anchor", "middle"),
                         );
                 }
-                if let Some(label) = &axis_domains[Axis3::X].label {
-                    graph_svg.append(
-                        svg::node::element::Text::new(label.text())
-                            .set("x", rect.0[Axis2::X].midpoint())
-                            .set("y", y + 10.0 + font_height)
-                            .set("dominant-baseline", "hanging")
-                            .set("text-anchor", "middle"),
-                    );
-                }
+            }
+            if let Some(label) = &axis_domains[Axis3::X].label
+                && let Some(label) = label.text()
+            {
+                let x = rect.0[Axis2::X].midpoint();
+                let y = rect.0[Axis2::Y].1 + 10.0 + font_height;
+                graph_svg.append(
+                    svg::node::element::Text::new(label)
+                        .set("x", x)
+                        .set("y", y)
+                        .set("dominant-baseline", "hanging")
+                        .set("text-anchor", "middle"),
+                );
             }
         }
+
         for (y_index, y_facet) in y_facets.clone().enumerate() {
             let rect = rect.subrect(0, nx_facets, y_index, ny_facets);
             // Y axis.
@@ -770,7 +782,7 @@ impl Visualization {
                     .set("x1", x)
                     .set("x2", x)
                     .set("stroke", "black")
-                    .add(Comment::new(format!("Y axis {y_index}"))),
+                    .set("c:description", format!("Y axis {y_index}")),
             );
             for (frac, label) in axis_domains[Axis3::Y].ticks() {
                 let svg_y = rect.0[Axis2::Y].frac(1.0 - frac);
@@ -801,29 +813,35 @@ impl Visualization {
                     }
                 })
                 .join(", ");
-            let x = x - 10.0 - y_axis_text_width - font_height;
-            let y = rect.0[Axis2::Y].midpoint();
-            graph_svg.append(
-                svg::node::element::Text::new(label)
-                    .set("x", x)
-                    .set("y", y)
-                    .set("dominant-baseline", "hanging")
-                    .set("text-anchor", "middle")
-                    .set("transform", format!("rotate(-90, {x}, {y})")),
-            );
+            if !label.is_empty() {
+                let x = x - 10.0 - y_axis_text_width - font_height;
+                let y = rect.0[Axis2::Y].midpoint();
+                graph_svg.append(
+                    svg::node::element::Text::new(label)
+                        .set("x", x)
+                        .set("y", y)
+                        .set("dominant-baseline", "hanging")
+                        .set("text-anchor", "middle")
+                        .set("transform", format!("rotate(-90, {x}, {y})"))
+                        .set("c:description", "Row facet label"),
+                );
+            }
         }
 
-        if let Some(label) = &axis_domains[Axis3::Y].label {
+        if let Some(label) = &axis_domains[Axis3::Y].label
+            && let Some(label) = label.text()
+        {
             let x = rect.0[Axis2::X].0 - 10.0 - y_axis_text_width - font_height;
             let y = rect.0[Axis2::Y].midpoint();
             graph_svg.append(
-                svg::node::element::Text::new(dbg!(label.text()))
+                svg::node::element::Text::new(label)
                     .set("x", x)
                     .set("y", y)
                     .set("dominant-baseline", "hanging")
                     .set("text-anchor", "middle")
-                    .set("transform", format!("rotate(-90, {x}, {y})")),
-            );
+                    .set("transform", format!("rotate(-90, {x}, {y})"))
+                    .set("c:description", "Y axis label"),
+            )
         }
 
         for (x_index, x_facet) in x_facets.enumerate() {
@@ -2635,6 +2653,7 @@ struct Element<'a> {
 impl<'a> Element<'a> {
     fn new(
         raw: &'a RawElement,
+        locale: &'static Locale<'static>,
         graphic: Graphic,
         series: &BTreeMap<&str, Series>,
         bin_widths: &mut BTreeMap<String, f64>,
@@ -2723,6 +2742,7 @@ impl<'a> Element<'a> {
                         let total = frequencies.values().sum::<f64>();
                         let mut y = x.clone();
                         y.categorical = false;
+                        y.formatter = Formatter::default_for_locale(locale);
                         for value in &mut y.values {
                             let frequency =
                                 frequencies.get(&value.value).copied().unwrap_or_default();
@@ -4005,11 +4025,11 @@ struct Label {
 }
 
 impl Label {
-    fn text(&self) -> String {
+    fn text(&self) -> Option<String> {
         if let LabelChild::Text(text) = &self.child {
-            text.iter().map(|text| &text.text).join("")
+            Some(text.iter().map(|text| &text.text).join(""))
         } else {
-            String::new()
+            None
         }
     }
 }
@@ -4089,11 +4109,11 @@ struct LabelFrame {
 }
 
 impl LabelFrame {
-    fn text(&self) -> String {
+    fn text(&self) -> Option<String> {
         if let Some(label) = &self.label {
             label.text()
         } else {
-            String::new()
+            None
         }
     }
 }
@@ -4184,7 +4204,7 @@ impl<'a> FrameType<'a> {
                 let pangocairo_context = pangocairo::functions::create_context(&context);
                 pangocairo::functions::context_set_resolution(&pangocairo_context, 96.0);
                 let layout = pango::Layout::new(&pangocairo_context);
-                let text = label_frame.text();
+                let text = label_frame.text().unwrap_or_default();
                 layout.set_text(&text);
                 let (w, h) = layout.size();
                 enum_map! { Axis2::X => w as f64 / 1024.0, Axis2::Y => h as f64 / 1024.0}
index dae403567156b6e3219eb60383946a41ca935a46..cd8df20a4955a09887ff6fa6c5a4cc494d1446d1 100644 (file)
@@ -1,4 +1,4 @@
-<svg height="500" style="font-family: &quot;Sans Serif&quot;" viewBox="0 0 625 500" width="625" xmlns="http://www.w3.org/2000/svg">
+<svg height="500" style="font-family: &quot;Sans Serif&quot;" viewBox="0 0 625 500" width="625" xmlns="http://www.w3.org/2000/svg" xmlns:c="http://www.example.org/">
 <text dominant-baseline="hanging" font-family="sans-serif" id="frame_subtitle_1" x="0" y="28">
 Group Name
 </text>
@@ -34,9 +34,7 @@ ROC Curve
 <text dominant-baseline="hanging" text-anchor="middle" x="340" y="472">
 X Axis
 </text>
-<line stroke="black" x1="61.25" x2="61.25" y1="51" y2="439">
-<!-- Y axis 0 -->
-</line>
+<line c:description="Y axis 0" stroke="black" x1="61.25" x2="61.25" y1="51" y2="439"/>
 <line stroke="black" x1="61.25" x2="51.25" y1="439" y2="439"/>
 <text dominant-baseline="middle" text-anchor="end" x="51.25" y="439">
 0
@@ -61,7 +59,7 @@ X Axis
 <text dominant-baseline="middle" text-anchor="end" x="51.25" y="51">
 1
 </text>
-<text dominant-baseline="hanging" text-anchor="middle" transform="rotate(-90, 6.25, 245)" x="6.25" y="245">
+<text c:description="Y axis label" dominant-baseline="hanging" text-anchor="middle" transform="rotate(-90, 6.25, 245)" x="6.25" y="245">
 Y Axis
 </text>
 <rect fill="#f0f0f0" height="388" stroke="#000000" width="557.5" x="61.25" y="51"/>
index a1d6d25b29490e1f5ced384c1b8a8662deaf4e4d..0de1665fd47820560103d89a2336984ade19894d 100644 (file)
@@ -1,4 +1,4 @@
-<svg height="168" style="font-family: &quot;Sans Serif&quot;" viewBox="0 0 504 168" width="504" xmlns="http://www.w3.org/2000/svg">
+<svg height="168" style="font-family: &quot;Sans Serif&quot;" viewBox="0 0 504 168" width="504" xmlns="http://www.w3.org/2000/svg" xmlns:c="http://www.example.org/">
 <text dominant-baseline="hanging" font-family="sans-serif" id="frame_subtitle_1" x="0" y="0">
 Title
 </text>
@@ -15,9 +15,7 @@ Title
 <text dominant-baseline="hanging" text-anchor="middle" x="97.9999967956543" y="128.20000000000002">
 V2
 </text>
-<line stroke="black" x1="28" x2="28" y1="0" y2="95.20000000000002">
-<!-- Y axis 0 -->
-</line>
+<line c:description="Y axis 0" stroke="black" x1="28" x2="28" y1="0" y2="95.20000000000002"/>
 <line stroke="black" x1="28" x2="18" y1="95.20000000000002" y2="95.20000000000002"/>
 <text dominant-baseline="middle" text-anchor="end" x="18" y="95.20000000000002">
 0
@@ -70,9 +68,7 @@ V2
 <text dominant-baseline="hanging" text-anchor="middle" x="265.9999903869629" y="128.20000000000002">
 V1
 </text>
-<line stroke="black" x1="195.9999935913086" x2="195.9999935913086" y1="0" y2="95.20000000000002">
-<!-- Y axis 0 -->
-</line>
+<line c:description="Y axis 0" stroke="black" x1="195.9999935913086" x2="195.9999935913086" y1="0" y2="95.20000000000002"/>
 <line stroke="black" x1="195.9999935913086" x2="185.9999935913086" y1="95.20000000000002" y2="95.20000000000002"/>
 <text dominant-baseline="middle" text-anchor="end" x="185.9999935913086" y="95.20000000000002">
 0
@@ -121,9 +117,7 @@ V1
 <text dominant-baseline="hanging" text-anchor="middle" x="433.99999359130857" y="128.20000000000002">
 V3
 </text>
-<line stroke="black" x1="363.9999871826172" x2="363.9999871826172" y1="0" y2="95.20000000000002">
-<!-- Y axis 0 -->
-</line>
+<line c:description="Y axis 0" stroke="black" x1="363.9999871826172" x2="363.9999871826172" y1="0" y2="95.20000000000002"/>
 <line stroke="black" x1="363.9999871826172" x2="353.9999871826172" y1="95.20000000000002" y2="95.20000000000002"/>
 <text dominant-baseline="middle" text-anchor="end" x="353.9999871826172" y="95.20000000000002">
 0
index 866c0e657224e7ec830dde8fb4cbd879ada68517..6c5af5e496e024bf818309d21de2fac55a3848c1 100644 (file)
@@ -1,4 +1,4 @@
-<svg height="500" style="font-family: &quot;Sans Serif&quot;" viewBox="0 0 625 500" width="625" xmlns="http://www.w3.org/2000/svg">
+<svg height="500" style="font-family: &quot;Sans Serif&quot;" viewBox="0 0 625 500" width="625" xmlns="http://www.w3.org/2000/svg" xmlns:c="http://www.example.org/">
 <g id="frame_data_1">
 <line stroke="black" x1="83.25" x2="618.75" y1="439" y2="439"/>
 <line stroke="black" x1="217.125" x2="217.125" y1="439" y2="449"/>
@@ -12,9 +12,7 @@ Value1
 <text dominant-baseline="hanging" text-anchor="middle" x="351" y="472">
 V0
 </text>
-<line stroke="black" x1="83.25" x2="83.25" y1="5" y2="219.5">
-<!-- Y axis 0 -->
-</line>
+<line c:description="Y axis 0" stroke="black" x1="83.25" x2="83.25" y1="5" y2="219.5"/>
 <line stroke="black" x1="83.25" x2="73.25" y1="219.5" y2="219.5"/>
 <text dominant-baseline="middle" text-anchor="end" x="73.25" y="219.5">
 .0%
@@ -31,12 +29,10 @@ V0
 <text dominant-baseline="middle" text-anchor="end" x="73.25" y="55.75223214285713">
 30.0%
 </text>
-<text dominant-baseline="hanging" text-anchor="middle" transform="rotate(-90, 6.25, 112.25)" x="6.25" y="112.25">
-Percent
+<text c:description="Row facet label" dominant-baseline="hanging" text-anchor="middle" transform="rotate(-90, 6.25, 112.25)" x="6.25" y="112.25">
+no
 </text>
-<line stroke="black" x1="83.25" x2="83.25" y1="224.5" y2="439">
-<!-- Y axis 1 -->
-</line>
+<line c:description="Y axis 1" stroke="black" x1="83.25" x2="83.25" y1="224.5" y2="439"/>
 <line stroke="black" x1="83.25" x2="73.25" y1="439" y2="439"/>
 <text dominant-baseline="middle" text-anchor="end" x="73.25" y="439">
 .0%
@@ -53,7 +49,10 @@ Percent
 <text dominant-baseline="middle" text-anchor="end" x="73.25" y="275.2522321428571">
 30.0%
 </text>
-<text dominant-baseline="hanging" text-anchor="middle" transform="rotate(-90, 6.25, 331.75)" x="6.25" y="331.75">
+<text c:description="Row facet label" dominant-baseline="hanging" text-anchor="middle" transform="rotate(-90, 6.25, 331.75)" x="6.25" y="331.75">
+yes
+</text>
+<text c:description="Y axis label" dominant-baseline="hanging" text-anchor="middle" transform="rotate(-90, 6.25, 222)" x="6.25" y="222">
 Percent
 </text>
 <rect fill="#f0f0f0" height="214.5" stroke="#000000" width="535.5" x="83.25" y="5"/>
index b8c23486d67b645a85041fa7b238f7f3c5a1dde3..23056aa2e01540aaeedfb2eb634dfde2768544ba 100644 (file)
@@ -1,4 +1,4 @@
-<svg height="500" style="font-family: &quot;Sans Serif&quot;" viewBox="0 0 625 500" width="625" xmlns="http://www.w3.org/2000/svg">
+<svg height="500" style="font-family: &quot;Sans Serif&quot;" viewBox="0 0 625 500" width="625" xmlns="http://www.w3.org/2000/svg" xmlns:c="http://www.example.org/">
 <g id="frame_pie_1">
 <line stroke="black" x1="25.25" x2="468.75" y1="462" y2="462"/>
 <line stroke="black" x1="25.25" x2="25.25" y1="462" y2="472"/>
 <text dominant-baseline="hanging" text-anchor="middle" x="432.98387096774195" y="472">
 50
 </text>
-<line stroke="black" x1="25.25" x2="25.25" y1="5" y2="231">
-<!-- Y axis 0 -->
-</line>
+<line c:description="Y axis 0" stroke="black" x1="25.25" x2="25.25" y1="5" y2="231"/>
 <line stroke="black" x1="25.25" x2="15.25" y1="NaN" y2="NaN"/>
 <text dominant-baseline="middle" text-anchor="end" x="15.25" y="NaN">
 0
 </text>
-<line stroke="black" x1="25.25" x2="25.25" y1="236" y2="462">
-<!-- Y axis 1 -->
-</line>
+<text c:description="Row facet label" dominant-baseline="hanging" text-anchor="middle" transform="rotate(-90, -16.75, 118)" x="-16.75" y="118">
+yes
+</text>
+<line c:description="Y axis 1" stroke="black" x1="25.25" x2="25.25" y1="236" y2="462"/>
 <line stroke="black" x1="25.25" x2="15.25" y1="NaN" y2="NaN"/>
 <text dominant-baseline="middle" text-anchor="end" x="15.25" y="NaN">
 0
 </text>
+<text c:description="Row facet label" dominant-baseline="hanging" text-anchor="middle" transform="rotate(-90, -16.75, 349)" x="-16.75" y="349">
+no
+</text>
 <rect fill="rgb(0, 0, 0, 0.00)" height="226" stroke="rgb(0, 0, 0, 0.00)" width="443.5" x="25.25" y="5"/>
 <g id="element_element_1">
 <rect fill="#3e58ac" height="113" stroke="#000000" width="1" x="239.84677419354838" y="118"/>
index 56073e1ebbb5e372a6fbcb4a73c8ba01a675e0ac..f4b742d42da3ce3de534b9ac3241a8e882c8e0f3 100644 (file)
-<svg height="500" style="font-family: &quot;Sans Serif&quot;" viewBox="0 0 625 500" width="625" xmlns="http://www.w3.org/2000/svg">
+<svg height="500" style="font-family: &quot;Sans Serif&quot;" viewBox="0 0 625 500" width="625" xmlns="http://www.w3.org/2000/svg" xmlns:c="http://www.example.org/">
 <g id="frame_data_1">
-<line stroke="black" x1="70.25" x2="342" y1="439" y2="439"/>
-<line stroke="black" x1="138.1875" x2="138.1875" y1="439" y2="449"/>
-<text dominant-baseline="hanging" text-anchor="middle" x="138.1875" y="449">
+<line stroke="black" x1="48.25" x2="331" y1="439" y2="439"/>
+<line stroke="black" x1="118.9375" x2="118.9375" y1="439" y2="449"/>
+<text dominant-baseline="hanging" text-anchor="middle" x="118.9375" y="449">
 
 </text>
-<line stroke="black" x1="274.0625" x2="274.0625" y1="439" y2="449"/>
-<text dominant-baseline="hanging" text-anchor="middle" x="274.0625" y="449">
+<line stroke="black" x1="260.3125" x2="260.3125" y1="439" y2="449"/>
+<text dominant-baseline="hanging" text-anchor="middle" x="260.3125" y="449">
 
 </text>
-<text dominant-baseline="hanging" text-anchor="middle" x="206.125" y="472">
+<text dominant-baseline="hanging" text-anchor="middle" x="333.5" y="472">
 Value of Variable 4
 </text>
-<line stroke="black" x1="347" x2="618.75" y1="439" y2="439"/>
-<line stroke="black" x1="414.9375" x2="414.9375" y1="439" y2="449"/>
-<text dominant-baseline="hanging" text-anchor="middle" x="414.9375" y="449">
+<line stroke="black" x1="336" x2="618.75" y1="439" y2="439"/>
+<line stroke="black" x1="406.6875" x2="406.6875" y1="439" y2="449"/>
+<text dominant-baseline="hanging" text-anchor="middle" x="406.6875" y="449">
 
 </text>
-<line stroke="black" x1="550.8125" x2="550.8125" y1="439" y2="449"/>
-<text dominant-baseline="hanging" text-anchor="middle" x="550.8125" y="449">
+<line stroke="black" x1="548.0625" x2="548.0625" y1="439" y2="449"/>
+<text dominant-baseline="hanging" text-anchor="middle" x="548.0625" y="449">
 
 </text>
-<text dominant-baseline="hanging" text-anchor="middle" x="482.875" y="472">
+<text dominant-baseline="hanging" text-anchor="middle" x="333.5" y="472">
 Value of Variable 4
 </text>
-<line stroke="black" x1="70.25" x2="70.25" y1="5" y2="109.75">
-<!-- Y axis 0 -->
-</line>
-<line stroke="black" x1="70.25" x2="60.25" y1="109.75" y2="109.75"/>
-<text dominant-baseline="middle" text-anchor="end" x="60.25" y="109.75">
-.00
+<line c:description="Y axis 0" stroke="black" x1="48.25" x2="48.25" y1="5" y2="109.75"/>
+<line stroke="black" x1="48.25" x2="38.25" y1="109.75" y2="109.75"/>
+<text dominant-baseline="middle" text-anchor="end" x="38.25" y="109.75">
+0
 </text>
-<line stroke="black" x1="70.25" x2="60.25" y1="93.12301587301587" y2="93.12301587301587"/>
-<text dominant-baseline="middle" text-anchor="end" x="60.25" y="93.12301587301587">
-1.00
+<line stroke="black" x1="48.25" x2="38.25" y1="93.12301587301587" y2="93.12301587301587"/>
+<text dominant-baseline="middle" text-anchor="end" x="38.25" y="93.12301587301587">
+1
 </text>
-<line stroke="black" x1="70.25" x2="60.25" y1="76.49603174603175" y2="76.49603174603175"/>
-<text dominant-baseline="middle" text-anchor="end" x="60.25" y="76.49603174603175">
-2.00
+<line stroke="black" x1="48.25" x2="38.25" y1="76.49603174603175" y2="76.49603174603175"/>
+<text dominant-baseline="middle" text-anchor="end" x="38.25" y="76.49603174603175">
+2
 </text>
-<line stroke="black" x1="70.25" x2="60.25" y1="59.86904761904761" y2="59.86904761904761"/>
-<text dominant-baseline="middle" text-anchor="end" x="60.25" y="59.86904761904761">
-3.00
+<line stroke="black" x1="48.25" x2="38.25" y1="59.86904761904761" y2="59.86904761904761"/>
+<text dominant-baseline="middle" text-anchor="end" x="38.25" y="59.86904761904761">
+3
 </text>
-<line stroke="black" x1="70.25" x2="60.25" y1="43.242063492063494" y2="43.242063492063494"/>
-<text dominant-baseline="middle" text-anchor="end" x="60.25" y="43.242063492063494">
-4.00
+<line stroke="black" x1="48.25" x2="38.25" y1="43.242063492063494" y2="43.242063492063494"/>
+<text dominant-baseline="middle" text-anchor="end" x="38.25" y="43.242063492063494">
+4
 </text>
-<line stroke="black" x1="70.25" x2="60.25" y1="26.615079365079357" y2="26.615079365079357"/>
-<text dominant-baseline="middle" text-anchor="end" x="60.25" y="26.615079365079357">
-5.00
+<line stroke="black" x1="48.25" x2="38.25" y1="26.615079365079357" y2="26.615079365079357"/>
+<text dominant-baseline="middle" text-anchor="end" x="38.25" y="26.615079365079357">
+5
 </text>
-<line stroke="black" x1="70.25" x2="60.25" y1="9.988095238095232" y2="9.988095238095232"/>
-<text dominant-baseline="middle" text-anchor="end" x="60.25" y="9.988095238095232">
-6.00
+<line stroke="black" x1="48.25" x2="38.25" y1="9.988095238095232" y2="9.988095238095232"/>
+<text dominant-baseline="middle" text-anchor="end" x="38.25" y="9.988095238095232">
+6
 </text>
-<text dominant-baseline="hanging" text-anchor="middle" transform="rotate(-90, 6.25, 57.375)" x="6.25" y="57.375">
+<text c:description="Row facet label" dominant-baseline="hanging" text-anchor="middle" transform="rotate(-90, 6.25, 57.375)" x="6.25" y="57.375">
 4
 </text>
-<line stroke="black" x1="70.25" x2="70.25" y1="114.75" y2="219.5">
-<!-- Y axis 1 -->
-</line>
-<line stroke="black" x1="70.25" x2="60.25" y1="219.5" y2="219.5"/>
-<text dominant-baseline="middle" text-anchor="end" x="60.25" y="219.5">
-.00
+<line c:description="Y axis 1" stroke="black" x1="48.25" x2="48.25" y1="114.75" y2="219.5"/>
+<line stroke="black" x1="48.25" x2="38.25" y1="219.5" y2="219.5"/>
+<text dominant-baseline="middle" text-anchor="end" x="38.25" y="219.5">
+0
 </text>
-<line stroke="black" x1="70.25" x2="60.25" y1="202.87301587301587" y2="202.87301587301587"/>
-<text dominant-baseline="middle" text-anchor="end" x="60.25" y="202.87301587301587">
-1.00
+<line stroke="black" x1="48.25" x2="38.25" y1="202.87301587301587" y2="202.87301587301587"/>
+<text dominant-baseline="middle" text-anchor="end" x="38.25" y="202.87301587301587">
+1
 </text>
-<line stroke="black" x1="70.25" x2="60.25" y1="186.24603174603175" y2="186.24603174603175"/>
-<text dominant-baseline="middle" text-anchor="end" x="60.25" y="186.24603174603175">
-2.00
+<line stroke="black" x1="48.25" x2="38.25" y1="186.24603174603175" y2="186.24603174603175"/>
+<text dominant-baseline="middle" text-anchor="end" x="38.25" y="186.24603174603175">
+2
 </text>
-<line stroke="black" x1="70.25" x2="60.25" y1="169.61904761904762" y2="169.61904761904762"/>
-<text dominant-baseline="middle" text-anchor="end" x="60.25" y="169.61904761904762">
-3.00
+<line stroke="black" x1="48.25" x2="38.25" y1="169.61904761904762" y2="169.61904761904762"/>
+<text dominant-baseline="middle" text-anchor="end" x="38.25" y="169.61904761904762">
+3
 </text>
-<line stroke="black" x1="70.25" x2="60.25" y1="152.9920634920635" y2="152.9920634920635"/>
-<text dominant-baseline="middle" text-anchor="end" x="60.25" y="152.9920634920635">
-4.00
+<line stroke="black" x1="48.25" x2="38.25" y1="152.9920634920635" y2="152.9920634920635"/>
+<text dominant-baseline="middle" text-anchor="end" x="38.25" y="152.9920634920635">
+4
 </text>
-<line stroke="black" x1="70.25" x2="60.25" y1="136.36507936507937" y2="136.36507936507937"/>
-<text dominant-baseline="middle" text-anchor="end" x="60.25" y="136.36507936507937">
-5.00
+<line stroke="black" x1="48.25" x2="38.25" y1="136.36507936507937" y2="136.36507936507937"/>
+<text dominant-baseline="middle" text-anchor="end" x="38.25" y="136.36507936507937">
+5
 </text>
-<line stroke="black" x1="70.25" x2="60.25" y1="119.73809523809523" y2="119.73809523809523"/>
-<text dominant-baseline="middle" text-anchor="end" x="60.25" y="119.73809523809523">
-6.00
+<line stroke="black" x1="48.25" x2="38.25" y1="119.73809523809523" y2="119.73809523809523"/>
+<text dominant-baseline="middle" text-anchor="end" x="38.25" y="119.73809523809523">
+6
 </text>
-<text dominant-baseline="hanging" text-anchor="middle" transform="rotate(-90, 6.25, 167.125)" x="6.25" y="167.125">
+<text c:description="Row facet label" dominant-baseline="hanging" text-anchor="middle" transform="rotate(-90, 6.25, 167.125)" x="6.25" y="167.125">
 5
 </text>
-<line stroke="black" x1="70.25" x2="70.25" y1="224.5" y2="329.25">
-<!-- Y axis 2 -->
-</line>
-<line stroke="black" x1="70.25" x2="60.25" y1="329.25" y2="329.25"/>
-<text dominant-baseline="middle" text-anchor="end" x="60.25" y="329.25">
-.00
+<line c:description="Y axis 2" stroke="black" x1="48.25" x2="48.25" y1="224.5" y2="329.25"/>
+<line stroke="black" x1="48.25" x2="38.25" y1="329.25" y2="329.25"/>
+<text dominant-baseline="middle" text-anchor="end" x="38.25" y="329.25">
+0
 </text>
-<line stroke="black" x1="70.25" x2="60.25" y1="312.6230158730159" y2="312.6230158730159"/>
-<text dominant-baseline="middle" text-anchor="end" x="60.25" y="312.6230158730159">
-1.00
+<line stroke="black" x1="48.25" x2="38.25" y1="312.6230158730159" y2="312.6230158730159"/>
+<text dominant-baseline="middle" text-anchor="end" x="38.25" y="312.6230158730159">
+1
 </text>
-<line stroke="black" x1="70.25" x2="60.25" y1="295.99603174603175" y2="295.99603174603175"/>
-<text dominant-baseline="middle" text-anchor="end" x="60.25" y="295.99603174603175">
-2.00
+<line stroke="black" x1="48.25" x2="38.25" y1="295.99603174603175" y2="295.99603174603175"/>
+<text dominant-baseline="middle" text-anchor="end" x="38.25" y="295.99603174603175">
+2
 </text>
-<line stroke="black" x1="70.25" x2="60.25" y1="279.3690476190476" y2="279.3690476190476"/>
-<text dominant-baseline="middle" text-anchor="end" x="60.25" y="279.3690476190476">
-3.00
+<line stroke="black" x1="48.25" x2="38.25" y1="279.3690476190476" y2="279.3690476190476"/>
+<text dominant-baseline="middle" text-anchor="end" x="38.25" y="279.3690476190476">
+3
 </text>
-<line stroke="black" x1="70.25" x2="60.25" y1="262.7420634920635" y2="262.7420634920635"/>
-<text dominant-baseline="middle" text-anchor="end" x="60.25" y="262.7420634920635">
-4.00
+<line stroke="black" x1="48.25" x2="38.25" y1="262.7420634920635" y2="262.7420634920635"/>
+<text dominant-baseline="middle" text-anchor="end" x="38.25" y="262.7420634920635">
+4
 </text>
-<line stroke="black" x1="70.25" x2="60.25" y1="246.11507936507937" y2="246.11507936507937"/>
-<text dominant-baseline="middle" text-anchor="end" x="60.25" y="246.11507936507937">
-5.00
+<line stroke="black" x1="48.25" x2="38.25" y1="246.11507936507937" y2="246.11507936507937"/>
+<text dominant-baseline="middle" text-anchor="end" x="38.25" y="246.11507936507937">
+5
 </text>
-<line stroke="black" x1="70.25" x2="60.25" y1="229.48809523809524" y2="229.48809523809524"/>
-<text dominant-baseline="middle" text-anchor="end" x="60.25" y="229.48809523809524">
-6.00
+<line stroke="black" x1="48.25" x2="38.25" y1="229.48809523809524" y2="229.48809523809524"/>
+<text dominant-baseline="middle" text-anchor="end" x="38.25" y="229.48809523809524">
+6
 </text>
-<text dominant-baseline="hanging" text-anchor="middle" transform="rotate(-90, 6.25, 276.875)" x="6.25" y="276.875">
+<text c:description="Row facet label" dominant-baseline="hanging" text-anchor="middle" transform="rotate(-90, 6.25, 276.875)" x="6.25" y="276.875">
 7
 </text>
-<line stroke="black" x1="70.25" x2="70.25" y1="334.25" y2="439">
-<!-- Y axis 3 -->
-</line>
-<line stroke="black" x1="70.25" x2="60.25" y1="439" y2="439"/>
-<text dominant-baseline="middle" text-anchor="end" x="60.25" y="439">
-.00
+<line c:description="Y axis 3" stroke="black" x1="48.25" x2="48.25" y1="334.25" y2="439"/>
+<line stroke="black" x1="48.25" x2="38.25" y1="439" y2="439"/>
+<text dominant-baseline="middle" text-anchor="end" x="38.25" y="439">
+0
 </text>
-<line stroke="black" x1="70.25" x2="60.25" y1="422.3730158730159" y2="422.3730158730159"/>
-<text dominant-baseline="middle" text-anchor="end" x="60.25" y="422.3730158730159">
-1.00
+<line stroke="black" x1="48.25" x2="38.25" y1="422.3730158730159" y2="422.3730158730159"/>
+<text dominant-baseline="middle" text-anchor="end" x="38.25" y="422.3730158730159">
+1
 </text>
-<line stroke="black" x1="70.25" x2="60.25" y1="405.74603174603175" y2="405.74603174603175"/>
-<text dominant-baseline="middle" text-anchor="end" x="60.25" y="405.74603174603175">
-2.00
+<line stroke="black" x1="48.25" x2="38.25" y1="405.74603174603175" y2="405.74603174603175"/>
+<text dominant-baseline="middle" text-anchor="end" x="38.25" y="405.74603174603175">
+2
 </text>
-<line stroke="black" x1="70.25" x2="60.25" y1="389.1190476190476" y2="389.1190476190476"/>
-<text dominant-baseline="middle" text-anchor="end" x="60.25" y="389.1190476190476">
-3.00
+<line stroke="black" x1="48.25" x2="38.25" y1="389.1190476190476" y2="389.1190476190476"/>
+<text dominant-baseline="middle" text-anchor="end" x="38.25" y="389.1190476190476">
+3
 </text>
-<line stroke="black" x1="70.25" x2="60.25" y1="372.4920634920635" y2="372.4920634920635"/>
-<text dominant-baseline="middle" text-anchor="end" x="60.25" y="372.4920634920635">
-4.00
+<line stroke="black" x1="48.25" x2="38.25" y1="372.4920634920635" y2="372.4920634920635"/>
+<text dominant-baseline="middle" text-anchor="end" x="38.25" y="372.4920634920635">
+4
 </text>
-<line stroke="black" x1="70.25" x2="60.25" y1="355.86507936507934" y2="355.86507936507934"/>
-<text dominant-baseline="middle" text-anchor="end" x="60.25" y="355.86507936507934">
-5.00
+<line stroke="black" x1="48.25" x2="38.25" y1="355.86507936507934" y2="355.86507936507934"/>
+<text dominant-baseline="middle" text-anchor="end" x="38.25" y="355.86507936507934">
+5
 </text>
-<line stroke="black" x1="70.25" x2="60.25" y1="339.23809523809524" y2="339.23809523809524"/>
-<text dominant-baseline="middle" text-anchor="end" x="60.25" y="339.23809523809524">
-6.00
+<line stroke="black" x1="48.25" x2="38.25" y1="339.23809523809524" y2="339.23809523809524"/>
+<text dominant-baseline="middle" text-anchor="end" x="38.25" y="339.23809523809524">
+6
 </text>
-<text dominant-baseline="hanging" text-anchor="middle" transform="rotate(-90, 6.25, 386.625)" x="6.25" y="386.625">
+<text c:description="Row facet label" dominant-baseline="hanging" text-anchor="middle" transform="rotate(-90, 6.25, 386.625)" x="6.25" y="386.625">
 6
 </text>
-<text dominant-baseline="hanging" text-anchor="middle" transform="rotate(-90, 6.25, 222)" x="6.25" y="222">
+<text c:description="Y axis label" dominant-baseline="hanging" text-anchor="middle" transform="rotate(-90, 6.25, 222)" x="6.25" y="222">
 Frequency
 </text>
-<rect fill="#f0f0f0" height="104.75" stroke="#000000" width="271.75" x="70.25" y="5"/>
+<rect fill="#f0f0f0" height="104.75" stroke="#000000" width="282.75" x="48.25" y="5"/>
 <g id="element_histogram_1">
-<rect fill="#d3ce97" height="99.76190476190477" stroke="#000000" width="44.838750000000005" x="115.768125" y="9.988095238095232"/>
-<rect fill="#d3ce97" height="49.88095238095239" stroke="#000000" width="44.838750000000005" x="251.643125" y="59.86904761904761"/>
+<rect fill="#d3ce97" height="99.76190476190477" stroke="#000000" width="46.65375" x="95.610625" y="9.988095238095232"/>
+<rect fill="#d3ce97" height="49.88095238095239" stroke="#000000" width="46.653749999999974" x="236.985625" y="59.86904761904761"/>
 </g>
-<rect fill="#f0f0f0" height="104.75" stroke="#000000" width="271.75" x="70.25" y="114.75"/>
+<rect fill="#f0f0f0" height="104.75" stroke="#000000" width="282.75" x="48.25" y="114.75"/>
 <g id="element_histogram_1">
-<rect fill="#d3ce97" height="99.76190476190477" stroke="#000000" width="44.838750000000005" x="115.768125" y="119.73809523809523"/>
+<rect fill="#d3ce97" height="99.76190476190477" stroke="#000000" width="46.65375" x="95.610625" y="119.73809523809523"/>
 </g>
-<rect fill="#f0f0f0" height="104.75" stroke="#000000" width="271.75" x="70.25" y="224.5"/>
+<rect fill="#f0f0f0" height="104.75" stroke="#000000" width="282.75" x="48.25" y="224.5"/>
 <g id="element_histogram_1">
-<rect fill="#d3ce97" height="99.76190476190476" stroke="#000000" width="44.838750000000005" x="115.768125" y="229.48809523809524"/>
+<rect fill="#d3ce97" height="99.76190476190476" stroke="#000000" width="46.65375" x="95.610625" y="229.48809523809524"/>
 </g>
-<rect fill="#f0f0f0" height="104.75" stroke="#000000" width="271.75" x="70.25" y="334.25"/>
+<rect fill="#f0f0f0" height="104.75" stroke="#000000" width="282.75" x="48.25" y="334.25"/>
 <g id="element_histogram_1">
-<rect fill="#d3ce97" height="49.88095238095241" stroke="#000000" width="44.838750000000005" x="251.643125" y="389.1190476190476"/>
+<rect fill="#d3ce97" height="49.88095238095241" stroke="#000000" width="46.653749999999974" x="236.985625" y="389.1190476190476"/>
 </g>
-<rect fill="#f0f0f0" height="104.75" stroke="#000000" width="271.75" x="347" y="5"/>
+<rect fill="#f0f0f0" height="104.75" stroke="#000000" width="282.75" x="336" y="5"/>
 <g id="element_histogram_1">
-<rect fill="#d3ce97" height="99.76190476190477" stroke="#000000" width="44.838750000000005" x="392.518125" y="9.988095238095232"/>
+<rect fill="#d3ce97" height="99.76190476190477" stroke="#000000" width="46.653749999999945" x="383.360625" y="9.988095238095232"/>
 </g>
-<rect fill="#f0f0f0" height="104.75" stroke="#000000" width="271.75" x="347" y="114.75"/>
+<rect fill="#f0f0f0" height="104.75" stroke="#000000" width="282.75" x="336" y="114.75"/>
 <g id="element_histogram_1">
-<rect fill="#d3ce97" height="99.76190476190477" stroke="#000000" width="44.838750000000005" x="392.518125" y="119.73809523809523"/>
+<rect fill="#d3ce97" height="99.76190476190477" stroke="#000000" width="46.653749999999945" x="383.360625" y="119.73809523809523"/>
 </g>
-<rect fill="#f0f0f0" height="104.75" stroke="#000000" width="271.75" x="347" y="224.5"/>
+<rect fill="#f0f0f0" height="104.75" stroke="#000000" width="282.75" x="336" y="224.5"/>
 <g id="element_histogram_1">
-<rect fill="#d3ce97" height="49.88095238095241" stroke="#000000" width="44.83874999999989" x="528.393125" y="279.3690476190476"/>
+<rect fill="#d3ce97" height="49.88095238095241" stroke="#000000" width="46.653749999999945" x="524.735625" y="279.3690476190476"/>
 </g>
-<rect fill="#f0f0f0" height="104.75" stroke="#000000" width="271.75" x="347" y="334.25"/>
+<rect fill="#f0f0f0" height="104.75" stroke="#000000" width="282.75" x="336" y="334.25"/>
 <g id="element_histogram_1">
-<rect fill="#d3ce97" height="99.76190476190476" stroke="#000000" width="44.838750000000005" x="392.518125" y="339.23809523809524"/>
+<rect fill="#d3ce97" height="99.76190476190476" stroke="#000000" width="46.653749999999945" x="383.360625" y="339.23809523809524"/>
 </g>
 </g>
 </svg>