Combining bag of words and other features in one model using sklearn and pandas
ML System Design practice on Codemia
Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.
Introduction
Text rarely tells the whole story in a machine learning problem. A classifier can often improve when bag-of-words features are combined with metadata such as ratings, categories, message length, or customer source.
Why Mixed Feature Sets Help
Bag-of-words features capture which terms appear in a document, but they do not automatically include structured information that may also be predictive. Imagine a support-ticket classifier. The words in the ticket matter, but so do the product tier, ticket age, and whether the request came from email or chat.
In scikit-learn, the cleanest way to combine these signals is to keep your data in a pandas DataFrame and let a ColumnTransformer apply the right preprocessing to each column. Text can go through CountVectorizer or TfidfVectorizer, numeric columns can be scaled, and categorical columns can be one-hot encoded. The resulting matrices are then concatenated into a single feature matrix.
Building a Combined Pipeline
The following example trains a sentiment model from review text plus a numeric score and a categorical source column.
This pattern matters because it keeps training and inference aligned. The same vocabulary, scaling parameters, and category mapping used during training are reused automatically when you call predict.
Working With Sparse and Dense Inputs
Text vectorizers normally produce a sparse matrix because most documents contain only a small fraction of the vocabulary. That is good for memory efficiency. Numeric and categorical features may be dense or sparse depending on the transformer.
When you use a ColumnTransformer, scikit-learn handles the concatenation for you. In many practical cases you do not need to manually call scipy.sparse.hstack. Manual stacking is still useful if you already computed the text matrix separately:
The pipeline approach is still preferable for production code because it reduces the chance of mismatched preprocessing steps.
When to Use Counts Versus TF-IDF
CountVectorizer gives raw term frequencies. It is simple and works well with models such as multinomial naive Bayes. TfidfVectorizer down-weights very common terms and is often a better default for linear models such as logistic regression or linear support vector machines.
The decision depends on both the dataset and the model. If your auxiliary features are strong, the exact text weighting scheme may matter less than having a reliable preprocessing pipeline. The important part is that all features are learned together from the same training split.
Common Pitfalls
- Fitting the vectorizer on the full dataset before the train-test split causes leakage and inflates evaluation metrics.
- Calling
.toarray()on a large sparse text matrix can exhaust memory quickly. - Forgetting to encode categorical columns will make most models fail because they cannot consume raw strings.
- Scaling numeric features separately from the saved pipeline can create train and inference mismatches.
- Misaligned pandas indices can silently pair the wrong rows if you preprocess text and tabular features in separate steps.
Summary
- Keep text and tabular data together in a pandas
DataFrameso row alignment stays simple. - Use
ColumnTransformerto apply text, numeric, and categorical preprocessing in one place. - Wrap preprocessing and the estimator in a
Pipelineso training and inference share the same logic. - Prefer sparse-aware workflows and avoid densifying text features unless the dataset is small.
- Choose
CountVectorizerorTfidfVectorizerbased on the model and dataset, then validate with cross-validation.
Related reading
- Combining CNN and bidirectional LSTM
- Combining feature extraction classes in scikit-learn
- Combining graphs is there a TensorFlow import_graph_def equivalent for C?
- Combining random forests built with different training sets in R
- Combining two Series into a DataFrame in pandas
- Common elements comparison between 2 lists
- Combining Weak Learners into a Strong Classifier
- Common causes of nans during training of neural networks
.png&w=3840&q=75)
Tackling System Design Interview Problems
A short course that equips you with the skills to approach system design interviews methodically.
Start the free courseNo course covers this one yet
Basis Lab writes one for you from a sentence about what you want to be able to do, then teaches it and checks you understood. Your first course is free.
Build my courseML System Design practice on Codemia
Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.