Repository: py-why/EconML (language: python)

Issue:
Issue associated with Causal Forest DML when calling Score() method
Hi, thanks for the fascinating work you guys provide!

I'm new to causal inference field and i found this package super to help build model. While i came across an IndexError when trying to call the model.score() as i built a causal forest model. 

The model parameter i used is as following:

```
model = CausalForestDML(
                model_y=RandomForestRegressor(n_estimators=150),
                model_t=RandomForestRegressor(n_estimators=150),
                n_jobs=-1,
                min_var_fraction_leaf=0.5,
                min_var_leaf_on_val=True,
                mc_iters = 4,
                n_estimators=50,
                subforest_size=5
                )
            
        model.tune(Y=Y, T=T, X=X, W=W)
        model.fit(Y=Y, T=T, W=W, X=X, cache_values=False)
```

And when i call the score method i received the following error:
<img width="665" alt="Screenshot 2023-04-22 at 11 00 22 PM" src="https://user-images.githubusercontent.com/47633393/233819170-9f227098-7185-4842-815e-d5a9429e485a.png">


And my guess for why it happened is the **mc_iter** parameter, as when i changed the **mc_iters = 2**, i can run the score method without any error. Really appreciate any advice or help, Thanks!


Discussion / hints:

Fix patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 82ba25bc6..413635a8f 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -124,7 +124,8 @@ jobs:
     - run: sudo apt-get -yq install graphviz
       name: Install graphviz
       if: ${{ matrix.install_graphviz }}
-    - run: pip install -e .${{ matrix.extras }}
+    # Add verbose flag to pip installation if in debug mode
+    - run: pip install -e .${{ matrix.extras }} ${{ fromJSON('["","-v"]')[runner.debug] }}
       name: Install econml
     - run: pip install pytest pytest-runner jupyter jupyter-client nbconvert nbformat seaborn xgboost tqdm
       name: Install test and notebook requirements
@@ -183,7 +184,8 @@ jobs:
         python-version: ${{ matrix.python-version }}
     - run: python -m pip install --upgrade pip && pip install --upgrade setuptools
       name: Ensure latest pip and setuptools
-    - run: pip install -e .${{ matrix.extras }}
+    # Add verbose flag to pip installation if in debug mode
+    - run: pip install -e .${{ matrix.extras }} ${{ fromJSON('["","-v"]')[runner.debug] }}
       name: Install econml
     - run: pip install pytest pytest-runner coverage
       name: Install pytest
@@ -224,7 +226,7 @@ jobs:
     steps:
     - run: exit 1
       name: At least one check failed or was cancelled
-      if: ${{ !(success()) }}
+      if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }}
     - run: exit 0
       name: All checks passed
