LogisticRegression

Enables you to fit a logistic regression model to your data and then predict new class labels and probabilities.

LogisticRegression from SAS Viya on Heart Disease

Source

This example is adapted from Heart Disease UCI by Harshal Gadhe.

Data Preparation

About the data set

The original data contains 76 different attributes of patients from four different hospital databases. The goal is to determine if the attributes can be used to predict whether patients are diagnosed with heart disease. However, this data has been subset to contain only 14 factors from only the Cleveland database. Here are the variables included and their interpretations:

  • age
  • trestbps: resting blood pressure
  • chol: serum cholesterol
  • thalch: maximum heart reate achieved
  • ca: number of major vessels (0-3) colored by fluoroscopy
  • sex
  • cp: chest pain type
  • exang: exercise-induced angina
  • slope: slope of the peak exercise ST segment
  • thal: thalassemia (3 = normal; 6=fixed defect; 7 = reversable defect)
  • restecg: resting electrocardiographic results
  • fbs: fasting blood sugar
  • target: diagnosis of heart disease
  • oldpeak: ST depression induced by exercise relative to rest
import os
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sn

import warnings
warnings.filterwarnings("ignore", category=RuntimeWarning)
warnings.filterwarnings("ignore", category=UserWarning)
warnings.simplefilter(action='ignore', category=FutureWarning)
pd.options.mode.chained_assignment = None

Importing the data set

heart_df = pd.read_csv("https://raw.githubusercontent.com/sassoftware/sas-viya-workbench-examples/refs/heads/main/data/heart_disease.csv")
print(heart_df.head())
   age  trestbps  chol  thalch  oldpeak  ...  slope  thal  restecg  fbs  target
0   63       145   233     150      2.3  ...      0     1        0    1       0
1   67       160   286     108      1.5  ...      1     2        0    0       1
2   67       120   229     129      2.6  ...      1     0        0    0       1
3   37       130   250     187      3.5  ...      0     2        1    0       0
4   41       130   204     172      1.4  ...      2     2        0    0       0

Data Preprocessing

Print information about the data

Start by getting some general characteristics about the data set.

print(heart_df.info())
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 304 entries, 0 to 303
Data columns (total 14 columns):
 #   Column    Non-Null Count  Dtype  
---  ------    --------------  -----  
 0   age       304 non-null    int64  
 1   trestbps  304 non-null    int64  
 2   chol      304 non-null    int64  
 3   thalch    304 non-null    int64  
 4   oldpeak   304 non-null    float64
 5   ca        299 non-null    float64
 6   sex       304 non-null    int64  
 7   cp        304 non-null    int64  
 8   exang     304 non-null    int64  
 9   slope     304 non-null    int64  
 10  thal      304 non-null    int64  
 11  restecg   304 non-null    int64  
 12  fbs       304 non-null    int64  
 13  target    304 non-null    int64  
dtypes: float64(2), int64(12)
memory usage: 33.3 KB

Replacing NaN values with mean

There are some missing values in the data set. Replace the missing values with the mean for the column.

cols_sum_null = heart_df.isnull().sum()
print(cols_sum_null)
age         0
trestbps    0
chol        0
thalch      0
oldpeak     0
ca          5
sex         0
cp          0
exang       0
slope       0
thal        0
restecg     0
fbs         0
target      0
dtype: int64
hasnull_cols = cols_sum_null[cols_sum_null != 0]
for col in hasnull_cols.index:
    mean = heart_df[col].mean()
    heart_df[col].fillna(mean, inplace=True)
print(heart_df.isnull().sum())
age         0
trestbps    0
chol        0
thalch      0
oldpeak     0
ca          0
sex         0
cp          0
exang       0
slope       0
thal        0
restecg     0
fbs         0
target      0
dtype: int64

Correlations

print(heart_df.corr())
               age  trestbps      chol  ...   restecg       fbs    target
age       1.000000  0.281916  0.225333  ... -0.102142  0.120826  0.228467
trestbps  0.281916  1.000000  0.129773  ... -0.119188  0.175419  0.150904
chol      0.225333  0.129773  1.000000  ... -0.142105  0.012782  0.091021
thalch   -0.401508 -0.045660 -0.014568  ...  0.034189 -0.009941 -0.419619
oldpeak   0.209235  0.189202  0.052615  ... -0.050019  0.006968  0.426069
ca        0.354519  0.098706  0.117576  ... -0.107101  0.143925  0.456962
sex      -0.102636 -0.064622 -0.203126  ... -0.057334  0.046870  0.274144
cp       -0.064347  0.041611 -0.075577  ...  0.044318  0.097061 -0.433479
exang     0.096937  0.064930  0.065811  ... -0.063887  0.026593  0.433054
slope    -0.168549 -0.117505 -0.003035  ...  0.083403 -0.061122 -0.341159
thal     -0.105685 -0.123009 -0.011651  ...  0.025765 -0.065833 -0.510246
restecg  -0.102142 -0.119188 -0.142105  ...  1.000000 -0.080011 -0.134547
fbs       0.120826  0.175419  0.012782  ... -0.080011  1.000000  0.026484
target    0.228467  0.150904  0.091021  ... -0.134547  0.026484  1.000000
[14 rows x 14 columns]

