Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Column cards

A column card summarizes a column’s inferred role, counts, statistics, and value distribution. report.columns contains one dict per column. Cards use every input row; relationship sampling does not affect them.

The fixture includes constant and all-null columns, repeated categories, numeric measurements, dates, and invoice numbers with two formats.

1500 rows × 10 columns (standard budget); key candidate: invoice_no; 1 functional dependencies, 0 predictive dependencies, 0 conditional rules

A card at a glance

{
  "name": "risk_score",
  "dtype": "float64",
  "role": "continuous",
  "n": 1500,
  "null_count": 0,
  "null_fraction": 0.0,
  "distinct": 101,
  "distinct_ratio": 0.06733333333333333,
  "numeric_stats": {
    "min": 0.0,
    "max": 10.0,
    "mean": 4.930866666666659,
    "std": 2.8732421725678146,
    "q25": 2.475,
    "q50": 4.9,
    "q75": 7.3,
    "zeros": 9,
    "negatives": 0,
    "integral": false
  },
  "concentration": {
    "hhi": 0.010659555555555556,
    "entropy_nats": 4.576751934201698,
    "effective_cardinality": 97.19817486700717,
    "top1_share": 0.017333333333333333,
    "top3_share": 0.050666666666666665
  },
  "top_values": [
    {
      "value": "6.1",
      "count": 26,
      "share": 0.017333333333333333
    },
    {
      "value": "6",
      "count": 25,
      "share": 0.016666666666666666
    },
    {
      "value": "7.3",
      "count": 25,
      "share": 0.016666666666666666
    },
    {
      "value": "5.5",
      "count": 24,
      "share": 0.016
    },
    {
      "value": "6.8",
      "count": 24,
      "share": 0.016
    }
  ]
}

risk_score has the inferred role continuous. Its n, null_count, distinct, and distinct_ratio describe all input rows. numeric_stats contains the mean, standard deviation, quartiles, zero and negative counts, and whether every value is integral. concentration describes how often values repeat; top_values lists the most frequent values.

The statistics block depends on dtype: strings have string_stats, booleans have bool_stats, and dates have temporal_stats. The date scan adds the most frequent interval to temporal_stats. For signup_date, that interval is one week:

{
  "min": "2024-01-01",
  "max": "2052-09-23",
  "span_days": 10493,
  "modal_interval_days": 7
}

Roles

Role inference applies rules to dtype and exact counts. The resulting label describes observed behavior and may differ from the column’s meaning in the application:

RoleInferred whenNotes
all_nullno non-null valuesflagged as a finding too
constantone distinct valuedrop candidate
booleanboolean dtype
categoricalstrings with ≤ 500 distinct values; numeric with ≤ 12 distinct (n ≥ 30), or ≤ 100 distinct and ≤ 2% of rows (n ≥ 100)numeric categories carry a treat_as_categorical hint
free_textstrings with > 500 distinct valuesexcluded from nominal model passes
identifiernumeric with distinct ratio ≥ 0.98check intended meaning before treating as a join key
continuousnumeric, otherwise
date / datetimedate or datetime dtypedatetime analyzed at day granularity for gaps
otherdtype the profiler treats as opaquereported in coverage

A numeric measurement with no repeated values, such as random floats, has a distinct ratio of 1.0 and receives the identifier role. That rule cannot establish whether the column identifies an entity; check its definition and use in the application. Date and datetime dtypes retain their own roles. The numeric-categorical thresholds also need context: a 13-level ordered code may still represent categories.

Concentration

The concentration block describes the frequencies of non-null values. The Herfindahl–Hirschman index is the sum of squared value shares: 1.0 for a constant column, or 1/k1/k for kk equally frequent values. Shannon entropy is reported in nats. Effective cardinality, exp⁡(entropy)\exp(\text{entropy}), is the number of equally frequent values that would have the same entropy. A six-level column dominated by one value has effective cardinality near 1; a balanced six-level column has 6. top1_share and top3_share give the fractions occupied by the most frequent value and the three most frequent values.

The email_domain card illustrates these measures:

{
  "hhi": 0.34874666666666665,
  "entropy_nats": 1.1724469750309252,
  "effective_cardinality": 3.229886428078974,
  "top1_share": 0.48533333333333334,
  "top3_share": 0.9506666666666667
}
[
  {
    "value": "gmail.com",
    "count": 728,
    "share": 0.48533333333333334
  },
  {
    "value": "outlook.com",
    "count": 402,
    "share": 0.268
  },
  {
    "value": "corp.io",
    "count": 296,
    "share": 0.19733333333333333
  },
  {
    "value": "proton.me",
    "count": 74,
    "share": 0.04933333333333333
  }
]

All cards at a glance

Render one row per column to compare roles, null fractions, and value frequencies. The Great Tables styles below wrap long column names and roles:

Loading...

The table shows unit as constant, legacy_flag as all null, plan and email_domain as concentrated categoricals, risk_score as continuous, and invoice_no as free text.

invoice_no has the free_text role because it exceeds the 500-value threshold for string categories. It is also null-free, with 1,500 distinct values in 1,500 rows, so its values can identify rows in this table. The role excludes it from nominal model passes; uniqueness is checked separately from its exact counts.

Cards are also the input to charts. The top values of a categorical column make a quick bar chart — Altair over the card’s top_values:

Loading...

Format patterns

String cards carry one more block: format_patterns, the shape signatures of the column’s values. Digits become #, lowercase letters a, uppercase letters A, other characters are kept, and signatures truncate at 24 characters. Two clusters of signatures in a column that should have one can indicate mixed formats, as in this invoice_no fixture:

[
  {
    "pattern": "####",
    "count": 750,
    "share": 0.5,
    "example": "0001"
  },
  {
    "pattern": "AAA-####",
    "count": 750,
    "share": 0.5,
    "example": "INV-0000"
  }
]

Half the invoice numbers have the pattern AAA-#### and half have ####. The card reports both signatures and their shares without listing all 1,500 values. The mixed-format finding suggests normalization before parsing; whether to change these values depends on the expected invoice format.

Card-level findings

The profiler also creates findings from card counts: constant and all-null columns, nearly constant two-level columns such as channel, concentrated values, numeric categories such as status_code, and identifier-like columns. These receive lower selection priority than relationship findings. The loop below prints the findings for unit, legacy_flag, channel, and status_code, along with any suggested action.

[concentration] column channel is nearly constant: 99.7% 'web' vs 4 'app'
    → treat the rare value as the signal
[concentration] column unit is constant ('kg')
    → drop from modeling; carries no information
[column_roles] numeric column status_code behaves like a category (6 distinct values)
    → treat as categorical in models; do not scale
[missingness] column legacy_flag is entirely null
    → consider dropping

The thresholds for role rules, concentration flags, and format findings are listed in Column cards.