POST 1 of 5 MorningAI/MLConcept
A DataFrame is a dict of NumPy arrays
If you understand NumPy from yesterday, you almost understand pandas. A DataFrame is, mechanically, a dict mapping column-name to typed array, plus a row index. That single sentence explains most of pandas' performance characteristics. Reading a column — df['col'] — is O(1). It's a pointer to the underlying NumPy array. No copying. Vectorised operations on columns — df['a'] + df['b'] — run in C, not Python. NumPy under the hood. Fast. Reading a row by position — df.iloc[i] — has to construct a Series across all columns. Slower than reading a column. Still constant time per row, but multi-column access pays a per-row constructor cost. Iterating row by row with df.iterrows() — disastrous. For each row, pandas constructs a new Series. The Python overhead per row dominates. On a million-row DataFrame, iterrows can take minutes for what vectorised code does in milliseconds. The rule that drops out — operate on whole columns, not on individual rows. df['a'] + df['b'] (vectorised) instead of [a + b for a, b in zip(df['a'], df['b'])] (Python loop) instead of df.iterrows() with row.a + row.b (slowest). Other consequences of the dict-of-arrays model: Column types are uniform. Each column is one NumPy dtype. Mixed types in a column become 'object' dtype, which loses NumPy's speed advantages. The row index is a separate first-class structure. It's not just a counter — it can be a date, a string, a multi-level tuple. df.loc[index_value] uses the index for lookup; df.iloc[position] uses the integer position. Missing values exist via NaN (for floats) or pd.NA (newer, type-aware). Either way, special handling — most operations propagate missing values; some functions skip them. Know the model. The performance and behaviour follow.
#NumPy#Pandas#DataScience#Python#100DaysOfCode#Pandas