dsldPy: the Python interface to DSLD

dsldPy makes DSLD’s statistical models, fairness methods, and visualizations available from Python through rpy2. The models use the R implementation, so R and the R package dsld must be installed first.

Installation

This repository contains Python interface version 2.0.0, paired with R package version 2.0.0. Install both from the same checkout.

  1. Install R and confirm that R RHOME works in your terminal.
  2. Install the R package using the R installation instructions.
  3. From the repository root, install the Python interface into your environment:
python -m pip install ./inst

Python 3.9 or newer is required. For the example notebooks and their execution tools, use python -m pip install './inst[examples]'.

pip install dsldPy installs the version available on PyPI, which may differ from this checkout. It does not install R or the R package. DSLD is currently archived on CRAN; installing the local R source is required for this maintenance version.

Data and a first model

Functions accept either pandas data frames or R data frames. pandas categorical columns preserve their levels when converted to R. preprocess_data() is a convenient way to specify categorical and numeric columns explicitly; it returns an R data frame.

The following example uses data bundled with the R package, so no file paths need to be edited:

import rpy2.robjects as ro
from rpy2.robjects.packages import importr
from dsldPy import (
    dsld_Rpy2_RDataframeToPandas,
    preprocess_data,
    dsldPyLinear,
    dsldPyLinearSummary,
    dsldPyLinearPredict,
)

bundled = ro.Environment()
importr("utils").data("svcensus", package="dsld", envir=bundled)
wages = dsld_Rpy2_RDataframeToPandas(bundled["svcensus"])
wages = wages[["age", "wageinc", "gender"]]
r_wages = preprocess_data(wages, cat_features=["gender"],
                          num_features=["age", "wageinc"])

model = dsldPyLinear(r_wages, "wageinc", "gender")
dsldPyLinearSummary(model)
predictions = dsldPyLinearPredict(model, wages[["age", "gender"]].head())
print(predictions)

For separate group fits, pass interactions=True; prediction points then contain the nonsensitive predictors. dsldPyLogit() supports binary outcomes with yesYVal identifying the positive label.

Fair prediction with held-out data

Use held-out rows for evaluating model quality. This example keeps the positive class labels and the sensitive attribute available for evaluation:

from dsldPy import dsldPyQeFairRF, dsldPyQeFairML_Predict, dsldPyFairUtils

importr("utils").data("compas1", package="dsld", envir=bundled)
records = dsld_Rpy2_RDataframeToPandas(bundled["compas1"])
records = records[["age", "decile_score", "priors_count", "race", "two_year_recid"]]
records = records.sample(n=800, random_state=2026)
train = records.sample(frac=0.75, random_state=2026)
test = records.drop(train.index)

ro.r["set.seed"](2026)  # Seed R as well as the pandas split.
fair_model = dsldPyQeFairRF(
    train, "two_year_recid", "race",
    deweightPars={"decile_score": 0.3}, nTree=100, yesYVal="Yes",
)
result = dsldPyQeFairML_Predict(fair_model, test.drop(columns="two_year_recid"))
error = (test["two_year_recid"].astype(str).to_numpy() != result["test_classes"]).mean()
print("Test misclassification rate:", error)
print("Group correlations:", result["test_correlations"])

ro.r["set.seed"](2026)
tradeoff = dsldPyFairUtils(
    train, "two_year_recid", "race", "dsldQeFairRF",
    deweightPars={"decile_score": [1.0, 0.3]}, yesYVal="Yes", k_folds=3,
    model_args={"nTree": 50},
)
print(tradeoff)

Return values and metric names

Graphics

dsldPyDensitybyS(..., graphType="plotly") returns and displays a Python Plotly figure, including its bandwidth slider. Use graphType="plot" for a static image. Static R plots close their graphics devices and remove temporary images after displaying them. dsldPyFreqPCoord(..., show=False) renders without showing the image; plot_filename saves an explicit output file.

dsldPyScatterPlot3D() uses Python Plotly directly and returns its figure. dsldPyConfounders() displays each relevant table or density plot and returns the results by column name. dsldPyIamb() saves its network plot to the requested filename.

Examples and function guide

The notebooks load the bundled datasets, set random seeds, and run without machine-specific file paths:

Area Functions
Group comparisons dsldPyLinear, dsldPyLogit, dsldPyML
Confounders and proxies dsldPyCHunting, dsldPyOHunting, dsldPyTakeALookAround
Matching and discovery dsldPyMatchedATE, dsldPyIamb
Tables and graphics dsldPyFrequencybyS, dsldPyDensitybyS, dsldPyConfounders, dsldPyFreqPCoord, dsldPyScatterPlot3D, dsldPyConditDisparity
fairml wrappers dsldPyFrrm, dsldPyFgrrm, dsldPyNclm, dsldPyZlm, dsldPyZlrm
EDF wrappers dsldPyQeFairKNN, dsldPyQeFairRF, dsldPyQeFairRidgeLin, dsldPyQeFairRidgeLog
Parameter grids dsldPyFairUtils

Troubleshooting

For issues, contact Aditya Mittal at mittalaa@uci.edu or use GitHub issues. Include Python and R versions and a small reproducible example.

Authors

Norm Matloff, Aditya Mittal, Taha Abdullah, Arjun Ashok, Shubhada Martha, Billy Ouattara, Jonathan Tran, and Brandon Zarate.