-      if: ${{ success() }}
+      if: ${{ !(contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled')) }}
diff --git a/econml/_ensemble/_ensemble.py b/econml/_ensemble/_ensemble.py
index ff833f9ec..cdc23da4c 100644
--- a/econml/_ensemble/_ensemble.py
+++ b/econml/_ensemble/_ensemble.py
@@ -158,8 +158,8 @@ def _partition_estimators(n_estimators, n_jobs):
 
     # Partition estimators between jobs
     n_estimators_per_job = np.full(n_jobs, n_estimators // n_jobs,
-                                   dtype=np.int)
-    n_estimators_per_job[:n_estimators % n_jobs] += 1
+                                   dtype=int)
+    n_estimators_per_job[: n_estimators % n_jobs] += 1
     starts = np.cumsum(n_estimators_per_job)
 
     return n_jobs, n_estimators_per_job.tolist(), [0] + starts.tolist()
diff --git a/econml/_ortho_learner.py b/econml/_ortho_learner.py
index fdc9e7693..39a300ade 100644
--- a/econml/_ortho_learner.py
+++ b/econml/_ortho_learner.py
@@ -899,7 +899,7 @@ def score(self, Y, T, X=None, W=None, Z=None, sample_weight=None, groups=None):
                     nuisances = [np.zeros((n_iters * n_splits,) + nuis.shape) for nuis in nuisance_temp]
 
                 for it, nuis in enumerate(nuisance_temp):
-                    nuisances[it][i * n_iters + j] = nuis
+                    nuisances[it][j * n_iters + i] = nuis
 
         for it in range(len(nuisances)):
             nuisances[it] = np.mean(nuisances[it], axis=0)
diff --git a/econml/data/dynamic_panel_dgp.py b/econml/data/dynamic_panel_dgp.py
index 82b842912..cb7ffa17c 100644
--- a/econml/data/dynamic_panel_dgp.py
+++ b/econml/data/dynamic_panel_dgp.py
@@ -135,7 +135,7 @@ def simulate_residuals(ind):
 
 
 def simulate_residuals_all(res_df):
-    res_df_new = res_df.copy(deep=True)
+    res_df_new = res_df.astype(dtype='float64', copy=True, errors='raise')
     for i in range(res_df.shape[1]):
         res_df_new.iloc[:, i] = simulate_residuals(i)
     # demean the new residual again
diff --git a/notebooks/Solutions/Causal Interpretation for Ames Housing Price.ipynb b/notebooks/Solutions/Causal Interpretation for Ames Housing Price.ipynb
index 3b7b7d936..504d9e0f7 100644
--- a/notebooks/Solutions/Causal Interpretation for Ames Housing Price.ipynb
+++ b/notebooks/Solutions/Causal Interpretation for Ames Housing Price.ipynb
@@ -598,7 +598,7 @@
     "X = Xy.drop(columns = 'SalePrice')\n",
     "X_ohe = (\n",
     "    X\n",
-    "    .pipe(pd.get_dummies, prefix_sep = '_OHE_', columns = categorical)\n",
+    "    .pipe(pd.get_dummies, prefix_sep = '_OHE_', columns = categorical, dtype='uint8')\n",
     ")\n",
     "y = Xy['SalePrice']"
    ]
diff --git a/notebooks/Solutions/Causal Interpretation for Employee Attrition Dataset.ipynb b/notebooks/Solutions/Causal Interpretation for Employee Attrition Dataset.ipynb
index 24f00b8c2..94ba335da 100644
--- a/notebooks/Solutions/Causal Interpretation for Employee Attrition Dataset.ipynb
+++ b/notebooks/Solutions/Causal Interpretation for Employee Attrition Dataset.ipynb
@@ -432,7 +432,7 @@
    "outputs": [],
    "source": [
     "categorical = []\n",
-    "for col, value in attritionXData.iteritems():\n",
+    "for col, value in attritionXData.items():\n",
     "    if value.dtype == \"object\":\n",
     "        categorical.append(col)\n",
     "\n",
diff --git a/setup.cfg b/setup.cfg
index 2e0ca2c37..70529d9a0 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -39,7 +39,7 @@ install_requires =
     joblib >= 0.13.0
     statsmodels >= 0.10
     pandas
-    shap >= 0.38.1, < 0.41.0
+    shap >= 0.38.1, < 0.42.0
     lightgbm
 test_suite = econml.tests
 tests_require =
@@ -58,6 +58,8 @@ tf =
     tensorflow > 1.10, < 2.3;python_version < '3.9'
     ; Version capped due to tensorflow incompatibility
     protobuf < 4
+    ; Version capped due to tensorflow incompatibility
+    numpy < 1.24
 plt =
     graphviz
     ; Version capped due to shap incompatibility
@@ -70,6 +72,8 @@ all =
     tensorflow > 1.10, < 2.3
     ; Version capped due to tensorflow incompatibility
     protobuf < 4
+    ; Version capped due to tensorflow incompatibility
+    numpy < 1.24
     ; Version capped due to shap incompatibility
     matplotlib < 3.6.0
     dowhy < 0.9


Test patch:
diff --git a/econml/tests/test_dml.py b/econml/tests/test_dml.py
index 8105f7ec7..57b5c3ec4 100644
--- a/econml/tests/test_dml.py
+++ b/econml/tests/test_dml.py
@@ -1095,6 +1095,7 @@ def test_nuisance_scores(self):
                 est.fit(y, T, X=X, W=W)
                 assert len(est.nuisance_scores_t) == len(est.nuisance_scores_y) == mc_iters
                 assert len(est.nuisance_scores_t[0]) == len(est.nuisance_scores_y[0]) == cv
+                est.score(y, T, X=X, W=W)
 
     def test_categories(self):
         dmls = [LinearDML, SparseLinearDML]