Feature Analysis for Classification (Iris)
Background
Before training a classifier you look at two things: how each feature is distributed within each class, and whether the classes are separable in feature space. This study uses the classic Iris dataset — three species, four measurements — to reproduce those two views with the convenience marks.
Class-conditional distributions
mark_density reads the feature from x and gives one curve per color group,
so you can see how a feature separates the classes. Petal length is clearly
bimodal: setosa sits far to the left, while versicolor and virginica
overlap in the middle. A single threshold on this feature would split setosa
perfectly but confuse the other two.
Feature separation
A scatter of two features, coloured by class, shows the decision boundary a linear model would try to find. Setosa is linearly separable from the other two; versicolor and virginica share a region where any straight boundary has to trade false positives for false negatives.
Implementation
//! Case study: exploratory feature analysis before training a classifier. //! //! Two views you would actually look at on the Iris dataset: //! //! 1. the **class-conditional distribution** of a feature (is it separable?), //! 2. a **scatter of two features**, coloured by class, to see the decision //! boundary a linear model would find. use charton::prelude::*; use std::error::Error; fn main() -> Result<(), Box<dyn Error>> { let iris = load_dataset("iris")?; // 1. Class-conditional density of petal length. chart!(&iris)? .mark_density()? .configure_density(|density| density.with_opacity(0.5)) .encode((alt::x("petal_length"), alt::color("species")))? .with_title("Petal length by species") .with_x_label("Petal length (cm)") .with_y_label("Density") .save("docs/src/images/case_data_science_density.svg")?; // 2. Two features, coloured by class. Setosa is linearly separable from the // other two; versicolor and virginica overlap. chart!(&iris)? .mark_point()? .configure_point(|point| point.with_size(40.0).with_opacity(0.8)) .encode(( alt::x("sepal_length"), alt::y("petal_length"), alt::color("species"), ))? .with_title("Sepal vs petal length") .with_x_label("Sepal length (cm)") .with_y_label("Petal length (cm)") .save("docs/src/images/case_data_science_scatter.svg")?; println!("Saved case_data_science_density.svg and case_data_science_scatter.svg"); Ok(()) }
Both figures are a single encoding each: y/x for the values and color for
the class. The axis and legend titles come from the original columns
(petal_length, sepal_length, species) automatically.
What it demonstrates
mark_densityfor class-conditional distributions, one curve per group.mark_point+colorfor feature separation and decision boundaries.- The grammar behind both: a density is
transform_density+mark_area; a scatter ismark_point. See 1-D Density and Scatter.
See also
- Violin — the same distributions as an outline with an inner box.
- 2-D Density — the joint distribution of two features.
- Scatter matrices — the full pairwise view.