Preparing Data for scikit-learn
In scikit-learn, that form is the NumPy array.
Why Models Need Arrays
Before any machine learning model can learn from data, that data has to be in a form the library can accept. In scikit-learn, that form is the NumPy array. NumPy is one of the fundamental packages for scientific computing in Python, and it provides functionality for multidimensional arrays, high-level mathematical functions, and pseudorandom number generators. This article focuses on one piece of that picture: how you create a NumPy array, what kind of object you have once you do, and how to reason about it when something goes wrong.
The approach here is code first. You will read a short program, predict what it prints, and only then use the explanation to check your prediction. Pay attention to the gap between your prediction and the real output, because that gap is where understanding forms.
Predicting a Printed Array
Consider this program. It passes a list of two lists to np.array and then prints the result and its shape. Read it before you look at the output.
np.arraybuilds an object of the ndarray class from the nested listprint(arr)displays the array's contents- arr.shape reports the size along each axis
What do you think happens?
Before running it, what do you think the two print calls display? Sketch the rows and then state the shape.
Reveal answer
The first print shows a two-row array: [[1 2 3] [4 5 6]] (NumPy prints each row on its own line). The second print shows (2, 3), meaning two rows and three columns.
The outer list has two items, so the array has two rows. Each inner list has three items, so each row has three elements. Compare your sketch with the printed output: if the row count or column count differed, look back at how the nested list was written.
How np.array Reads Nested Lists
The argument to np.array in that program is a list whose two items are themselves lists. Each inner list becomes one row of the resulting two-dimensional array. The outer structure gives the array its two rows, and each row contributes three elements. So the value 1 sits in the first row and first column, while 6 sits in the second row and third column.
Indexing in Python starts at zero, so positions are labeled with zero-based row and column numbers. The diagram below shows each value in its cell, with row 0 being the first row and column 0 being the first column.
Reading Shape as Rows and Columns
The shape is the object's way of reporting its size. For the array above, the shape is (2, 3). The first number counts the rows, which is the length of the outer list, and the second number counts the columns, which is the length of each inner list. Axis 0 runs down the rows and axis 1 runs across the columns, so the axis numbers line up with the shape tuple position by position.
Predicting the shape of a new array
What shape does np.array produce for [[7, 8], [9, 10], [11, 12], [13, 14]]?
- 1Count the outer list
The outer list has four inner lists, so the array has four rows.
- 2Count one inner list
Each inner list, such as [7, 8], has two items, so each row has two columns.
- 3Combine into a shape
Rows first, then columns, gives (4, 2).
The shape is (4, 2): four rows and two columns.
The ndarray Class
The core functionality of NumPy is the ndarray class. The name is shorthand for an n-dimensional array, which is a multidimensional container of values. When the program calls np.array, it builds an object of this class. Objects of the ndarray class are referred to as NumPy arrays, or simply arrays.
The word n-dimensional means the same class can describe a one-dimensional list of values, a two-dimensional table like the one above, or higher-dimensional containers. The two-dimensional case is the one you will meet most often when preparing rows of samples and their features.
One Type for Every Element
A central rule of the ndarray class is that all elements of a NumPy array must be of the same type. A plain Python list has no such requirement: one list can hold an integer, a string, and a decimal number side by side. The array is a more constrained container, and that constraint is what lets it act as the common data structure for scikit-learn.
[1. 2.5 3. ]
['1' 'two' '3']- The integers 1 and 3 are stored alongside the decimal 2.5, so NumPy gives every element a common decimal type
- The string 'two' forces every element to be text, so the integers 1 and 3 come back as strings
Mistakes with Mixed-Type Input
Common mistake Assuming a mixed list keeps each value's original type
What it looks likenp.array([1, 'two', 3]) is expected to hold the integers 1 and 3 as numbers.
Why it failsAn ndarray stores one type for all elements, so NumPy converts the values to a common type.
Do this insteadCheck the array's output after creation. Keep each column or input field of one type before conversion.
Common mistake Ignoring the conversion step before calling scikit-learn
Why it failsscikit-learn takes in data as NumPy arrays, so data must be converted first.
Do this insteadConvert the data to a NumPy array in your workflow before any scikit-learn function is called.
Common mistake Reading the nested list as columns instead of rows, which swaps the two shape numbers
Converting Before scikit-learn
scikit-learn takes in data in the form of NumPy arrays. This is a requirement, not a stylistic preference: any data you want to use with scikit-learn has to be converted to a NumPy array first. Because of this, the array is the fundamental data structure of the library. When you load or build data for a model, the conversion step belongs in your workflow before you call any scikit-learn function.
When a result differs from your prediction, the location of the difference usually points to one of three places: the input list you handed to np.array, the call that created the array, or the step that printed or used it. Trace the program in that order, comparing what you expected at each line with what the code actually produces. The earliest line where expectation and output part ways is the place to investigate.
Tracing a Mismatch Step by Step
A colleague writes np.array([[1, 2], [3, 'four']]) and expects a two-row array of numbers with shape (2, 2). Trace where the expectation first breaks. Which line causes the change, and what would you check first?
Hints
- Identify whether the inner lists mix types, and what rule applies to every element of an ndarray.
- Compare the expected output at the
np.arrayline with the value that is actually stored in the array. - The shape can still be (2, 2) even when the element types have changed, so check the values as well as the shape.
Key Takeaways
np.arrayturns nested Python lists into a NumPy array, where each inner list forms one row, and the resulting object is an instance of the ndarray class.- The shape tuple reports rows first and then columns, so the outer list length and each inner list length determine the printed shape.
- All elements of a NumPy array must be of the same type, so mixed-type input can silently change the meaning of values.
- scikit-learn takes in data as NumPy arrays, so data must be converted to an array before any scikit-learn function is called.
- When results diverge from predictions, trace the input list, the array creation call, and the printing or usage step, in that order.