Decision trees can handle both categorical and numerical variables at the same time as features, there is not any problem in doing that.
Theory
Every split in a decision tree is based on a feature. If the feature is categorical, the split is done with the elements belonging to a particular class. If the feature is contiuous, the split is done with the elements higher than a threshold. At every split, the decision tree will take the best variable at that moment. This will be done according to an impurity measure with the splitted branches. And the fact that the variable used to do split is categorical or continuous is irrelevant (in fact, decision trees categorize contiuous variables by creating binary regions with the threshold).
Implementation
Although, at a theoretical level, is very natural for a decision tree to handle categorical variables, most of the implementations don't do it and only accept continuous variables:
- This answer reflects on decision trees on scikit-learn not handling categorical variables. However, one of the scikit-learn developers argues that
At the moment it cannot. However RF tends to be very robust to categorical features abusively encoded as integer features in practice.
- This other post comments about xgboost not handling categorical variables.
- rpart in R can handle categories passed as factors, as explained in here
- Lightgbm and catboost can handle categories. Catboost does an "on the fly" target encoding, while lightgbm needs you to encode the categorical variable using ordinal encoding.
Here's an example of how lightgbm handles categories:
import pandas as pd
from sklearn.datasets import load_iris
from lightgbm import LGBMRegressor
from category_encoders import OrdinalEncoder
X = load_iris()['data']
y = load_iris()['target']
X = OrdinalEncoder(cols=[3]).fit_transform(X)
dt = LGBMRegressor()
dt.fit(X, y, categorical_feature=[3])