8. Pandas Data Handling Missing Values Multi Indexing and Dataset Combination Notes
Course Administration and Lab Logistics
Lab 1 grading status: Lab 1 was designated as optional and ungraded. Any displayed grades for Lab 1 represent automated misgrading or Canvas system import errors and will be updated.
Regrading policy: All submitted materials, including Lab 2 grades and feedback, will be comprehensively regraded. Official grade publications will be formally announced on the DLC platform to establish the official date of release.
Lab weight recalculations: Initial syllabus displays showing individual lab weights at resulted from automated course transfer settings from a prior semester. Imported legacy labs were removed, and new labs are generated on a weekly basis. System weights recalculate dynamically as new lab assignments are added.
Expected lab count: Within a standard -week semester, excluding midterm week and final exam week (leaving approximately instruction weeks), the course structure anticipates approximately to (or up to ) total lab assignments.
Missing Value Sentinels in Pandas
Data science pipelines encounter missing values represented primarily by two sentinel values: Python
Noneand NumPyNaN. Pandas also provides its own native sentinel,pd.NA.NoneSentinel:Origin: Standard raw Python object.
Primary use case: Placeholders for missing object types or text strings.
Data type:
NoneType.Function execution behavior: Functions lacking an explicit return statement automatically return
None. Calling operations expecting return values onNoneTypeobjects raises aTypeError.Error propagation: Does not propagate gracefully through numerical operations; it immediately halts execution with a
TypeError.Identity and comparison:
Noneis a single, standardized singleton object in memory. EvaluatingNone == NonereturnsTrue.
NaNSentinel (np.nan):Origin: NumPy library (representing "Not a Number"), adhering to the IEEE 754 floating-point standard.
Primary use case: Replacement placeholder for missing numerical data.
Data type:
float.Error propagation: Propagates through numerical computations without raising execution errors. If an operand in a matrix multiplication or mathematical array operation is
NaN, the final calculated result propagates asNaN.Identity and comparison: Floating-point standards dictate that
np.nanis not equal to itself. Evaluatingnp.nan == np.nanreturnsFalse.
Pandas Native
pd.NASentinel:Origin: Introduced in Pandas to serve as a unified missing data indicator across standard data types (integers, booleans, strings).
Data type:
NAType.Propagation and logical behavior: Propagates through arithmetic and comparison operations (
pd.NA == pd.NAyieldspd.NA). Operates under three-valued logic rules:True or pd.NAevaluates toTrue.False and pd.NAevaluates toFalse.
Detection, Filtering, and Imputation of Missing Data
Detecting missing values:
isna()/isnull(): Scans a Pandas Series or DataFrame and generates a Boolean mask of identical dimensions, returningTruefor missing sentinels (None,NaN,pd.NA) andFalsefor valid observations.notnull()/notna(): Performs the logical inverse ofisnull(), returningTruefor valid non-missing data andFalsefor missing sentinels.
Filtering missing values (
dropna()):Generates a filtered dataset by removing records or features containing missing values.
Axis specification:
(default): Removes entire rows (records) containing missing data.: Removes entire columns (features) containing missing data.Thresholding (
threshparameter): Retains rows or columns based on a minimum count of non-missing entries. For example, setting a threshold equivalent to of total record length drops features containing more than missing data.
Imputing missing values (
fillna()):Replaces missing sentinels with explicitly declared constants, calculated metrics (e.g., mean, median), or spatial values.
Forward filling (
method='ffill'): Propagates the last observed valid entry forward to overwrite subsequent missing values.Backward filling (
method='bfill'): Propagates the next observed valid entry backward to overwrite preceding missing values.
Hierarchical Indexing (MultiIndex)
Conceptual overview: MultiIndex structures enable representation of higher-dimensional data within 1D Series or 2D DataFrames without forcing dataset unstacking into sparse tables.
Dimensional levels: Allows multiple nested levels of indexing along the row axis (
) or column axis ().MultiIndex construction methods:
pd.MultiIndex.from_tuples(): Constructs a hierarchical index from a list of tuple pairs.Tuple array format:
[('California', 2000), ('California', 2010), ('New York', 2000), ('New York', 2010), ('Texas', 2000), ('Texas', 2010)].Index mapping: The first tuple element maps to the primary (outer) index level; the second element maps to the secondary (inner) index level.
pd.MultiIndex.from_product(): Constructs hierarchical levels via the Cartesian product of multiple lists.Row product example: Cartesian product of years
[2013, 2014]and visit numbers[1, 2]yields index levels(2013, 1),(2013, 2),(2014, 1),(2014, 2).Column product example: Cartesian product of patient subjects
['Bob', 'Alice', 'Sue']and clinical metrics['HR', 'Temp']yields outer column levels for subjects and inner column levels for metrics.
Data restructuring and indexing operations:
reindex(): Re-aligns flat series data with aMultiIndexobject (e.g.,pop.reindex(index)).unstack(): Pivots inner row index levels into columns, converting a multi-indexed Series into a 2D DataFrame where primary indices serve as row labels and secondary indices serve as column headers.MultiIndex DataFrame creation syntax:
Data extraction and slicing:
Extracting outer column groups:
df['Bob']returns all inner column attributes (HR,Temp) across all rows for patient Bob.Extracting specific columns:
df['Bob', 'HR']extracts the heart rate series specifically for Bob.Row extraction via
.loc:df.loc[2013]retrieves all rows matching the primary row index2013(encompassing visit1and visit2).df.loc[(2013, 2)]retrieves specifically visit2of year2013.Point extraction: Explicitly combining column and row hierarchies in order extracts individual data points.
Combining Datasets: Concatenation (pd.concat)
Conceptual overview:
pd.concatis a top-level Pandas library function (pd.concat([df1, df2, ...])) designed to combine sequence objects (Series, DataFrames) along a designated axis.Structural execution:
Accepts lists or homogeneous dictionaries of DataFrames or Series.
Performs arbitrary multi-object combinations in a single pass.
Memory behavior:
pd.concatcreates temporary memory copies of input objects before forming the final combined structure, resulting in temporary memory overhead for large operations.Axis alignment settings:
(default): Stacks objects vertically (row-wise).: Concatenates objects horizontally (column-wise).
Set logic options:
Outer join (
join='outer', default): Computes the union of indices/columns across objects, insertingNaNfor non-aligned entries.Inner join (
join='inner'): Computes the intersection of indices/columns across objects, retaining only matching axes.
Label management and duplicate handling:
Concatenation preserves duplicate row index numbers and duplicate column names.
Accessing a duplicated column label (e.g.,
result['B']) returns a DataFrame containing all matching column instances rather than a single Series.Index resetting (
ignore_index=True): Clears legacy axis labels along the target concatenation dimension, assigning a clean continuous sequential integer range ().
Converting Series for row concatenation:
Appending a 1D Series
s2as a row to DataFramedf1requires transforming the Series into a 1-row DataFrame:
Calling
.to_frame().T(orpd.DataFrame(s2).T) turns a vertical 1-column Series into a horizontal 1-row DataFrame.
Combining Datasets: Relational Merges (pd.merge)
Conceptual overview:
pd.mergeis a top-level Pandas function (pd.merge(left, right, on=..., how=...)) that executes SQL-style relational database joins on keys or columns.Relational multiplicity types:
One-to-one join: Key values exist uniquely ( instance) in both left and right DataFrames.
One-to-many / Many-to-one join: Key values exist once in one DataFrame and multiple times in the target DataFrame. Matches replicate the single-instance record across every corresponding multi-instance record.
Many-to-many join: Key values exist multiple times across both DataFrames. The join constructs the full Cartesian product of matching rows.
Join methods (
howparameter):how='left': Uses key alignment prioritize to the left DataFrame. Preserves all left rows; missing right matches populate asNaN.how='right': Prioritizes alignment to the right DataFrame. Preserves all right rows; missing left matches populate asNaN.how='inner'(default): Retains only records whose join keys exist in both input DataFrames (intersection).how='outer': Preserves all key records across both input DataFrames (union), insertingNaNwhere matches are absent.how='cross': Computes the Cartesian product of all rows between both DataFrames, ignoring key column alignment.
Column suffix management:
When merging DataFrames that contain matching non-key column names, Pandas appends default suffixes
_xand_yto distinguish left and right features.Custom suffixes can be defined via a tuple (e.g.,
suffixes=('_left', '_right')orsuffixes=('_l', '_r')).
Combining Datasets: Object Joins (DataFrame.join)
Conceptual overview:
DataFrame.joinis an instance method defined directly on DataFrame objects (left.join(right)).Structural defaults:
Merges datasets on row indices by default.
Performs a left join by default (
how='left'), preserving all row indices of the primary calling DataFrame.
Parameter support: Accepts standard relational parameters including
how='outer',how='inner',how='right',on,lsuffix, andrsuffix.Comparative selection guide for dataset combination:
pd.concat: Optimal for direct stacking (top-to-bottom or side-by-side) of arrays or DataFrames with uniform labels.pd.merge: Optimal for relational, database-style merging based on key columns.DataFrame.join: Optimal for index-aligned side-by-side joins directly invoked on DataFrame instances.
Questions & Discussion
Question: If each lab is marked as worth on Canvas, does that mean the course contains only four labs total?
Response: No. Transferring course materials from the prior semester automatically copied existing lab entries and legacy weight distributions. Legacy labs were removed to allow new labs to be created weekly. Weights dynamically update as new assignments are introduced. Accounting for a -week semester minus midterm and final exam weeks ( instruction weeks), the course will include roughly to (or to ) total labs.
Question: What happens if a backward fill (
bfill) is executed on missing trailing values at the end of a dataset where no subsequent valid number exists?Response: Execution does not raise an error. The trailing missing values remain un-filled (or retain default
NaNstates) because there is no trailing valid number to propagate backward.
Question: If
pd.concatfollows set logic (union/intersection), why does horizontal concatenation retain duplicate column names?Response:
pd.concatalongexecutes an outer join across row indices by default while preserving column headers intact. Duplicate column names across concatenated DataFrames are retained. Accessing a duplicate column header (e.g.,result['B']) returns a DataFrame containing all matching columns.
Question: Can the
axisparameter inpd.concataccept values like or ?Response: Concatenation dimensions for standard 2D DataFrames are strictly defined along
(rows) and(columns).