Data Analyst Interview
Menu
Browse in your language. All mock interviews, preparation sessions and feedback are in English only.

Why a pandas Mask and Its Inverse Can Both Exclude Rows

Pandas · Filtering

Why a pandas Mask and Its Inverse Can Both Exclude Rows

Keep unknown statuses visible when splitting an operations report.

Quick answer: For a pandas nullable Boolean Series, inverting a missing value with ~ leaves it missing. Boolean indexing excludes missing mask entries, so both df.loc[mask] and df.loc[~mask] omit those rows. Add an explicit mask.isna() group when the report needs a complete partition.

By Prakhar Shrivastava · October 24, 2026

Why do the two filtered groups contain only four of six orders?

A fictional operations export contains six orders from US, UK and German storefronts. Two orders are confirmed shipped, two explicitly have not shipped, and two have unavailable shipment status. All amounts are already normalized to USD. There is one row per order, and the export covers a single agreed reporting period.

The Boolean values have already been parsed correctly. This exercise is about selecting rows after parsing, not interpreting strings such as “False.” Unknown status must remain unknown; it is not a confirmed negative.

Reproduce the missing rows

import pandas as pd
orders = pd.DataFrame({
    'order_id': ['US1','US2','UK1','UK2','DE1','DE2'],
    'shipped': pd.Series([True,False,None,True,False,None], dtype='boolean'),
    'amount_usd': [100,40,70,80,30,60]
})
mask = orders['shipped']
shipped = orders.loc[mask]
not_shipped = orders.loc[~mask]
unknown = orders.loc[mask.isna()]
print('Shipped:', shipped['order_id'].tolist())
print('Not shipped:', not_shipped['order_id'].tolist())
print('Unknown:', unknown['order_id'].tolist())
print('Rows:', len(shipped), len(not_shipped), len(unknown))
print('USD:', shipped.amount_usd.sum(),
      not_shipped.amount_usd.sum(), unknown.amount_usd.sum())
Shipped: ['US1', 'UK2']
Not shipped: ['US2', 'DE1']
Unknown: ['UK1', 'DE2']
Rows: 2 2 2
USD: 180 70 130

The shipped and not-shipped groups contain four orders and $250 combined. The two unknown orders account for the remaining $130, bringing the original total to $380. The filtering operation did not delete source rows, but a report built only from the first two groups would omit them.

Why is the inverse not the full complement?

For known Boolean values, ~ changes True to False and False to True. For this nullable boolean dtype, ~pd.NA remains unknown. The inverse mask is therefore not equivalent to “every row not selected by the first filter.” At selection time, pandas treats missing mask entries as false, so the unknown rows enter neither result.

That distinction matters when a dashboard presents two groups as exhaustive. A title such as “shipped versus not shipped” can imply that all orders have a resolved status even when the data does not support it. Show a third unknown group and its amount or count.

How should an operational review queue handle unknowns?

A review queue may intentionally include both confirmed not-shipped orders and unavailable statuses. Name that population explicitly, for example “not confirmed shipped,” and retain the original flag so reviewers can distinguish the reasons.

review = orders.loc[~mask.fillna(False)]
# Includes US2, UK1, DE1 and DE2; original shipped column is unchanged.

This uses a filled temporary mask to decide inclusion. It does not establish that the unknown orders are actually unshipped. Do not overwrite the source flag or use the queue size as a confirmed not-shipped count.

Check that the three groups cover the input

assert len(shipped) + len(not_shipped) + len(unknown) == len(orders)
assert (shipped.amount_usd.sum() + not_shipped.amount_usd.sum()
        + unknown.amount_usd.sum()) == orders.amount_usd.sum()

These checks catch omitted records in this fixture. They do not prove the export itself is complete. Reconcile expected order IDs and load-completion records separately. Amount reconciliation alone is insufficient: zero-value or offsetting records could be omitted without changing a total.

The mask here comes directly from the same DataFrame, so its index aligns with the rows being selected. If you build a mask elsewhere, check index alignment and uniqueness before applying it. Also verify the dtype: object columns containing mixed strings, Booleans and nulls do not have the same explicit contract as this nullable Boolean example.

What should you say in an interview?

“The inverse nullable mask retains unknowns, and both filters exclude those entries. I will report true, false and unknown separately, reconcile their row counts to the input, and label any combined review queue by its actual inclusion rule.”

For regional comparisons, apply the same status definition and reporting cutoff to each market. A larger unknown share may reflect extraction or update timing; it is not enough evidence to conclude that one country’s fulfillment performance is worse.

Verification and sources

The example passed six assertions in pandas 2.2.3 covering group membership, the incomplete two-group count, the complete three-group count and USD reconciliation. The numeric amounts are synthetic whole-dollar values. Test your production dtype, version and numeric precision separately.

The official nullable Boolean guide documents missing-mask selection and three-valued logical behavior. Continue with parsing string flags correctly, distinguishing rows from known identities, and index alignment in pandas.

Leave a Comment

Discover more from Data Analyst Interview

Subscribe now to keep reading and get access to the full archive.

Continue reading

✉ WhatsApp