Visualizing the Data

Look at a variety of plots to get a sense of the data set.

  • a pair plot of each pair of variables
  • a heat map of the correlations
  • scatterplots of the target versus each factor
  • a histogram of the target's values
cat_threshold = 8
quantitative = [c for c in heart_df.columns if len(heart_df[c].unique()) > cat_threshold]

sn.pairplot(heart_df[quantitative])
SAS.pyplot(plt)
Output of the pair plot visualization
plt.figure(figsize=(12,10))
sn.heatmap(heart_df.corr(),annot=True,cmap=plt.cm.plasma)
SAS.pyplot(plt)
Output of the heat map visualization
plt.figure(figsize=(15,15))
for i in range(len(heart_df.columns)-1):
    plt.subplot(5, 3, i+1)
    sn.scatterplot(data=heart_df, x='target', y=heart_df.columns[i], hue='target')
    plt.xticks([0, 1])
plt.tight_layout(pad=4.0)
plt.show()
SAS.pyplot(plt)
Output of the scatterplot visualization
sn.countplot(x='target', hue='target', legend=False, data=heart_df)
plt.grid()
plt.ylabel("count")
SAS.pyplot(plt)
Output of the histogram visualization

Building and Training the Model

For details about using the classes in sasviya.ml, see the Python API documentation.

Data preprocessing

from sklearn.preprocessing import StandardScaler

sc=StandardScaler()
X=heart_df.drop('target',axis=1)
Y=heart_df['target']
heart_df=sc.fit(X).transform(X)

Creating training and test data

Split the original data by putting 75% of the data in the training set and 25% of the data into the test set.

from sklearn.model_selection import train_test_split
X_train,X_test,y_train,y_test=train_test_split(X,Y,test_size=0.25,random_state=3)

Training the model for six different algorithms

You will train six different models against the training set: LogisticRegression, DecisionTreeClassifier, SVC, ForestClassifier, KNeighborsClassifier, and GaussianNB. The latter two are sklearn classifiers.

from sasviya.ml.linear_model import LogisticRegression
from sasviya.ml.tree import DecisionTreeClassifier
from sasviya.ml.svm import SVC
from sasviya.ml.tree import ForestClassifier

from sklearn.neighbors import KNeighborsClassifier
from sklearn.naive_bayes import GaussianNB
def model(X_train,y_train):
    models=[]

    lr = LogisticRegression(
        solver='lbfgs',
        tol=1e-4,
        max_iter=1000)
    lr.fit(X_train,y_train)
    models.append(lr)

    tree=DecisionTreeClassifier()
    tree.fit(X_train,y_train)
    models.append(tree)

    svm=SVC(kernel='rbf', coef0=0.1, C=1.0)

    svm.fit(X_train,y_train)
    models.append(svm)

    knn=KNeighborsClassifier(n_neighbors=5)
    knn.fit(X_train,y_train)
    models.append(knn)

    rfc=ForestClassifier()
    rfc.fit(X_train,y_train)
    models.append(rfc)

    nb=GaussianNB()
    nb.fit(X_train,y_train)
    models.append(nb)

    return models
models=model(X_train,y_train)

Gathering the accuracy scores

After running the six models, you should examine how well they did relative to each other. For each, gather the accuracy scores for the training and test data and add them into a summary dataframe.

from sklearn.metrics import accuracy_score
train_accuracy=[]
test_accuracy=[]

for m in models:
    train_accuracy.append(round(m.score(X_train, y_train),2))
    test_accuracy.append(round(m.score(X_test, y_test),2))

Accuracy_score=pd.DataFrame({
    'Model': [str(m.__repr__()).split('(')[0]for m in models],
    'Train_Accuracy':train_accuracy,
    'Test_Accuracy':test_accuracy
})

Finding the Best Model

After displaying the table of all accuracy scores for the training and test data, graph the test accuracy for each algorithm to see how they all fared on the data.

print(Accuracy_score)
[14 rows x 14 columns]
                    Model  Train_Accuracy  Test_Accuracy
0      LogisticRegression            0.88           0.82
1  DecisionTreeClassifier            0.90           0.78
2                     SVC            0.85           0.87
3    KNeighborsClassifier            0.75           0.64
4        ForestClassifier            0.92           0.83
5              GaussianNB            0.86           0.87
plt.figure(figsize=(12,6))
plt.plot(Accuracy_score['Model'],Accuracy_score['Test_Accuracy'],marker='x',color='red')
plt.xlabel('Model')
plt.ylabel('Test Accuracy')
plt.title('Test Accuracy by Model')
plt.grid()
SAS.pyplot(plt)
Test accuracy
Last updated: September 14, 2026