Comparing Variable Types Across Python, NumPy, and Pandas
By this point in the course, you've met a fairly wide cast of variable types, starting with the humble integer and float, moving through strings, lists and dictionaries, then NumPy arrays, and finally pandas Series and DataFrames. It's easy, at this stage, to experience these as a long, unconnected list of things to memorise. In reality, they form a fairly natural progression, and seeing them laid out side by side, rather than encountered one at a time across separate sessions, often makes the relationships between them click in a way that reading about them individually doesn't.
The table below is designed to be a reference you return to, not something to memorise in one sitting. Use it whenever you find yourself unsure which type is the right tool for a particular job, or when you're trying to recall exactly how one type differs from something that feels superficially similar (a list versus a tuple, say, or a NumPy array versus a plain Python list).
A few dimensions are worth paying close attention to as you read across the rows:
Ordering matters because it determines whether "the second item" is even a meaningful question to ask. Lists, tuples, strings, arrays, and DataFrames all have a well-defined order, you can always ask for the third element and get a sensible answer. Dictionaries technically preserve insertion order in modern Python, but you'd rarely rely on that order for anything meaningful, since you look things up by key, not position. Sets abandon ordering entirely, trading it for very fast membership checks ("is this value already in here?").
Mutability, whether a type can be changed after it's created, is one of the more subtle distinctions, and one that causes real bugs when overlooked. Strings and tuples are immutable: once created, any "change" actually produces a brand new object rather than modifying the original in place. This is why string methods like .upper() return a new string rather than altering the original. Lists, dictionaries, arrays, and DataFrames, by contrast, can be modified directly, which is powerful, but also means you need to be careful about accidentally modifying shared data, exactly the kind of "slices are views, not copies" behaviour we saw earlier with NumPy arrays.
Dimensionality is where the progression becomes especially visible. Single values like int and float are zero-dimensional, they're just one number. Lists and strings are one-dimensional, a single ordered row of values. NumPy arrays generalise this idea further, supporting not just 1D but 2D matrices and even higher-dimensional structures, which is precisely what makes them so well suited to things like images, time series, or simulation output. Pandas then takes the 2D case, arguably the single most common shape of real-world data, tables, spreadsheets, CSV files and gives it an extra layer of structure: labelled rows and columns, rather than just raw numerical position.
Type flexibility is another axis worth noticing. A Python list or dictionary can happily mix an integer, a string, and a float in the same collection, this flexibility is convenient but comes at a performance cost. NumPy trades that flexibility away deliberately: every element in an array shares the same dtype, which is exactly what allows NumPy to perform calculations so much faster than equivalent Python loops. Pandas then strikes a kind of middle ground: within a single column (a Series), every value shares one dtype, just like a NumPy array, but across an entire DataFrame, different columns are free to hold entirely different types side by side, numbers in one column, text in another, dates in a third, which is exactly what real datasets tend to need.
Perhaps the most useful way to internalise this table isn't to treat each row as an isolated fact, but to notice the throughline connecting them. A pandas DataFrame isn't a totally new invention arriving out of nowhere in Session 2, it's built directly on ideas you already know: it's a table made of columns, each column behaves like a labelled NumPy array (a Series), and a NumPy array itself behaves like a faster, stricter version of a Python list. Once that chain feels intuitive, decisions about which type to reach for in your own code become much less about memorising rules, and much more about simply asking: "is this a single value, an unordered bag, an ordered sequence, a numerical grid, or a full table?", and letting the answer point you to the right tool.
| Type | Library | Stores | Ordered? | Mutable? | Dimensions | Mixed types allowed? | Typical use |
|---|---|---|---|---|---|---|---|
int |
Core Python | A single whole number | N/A (single value) | No (a new int is created on change) | 0D (scalar) | N/A | Counting, indexing, whole-number arithmetic |
float |
Core Python | A single decimal number | N/A (single value) | No | 0D (scalar) | N/A | Measurements, calculations needing precision |
bool |
Core Python | A single True/False value |
N/A (single value) | No | 0D (scalar) | N/A | Conditions, flags, filters |
str |
Core Python | A sequence of characters | Yes | No (immutable) | 1D | No, characters only | Text, labels, messages |
list |
Core Python | An ordered collection of values | Yes | Yes | 1D (can nest for more) | Yes | General-purpose ordered collections |
tuple |
Core Python | An ordered, fixed collection of values | Yes | No (immutable) | 1D | Yes | Fixed groupings of values that shouldn't change |
dict |
Core Python | Key-value pairs | Insertion order preserved (3.7+) | Yes | N/A (mapping, not positional) | Yes (keys and values) | Structured lookup by label |
set |
Core Python | An unordered collection of unique values | No | Yes | 1D | Yes | Removing duplicates, membership testing |
np.ndarray |
NumPy | A grid of numerical (or fixed-type) values | Yes | Yes | 1D, 2D, or N-D | No, single fixed dtype per array |
Fast numerical computation across large datasets |
np.dtype |
NumPy | Describes the data type stored in an array (e.g. int64, float64) |
N/A | N/A | N/A | N/A | Controls memory usage and precision of array contents |
pd.Series |
Pandas | A single labelled, one-dimensional column of data | Yes (with an index) | Yes | 1D | No, one dtype per Series (like an ndarray) | A single labelled column, or one row/column from a DataFrame |
pd.DataFrame |
Pandas | A labelled, two-dimensional table of data | Yes (rows and columns both labelled) | Yes | 2D | Yes, each column can have its own dtype | Spreadsheet-like structured, tabular data |
pd.Index |
Pandas | The labels used to identify rows (or columns) | Yes | No (typically immutable) | 1D | Usually no, one dtype per Index | Labelling and aligning rows/columns in a Series or DataFrame |