Fitting and Transforming Data in scikit-learn
A very common job in machine learning is to fit a preprocessing model on a dataset and then transform that same dataset with it.
A Question Before the Code
A very common job in machine learning is to fit a preprocessing model on a dataset and then transform that same dataset with it. Scikit-learn gives you two ways to write this job. You can call fit and then transform as two separate steps, or you can call fit_transform once and receive the transformed data back directly. Both routes are legitimate, so the practical question is which one to use and why.
What do you think happens?
If scaler.fit(X).transform(X) and scaler.fit_transform(X) are run on the same data, what do you think is true of their results?
Reveal answer
The two results are the same, and the difference lies in how the computation is organized.
The source states that the chained form and the combined form give the same result. The choice between them is about how the computation is organized, not about what the output means.
Keep this question in mind as you read the code below. If the two approaches give the same answer, the reason to prefer one over the other has to come from somewhere else. The rest of this article works toward that answer.
Two Ways to Write the Same Job
The snippet below uses StandardScaler from sklearn.preprocessing. The first assignment chains fit and transform together. The second uses fit_transform. The small array X is defined here only so the code can run. The source leaves the definition of X to the reader, so treat this array as a stand-in for any dataset.
- StandardScaler is the transformer used in this snippet
scaler.fit(X).transform(X) chains two method calls on the same scalerscaler.fit_transform(X)makes one method call on the scaler
Running this code prints two arrays, and the source's point is that they hold the same values. The first line of the chained version does not produce the transformed data directly. It produces the scaler, and the transformed data appears only after the second call. The combined version gets to the transformed data in a single call.
Tracing the Chained Line
Read the chained line from left to right. Python evaluates scaler.fit(X) first. That call hands back the scaler, so the .transform(X) that follows is called on the returned object. Its output is what gets stored in X_scaled. Following the sequence this way lets you see exactly which steps the code requests, even before you know what each step computes internally.
The source does not describe what the fitting step computes inside StandardScaler, so this article does not go into that. For the purpose here, it is enough to know that fit is the step that works from the data, and transform is the step that applies the result to data.
Fit Learns, Transform Applies
A useful way to hold the two steps apart is to treat fit as learning and transform as applying. The fit step reads the data and produces a result that the scaler keeps. The transform step takes data and uses that kept result to produce the output. Your data flows through the scaler in the direction shown below.
Why Both Routes Give One Result
The source describes fit_transform as the method you use when you want to fit a model on a dataset and then transform it. Every scikit-learn model that has a transform method also has a fit_transform method. So fit_transform is not a special one-off tool for StandardScaler. It is a pattern offered across transformers.
| Aspect | scaler.fit(X).transform(X) | scaler.fit_transform(X) |
|---|---|---|
| Method calls on the scaler | Two, chained together | One combined call |
| What comes back from the first call | The scaler itself | Not applicable; one call returns the transformed data |
| Output stored in the variable | The result of transform | The transformed data directly |
| Result compared with the other route | Same result | Same result |
| Source's note on efficiency | Can usually be computed less efficiently | Often more efficient to compute |
Two call patterns for the same preprocessing job, as described in the source.
Because the outputs match, the difference is about how the computation is organized. The combined form asks scikit-learn for both steps in one request, and the source says this can often be computed more efficiently. The chained form keeps the two steps visibly separate, which can make the fit and transform stages easier to read in a longer program.
Training Data Versus Test Data
The source explicitly recommends fit_transform when you are transforming the training set. That makes it a sensible default in that case: you fit the preprocessing model on the training data and transform that same training data in one call. Because fit stores what it learns on the scaler, the same scaler can then be used with transform alone on other data.
The test set is handled by transform rather than by a new fit because transform applies the parameters already stored on the scaler. Calling fit on the test set would have the scaler learn from different data, which is not what the training-set guidance describes. Transform on the test set reuses what was learned from the training set.
When the Combined Call Saves Less Than Expected
This means the choice between the two routes is mostly a question of readability and workflow, with efficiency as a possible bonus. When you transform the training set, fit_transform is a sensible default. When a particular transformer or dataset gives no real computational advantage from combining the steps, the chained or separated form loses nothing in correctness, because both produce the same result.
Mistakes to Avoid
Common mistake Assuming fit_transform changes the output compared with fit followed by transform
Why it failsThe source states that the two routes give the same result. The difference is in how the computation is organized.
Do this insteadChoose between them based on structure and measured efficiency, not on a belief that the answers differ.
Common mistake Assuming fit_transform is always faster
Why it failsThe source says the combined call can often be computed more efficiently, and that this is not guaranteed for every model.
Do this insteadMeasure the speed on your own data and model before relying on it.
Common mistake Calling fit on the test set to match the training set
Why it failsfit learns parameters from the data it is given. Learning new parameters from the test set means the test data no longer uses the statistics learned from the training set.
Do this insteadFit on the training data, then use transform alone on the test data.
Common mistake Treating the chained line as one operation instead of two, when transform is called on the object returned by fit
Reading the Calls in a New Snippet
Here is a new line: X_train_scaled = scaler.fit(X_train).transform(X_train). Identify which call learns from the data, which call applies the learned result, and which object each call is made on. Then rewrite the line using fit_transform and state whether the output changes.
Hints
- Look at which method name is fit and which is transform.
- The first call in a chain returns the scaler, so the next call is made on that object.
- The source says the two forms give the same result.
A colleague writes X_test_scaled = scaler.fit_transform(X_test) after fitting the scaler on X_train. Explain why this may be a problem given the training-set guidance, and say what line should be used instead.
Hints
- Think about which data fit should learn from.
- Consider what transform does with the parameters stored on the scaler.
Key Takeaways
scaler.fit(X).transform(X) andscaler.fit_transform(X)give the same result; the difference is how the computation is organized.- fit learns from the data and stores the result on the scaler, while transform applies that stored result to data.
fit_transformis available on every scikit-learn transformer that has a transform method, and it is a sensible default when transforming the training set.- The combined call can often be computed more efficiently, but this is not guaranteed for every model, so measure any speed gain rather than assuming it.