{"action":"created","comment":{"url":"https://api.github.com/repos/DeclareDesign/estimatr/pulls/comments/174007387","pull_request_review_id":103284683,"id":174007387,"diff_hunk":"@@ -106,349 +108,395 @@ List lm_solver(Eigen::Map<Eigen::MatrixXd>& Xfull,\n     // Rcout << XtX_inv << std::endl;\n   }\n \n-  // TODO See whether beta was not fit (i.e. dependent columns of X)\n-  //Eigen::ArrayBase<Derived> = beta_out.array().isNaN();\n+  return List::create(\n+    _[\"beta_hat\"]= beta_out,\n+    _[\"XtX_inv\"]= XtX_inv\n+  );\n+}\n \n-  // Two copies of the data because both weighted and unweighted needed for CR2\n-  Eigen::MatrixXd Xoriginal(n, r);\n-  Eigen::MatrixXd Xoriginalfull(n, p);\n-  Eigen::MatrixXd X(n, r);\n-  Eigen::VectorXd beta_hat(r);\n-  Eigen::ArrayXd weights(n);\n-  bool weighted = Xunweighted.isNotNull();\n-  if (weighted) {\n-    weights = Rcpp::as<Eigen::Map<Eigen::ArrayXd> >(weight);\n-    Xoriginalfull = Rcpp::as<Eigen::Map<Eigen::MatrixXd> >(Xunweighted);\n-  }\n-  // Reorder objects if rank-deficient\n-  if (r < p) {\n-    // Rcout << \"Rank-deficient!\" << std::endl;\n-    // Rcout << \"beta_out:\" << beta_out << std::endl;\n-\n-    int j = 0;\n-    for (int i = 0; i < p; i++) {\n-      // Rcout << \"isnan: \" << std::isnan(beta_out(i)) << std::endl;\n-      if (!std::isnan(beta_out(i))) {\n-        // Rcout << \"not NA: \" << i << std::endl;\n-        beta_hat(j) = beta_out(i);\n-        X.col(j) = Xfull.col(i);\n-        if (weighted) {\n-          Xoriginal.col(j) = Xoriginalfull.col(i);\n-        } else {\n-          Xoriginal.col(j) = Xfull.col(i);\n-        }\n-        j++;\n-      }\n-    }\n-  } else {\n-    beta_hat = beta_out;\n-    X = Xfull;\n-    if (weighted) {\n-      Xoriginal = Xoriginalfull;\n-    } else {\n-      Xoriginal = Xfull;\n-    }\n+// [[Rcpp::export]]\n+List lm_variance(const Eigen::Map<Eigen::MatrixXd>& X,\n+                 const Eigen::Map<Eigen::MatrixXd>& XtX_inv,\n+                 const Eigen::Map<Eigen::MatrixXd>& ei,\n+                 const Rcpp::Nullable<Rcpp::IntegerVector> & cluster,\n+                 const int & J,\n+                 const bool & ci,\n+                 const String type,\n+                 const std::vector<bool> & which_covs) {\n+\n+  const int n(X.rows()), r(X.cols()), ny(ei.cols());\n+  const double clustered = ((type == \"stata\") || (type == \"CR0\"));\n+  const int npars = r * ny;\n+  int sandwich_size = n;\n+  if (clustered) {\n+    sandwich_size = J;\n   }\n \n   // Rcout << \"X:\" << X << std::endl << std::endl;\n-  // Rcout << \"Xoriginal:\" << Xoriginal << std::endl << std::endl;\n-  // Rcout << \"beta_hat:\" << beta_hat << std::endl << std::endl;\n-\n-  Eigen::VectorXd dof = Eigen::VectorXd::Constant(r, -99.0);\n-  Eigen::VectorXd ei = Eigen::VectorXd::Constant(n, -99.0);\n-  double s2 = -99.0;\n+  // Rcout << \"ny: \" << ny << std::endl;\n+  // Rcout << \"ei: \" << std::endl << ei << std::endl;\n+  Eigen::MatrixXd Vcov_hat;\n+  Eigen::VectorXd dof = Eigen::VectorXd::Constant(npars, -99.0);\n+  Eigen::MatrixXd s2 = Eigen::MatrixXd::Constant(ny, ny, -99.0);\n \n   // Standard error calculations\n-  if (type != \"none\"){\n-\n-    // residuals\n-    ei = y - X * beta_hat;\n-    s2 = ei.dot(ei)/(n - r);\n+  if (type == \"classical\") {\n+    // Classical\n+    s2 = AtA(ei)/((double)n - (double)r);\n+    Vcov_hat = Kr(s2, XtX_inv);\n \n-    // Rcout << ei << std::endl;\n+    dof.fill(n - r);\n \n-    if (type == \"classical\") {\n-\n-      Vcov_hat = s2 * XtX_inv;\n-\n-    } else if ( (type == \"HC0\") | (type == \"HC1\") | (type == \"HC2\") | (type == \"HC3\") ) {\n-\n-      // hat values\n-      Eigen::ArrayXd ei2 = ei.array().pow(2);\n+  } else {\n+    // Robust\n+    Eigen::MatrixXd temp_omega = ei.array().pow(2);\n \n-      if(type == \"HC0\"){\n+    s2 = temp_omega.colwise().sum()/((double)n - (double)r);\n \n-        Vcov_hat = XtX_inv * (X.transpose() * ei2.matrix().asDiagonal()) * X * XtX_inv;\n+    dof.fill(n - r);\n \n-      } else if (type == \"HC1\") {\n+    Eigen::MatrixXd bread(npars, npars);\n+    Eigen::MatrixXd half_meat(sandwich_size, npars);\n+    if (ny == 1) {\n+      bread = XtX_inv;\n+    } else {\n+      bread = Kr(Eigen::MatrixXd::Identity(ny, ny), XtX_inv);\n+    }\n \n-        Vcov_hat =\n-          (double)n / ((double)n - (double)r) *\n-          XtX_inv * (X.transpose() * ei2.matrix().asDiagonal()) * X * XtX_inv;\n+    if ( !clustered ) {\n+      // Robust, no clusters\n \n-      } else if (type == \"HC2\") {\n-        Eigen::ArrayXd hii(n);\n+      if (type == \"HC2\") {\n \n         for (int i = 0; i < n; i++) {\n           Eigen::VectorXd Xi = X.row(i);\n-          hii(i) = ei2(i) / (1.0 - (Xi.transpose() * XtX_inv * Xi));\n+          temp_omega.row(i) = temp_omega.row(i) / (1.0 - (Xi.transpose() * XtX_inv * Xi));\n         }\n-        Vcov_hat = XtX_inv * (X.transpose() * hii.matrix().asDiagonal()) * X * XtX_inv;\n+\n       } else if (type == \"HC3\") {\n-        Eigen::ArrayXd hii(n);\n \n         for (int i = 0; i < n; i++) {\n           Eigen::VectorXd Xi = X.row(i);\n-          hii(i) = ei2(i) / (std::pow(1.0 - Xi.transpose() * XtX_inv * Xi, 2));\n+          temp_omega.row(i) = temp_omega.row(i) / (std::pow(1.0 - Xi.transpose() * XtX_inv * Xi, 2));\n         }\n-        Vcov_hat = XtX_inv * (X.transpose() * hii.matrix().asDiagonal()) * X * XtX_inv;\n+\n       }\n \n-    } else if ( (type == \"stata\") || (type == \"CR2\") || (type == \"CR0\") ) {\n+      // Rcout << \"temp_omega: \" << std::endl << temp_omega << std::endl;\n+      for (int m = 0; m < ny; m++) {\n+        half_meat.block(0, r*m, n, r) = X.array().colwise() * temp_omega.col(m).array().sqrt();\n+      }\n+\n+    } else {\n+      // Robust, clustered\n \n+      dof.fill(J - 1);\n       Eigen::Map<Eigen::ArrayXi> clusters = Rcpp::as<Eigen::Map<Eigen::ArrayXi> >(cluster);\n \n-      // Following code implements the clubSandwich package CR2 estimatr found here:\n-      // https://github.com/jepusto/clubSandwich\n-      // Much of the code is also a translation/adaptation from the R code in that package\n-      if (type == \"CR2\") {\n-\n-        Eigen::VectorXd cr2_eis;\n-        if (weighted) {\n-          // Instead of having X and Xt be weighted by sqrt(W), this has them weighted by W\n-          X.array().colwise() *= weights;\n-          // Unweighted residuals\n-          cr2_eis = y.array() / weights - (Xoriginal * beta_hat).array();\n-        } else {\n-          cr2_eis = ei;\n-        }\n+      double current_cluster = clusters(0);\n+      int clust_num = 0;\n+      int start_pos = 0;\n+      int len = 1;\n \n-        Eigen::MatrixXd tutX(J, r);\n+      // iterate over unique cluster values\n+      for (int i = 1; i <= n; ++i){\n \n-        // used for the dof corrction\n-        Eigen::MatrixXd H1s(r, r*J);\n-        Eigen::MatrixXd H2s(r, r*J);\n-        Eigen::MatrixXd H3s(r, r*J);\n-        Eigen::MatrixXd P_diags(r, J);\n+        if ((i == n) || (clusters(i) != current_cluster)) {\n+          // Rcout << current_cluster << std::endl;\n+          // Rcout << start_pos << std::endl;\n+          // Rcout << len << std::endl << std::endl;\n+          // Rcout <<  X.transpose().block(0, start_pos, r, len) << std::endl << std::endl;\n+          // Rcout << \"XteetX: \" << AtA(ei.segment(start_pos, len).transpose() * X.block(start_pos, 0, len, r)) << std::endl;\n \n-        Eigen::MatrixXd M_U_ct = XtX_inv.llt().matrixL();\n+          if (ny > 1) {\n \n-        Eigen::MatrixXd MUWTWUM = XtX_inv * X.transpose() * X * XtX_inv;\n-        Eigen::MatrixXd Omega_ct = MUWTWUM.llt().matrixL();\n+            // Stack residuals for this cluster from each model\n+            Eigen::MatrixXd ei_block = ei.block(start_pos, 0, len, ny);\n+            Eigen::Map<const Eigen::MatrixXd> ei_long(ei_block.data(), 1, len*ny);\n+            // Rcout << \"clust_num: \" << clust_num << std::endl;\n+            // Rcout << \"ei_long:\" << std::endl << ei_long << std::endl;\n+            half_meat.block(clust_num, 0, 1, npars) =\n+              ei_long *\n+              Kr(Eigen::MatrixXd::Identity(ny, ny), X.block(start_pos, 0, len, r));\n \n-        // Rcout << Omega_ct << std::endl;\n+          } else {\n+            // Rcout << \"clust_num: \" << clust_num << std::endl;\n+            // Rcout << \"ei:\" << std::endl << ei.block(start_pos, 0, len, 1).transpose() << std::endl;\n+            half_meat.row(clust_num) =\n+              ei.block(start_pos, 0, len, 1).transpose() *\n+              X.block(start_pos, 0, len, r);\n+          }\n \n-        // Rcout << \"SIZES\" << std::endl;\n-        // Rcout << \"X: \" << X.rows() << \"x\" << X.cols() << std::endl;\n-        // Rcout << \"Xoriginal: \" << Xoriginal.rows() << \"x\" << Xoriginal.cols() << std::endl;\n-        // Rcout << \"XtX_inv: \" << XtX_inv.rows() << \"x\" << XtX_inv.cols() << std::endl;\n \n-        double current_cluster = clusters(0);\n-        int j = 0;\n-        int start_pos = 0;\n-        int len = 1;\n+          if (i < n) {\n+            current_cluster = clusters(i);\n+            len = 1;\n+            start_pos = i;\n+          }\n \n-        // iterate over unique cluster values\n-        for(int i = 1; i <= n; ++i){\n+          clust_num++;\n \n-          //Rcout << \"clusters(i): \" << clusters(i) << std::endl;\n-          if ((i == n) || (clusters(i) != current_cluster)) {\n-            // Rcout << \"Current cluster: \" << current_cluster << std::endl;\n-            // Rcout << \"Starting position: \" << start_pos << std::endl;\n-            // Rcout << \"len: \" << len << std::endl << std::endl;\n-            // Rcout <<  X.transpose().block(0, start_pos, r, len) << std::endl << std::endl;\n+        } else {\n+          len++;\n+          continue;\n+        }\n+      }\n+    }\n \n-            // Rcout <<  X.transpose().block(0, start_pos, r, len) << std::endl << std::endl;\n+    // Rcout << \"bread: \" << std::endl<< bread << std::endl;\n+    // Rcout << \"half_meat:\" << std::endl << half_meat << std::endl;\n+    Vcov_hat = bread * (half_meat.transpose() * half_meat) * bread;\n \n-            // TODO H should be symmetric, shouldn't need to transpose\n-            Eigen::MatrixXd H = Xoriginal.block(start_pos, 0, len, r) * XtX_inv * X.block(start_pos, 0, len, r).transpose();\n+  }\n \n-            // Rcout << \"H: \" << H << std::endl;\n+  if (type == \"HC1\") {\n \n-            // Code from clubSandwich\n-            // uwTwu <- Map(function(uw, th) uw %*% th %*% t(uw),\n-            //             uw = UW_list, th = Theta_list)\n-            // MUWTWUM <- M_U %*% Reduce(\"+\", uwTwu) %*% M_U\n+    Vcov_hat =\n+      Vcov_hat *\n+      (double)n / ((double)n - (double)r);\n \n-            //(thet - h %*% thet - thet %*% t(h) + u %*% MUWTWUM %*% t(u))\n+  } else if (type == \"stata\") {\n \n-            // A' W R in clubSand notation\n-            // Rcout << \"At_WX: \" << (Eigen::MatrixXd::Identity(len, len) - H) - H.transpose() + Xoriginal.block(start_pos, 0, len, r) * MUWTWUM * Xoriginal.block(start_pos, 0, len, r).transpose() << std::endl;\n-            // Rcout << \"MUWTWUM: \" << MUWTWUM << std::endl;\n+    // Rcout << \"correction: \" << (((double)J * (n - 1)) / (((double)J - 1) * (n - r))) << std::endl;\n+    Vcov_hat =\n+      Vcov_hat *\n+      (((double)J * (n - 1)) / (((double)J - 1) * (n - r)));\n+  }\n \n-            Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> At_WX(\n-                (Eigen::MatrixXd::Identity(len, len) - H) - H.transpose() +\n-                  Xoriginal.block(start_pos, 0, len, r) * MUWTWUM * Xoriginal.block(start_pos, 0, len, r).transpose()\n-            );\n+  return List::create(_[\"Vcov_hat\"]= Vcov_hat,\n+                      _[\"dof\"]= dof,\n+                      _[\"res_var\"]= s2);\n+}\n \n-            Eigen::VectorXd eigvals = At_WX.eigenvalues();\n-            for (int m = 0; m < eigvals.size(); ++m) {\n-              if (eigvals(m) > std::pow(10.0, -12.0)) {\n-                eigvals(m) = 1.0 / std::sqrt(eigvals(m));\n-              } else {\n-                eigvals(m) = 0;\n-              }\n-            }\n \n-            // Rcout << \"Xblock: \" << X.block(start_pos, 0, len, r) << std::endl;\n-            // Rcout << \"At_WX_inv: \" << At_WX.operatorInverseSqrt() << std::endl;\n+//  if (weighted) {\n+// Instead of having X and Xt be weighted by sqrt(W), this has them weighted by W\n+// X.array().colwise() *= weights;\n+// }\n+// [[Rcpp::export]]\n+List lm_variance_cr2(const Eigen::Map<Eigen::MatrixXd>& X,\n+                     const Rcpp::Nullable<Rcpp::NumericMatrix> & Xunweighted,\n+                     const Eigen::Map<Eigen::MatrixXd>& XtX_inv,\n+                     const Eigen::Map<Eigen::MatrixXd>& ei,\n+                     const double weight_mean,\n+                     const Eigen::Map<Eigen::ArrayXi>& clusters,\n+                     const int & J,\n+                     const bool & ci,\n+                     const std::vector<bool> & which_covs) {\n \n-            // TODO mimic tol in arma implementation\n-            //Eigen::MatrixXd At_WX_inv = At_WX.operatorInverseSqrt() * X.block(start_pos, 0, len, r);\n-            Eigen::MatrixXd At_WX_inv =\n-              ((At_WX.eigenvectors() * eigvals.asDiagonal()) * At_WX.eigenvectors().transpose())\n-              * X.block(start_pos, 0, len, r);\n \n-            if (ci) {\n+  const int n(X.rows()), r(X.cols()), ny(ei.cols());\n+  const int npars = r * ny;\n \n-              Eigen::MatrixXd ME(r, len);\n-              if (weighted) {\n-                ME = (XtX_inv / weight_mean) * At_WX_inv.transpose();\n-              } else {\n-                ME = XtX_inv * At_WX_inv.transpose();\n-              }\n+  // Rcout << \"X:\" << X << std::endl << std::endl;\n+  // Rcout << \"beta_hat:\" << beta_hat << std::endl << std::endl;\n \n-              P_diags.col(j) = ME.array().pow(2).rowwise().sum();\n+  Eigen::MatrixXd Vcov_hat;\n+  Eigen::VectorXd dof = Eigen::VectorXd::Constant(npars, -99.0);\n \n-              Eigen::MatrixXd MEU = ME * Xoriginal.block(start_pos, 0, len, r);\n+  Eigen::MatrixXd Xoriginal(n, r);\n+  if (Xunweighted.isNotNull()) {\n+    Xoriginal = Rcpp::as<Eigen::Map<Eigen::MatrixXd> >(Xunweighted);\n+  } else {\n+    Xoriginal = X;\n+  }\n \n-              int p_pos = j*r;\n-              // Rcout << \"p_pos: \" << p_pos << std::endl;\n-              H1s.block(0, p_pos, r, r) = MEU * M_U_ct;\n-              H2s.block(0, p_pos, r, r) = ME * X.block(start_pos, 0, len, r) * M_U_ct;\n-              H3s.block(0, p_pos, r, r) = MEU * Omega_ct;\n-            }\n+  // Following code implements the clubSandwich package CR2 estimator found here:\n+  // https://github.com/jepusto/clubSandwich, using the R code as a template for\n+  // implementation\n \n-            // t(cr2_eis) %*% (I - P_ss)^{-1/2} %*% Xj\n-            // each ro  w is the contribution of the cluster to the meat\n-            // Below use  t(tutX) %*% tutX to sum contributions across clusters\n+  Eigen::MatrixXd bread(npars, npars);\n+  Eigen::MatrixXd half_meat(J, npars);\n+  if (ny == 1) {\n+    bread = XtX_inv;\n+  } else {\n+    bread = Kr(Eigen::MatrixXd::Identity(ny, ny), XtX_inv);\n+  }\n \n-            // Rcout << \"At_WX_inv: \" << At_WX_inv << std::endl;\n-            // Rcout << \"cr2_eis: \" << cr2_eis.segment(start_pos, len).transpose() << std::endl;\n-            tutX.row(j) = cr2_eis.segment(start_pos, len).transpose() * At_WX_inv;\n+  // used for the dof corrction\n+  Eigen::MatrixXd H1s(r, r*J);\n+  Eigen::MatrixXd H2s(r, r*J);\n+  Eigen::MatrixXd H3s(r, r*J);\n+  Eigen::MatrixXd P_diags(r, J);\n \n-            if (i < n) {\n-              current_cluster = clusters(i);\n-              len = 1;\n-              start_pos = i;\n-              j++;\n-            }\n+  Eigen::MatrixXd M_U_ct = XtX_inv.llt().matrixL();\n+  Eigen::MatrixXd MUWTWUM = XtX_inv * X.transpose() * X * XtX_inv;\n+  Eigen::MatrixXd Omega_ct = MUWTWUM.llt().matrixL();\n \n+  // Rcout << Omega_ct << std::endl;\n \n-          } else {\n-            len++;\n-            continue;\n-          }\n+  // Rcout << \"SIZES\" << std::endl;\n+  // Rcout << \"X: \" << X.rows() << \"x\" << X.cols() << std::endl;\n+  // Rcout << \"Xoriginal: \" << Xoriginal.rows() << \"x\" << Xoriginal.cols() << std::endl;\n+  // Rcout << \"XtX_inv: \" << XtX_inv.rows() << \"x\" << XtX_inv.cols() << std::endl;\n \n-        }\n+  double current_cluster = clusters(0);\n+  int clust_num = 0;\n+  int start_pos = 0;\n+  int len = 1;\n \n+  // Rcout << \"ei: \" << std::endl << ei << std::endl;\n \n-        // Rcout << \"XtX_inv: \" << std::endl << XtX_inv << std::endl;\n-        // Rcout << \"tutX: \" << std::endl << tutX << std::endl;\n+  // iterate over unique cluster values\n+  for(int i = 1; i <= n; ++i){\n \n-        Vcov_hat = XtX_inv * (tutX.transpose() * tutX) * XtX_inv;\n+    //Rcout << \"clusters(i): \" << clusters(i) << std::endl;\n+    if ((i == n) || (clusters(i) != current_cluster)) {\n+      // Rcout << \"Current cluster: \" << current_cluster << std::endl;\n+      // Rcout << \"Starting position: \" << start_pos << std::endl;\n+      // Rcout << \"len: \" << len << std::endl << std::endl;\n+      // Rcout <<  X.transpose().block(0, start_pos, r, len) << std::endl << std::endl;\n \n-        // Rcout << \"H1s\" << std::endl << std::endl;\n-        // Rcout << H1s << std::endl << std::endl;\n-        // Rcout << \"H2s\" << std::endl << std::endl;\n-        // Rcout << H2s << std::endl << std::endl;\n-        // Rcout << \"H3s\" << std::endl << std::endl;\n-        // Rcout << H3s << std::endl << std::endl;\n+      // Rcout <<  X.transpose().block(0, start_pos, r, len) << std::endl << std::endl;\n \n-        if (ci) {\n-          dof.fill(-99);\n-          int k = 0;\n-          for(int j = 0; j < p; j++){\n-            // only compute for covars that we need the DoF for\n-            if (!std::isnan(beta_out(j))) {\n-              if (which_covs[j]) {\n+      // TODO H should be symmetric, shouldn't need to transpose\n+      Eigen::MatrixXd H =\n+        Xoriginal.block(start_pos, 0, len, r) *\n+        XtX_inv *\n+        X.block(start_pos, 0, len, r).transpose();\n \n-                Eigen::MatrixXd H1t = H1s.row(k);\n-                Eigen::MatrixXd H2t = H2s.row(k);\n-                Eigen::MatrixXd H3t = H3s.row(k);\n-                // Rcout << H1t << std::endl<< std::endl;\n+      // Rcout << \"H: \" << H << std::endl;\n \n-                H1t.resize(r, J);\n-                H2t.resize(r, J);\n-                H3t.resize(r, J);\n+      // Code from clubSandwich\n+      // uwTwu <- Map(function(uw, th) uw %*% th %*% t(uw),\n+      //             uw = UW_list, th = Theta_list)\n+      // MUWTWUM <- M_U %*% Reduce(\"+\", uwTwu) %*% M_U\n \n-                // Rcout << H1t << std::endl<< std::endl;\n+      //(thet - h %*% thet - thet %*% t(h) + u %*% MUWTWUM %*% t(u))\n \n-                Eigen::MatrixXd uf = H1t.transpose() * H2t;\n-                Eigen::MatrixXd P_row = P_diags.row(k).asDiagonal();\n-                Eigen::MatrixXd P_array = (H3t.transpose()*H3t - uf - uf.transpose()) + P_row;\n-                // Rcout << \"P_array: \" << P_array << std::endl;\n+      // A' W R in clubSand notation\n+      // Rcout << \"At_WX: \" << (Eigen::MatrixXd::Identity(len, len) - H) - H.transpose() + Xoriginal.block(start_pos, 0, len, r) * MUWTWUM * Xoriginal.block(start_pos, 0, len, r).transpose() << std::endl;\n+      // Rcout << \"MUWTWUM: \" << MUWTWUM << std::endl;\n \n-                // Rcout << std::pow(P_array.trace(), 2) << \" and \" << P_array.array().pow(2).sum() << std::endl;\n-                dof(k) = std::pow(P_array.trace(), 2) / P_array.array().pow(2).sum();\n-              }\n-              k++;\n-            }\n-          }\n+      Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> At_WX(\n+          (Eigen::MatrixXd::Identity(len, len) - H) - H.transpose() +\n+            Xoriginal.block(start_pos, 0, len, r) *\n+            MUWTWUM *\n+            Xoriginal.block(start_pos, 0, len, r).transpose()\n+      );\n+\n+      Eigen::VectorXd eigvals = At_WX.eigenvalues();\n+      for (int m = 0; m < eigvals.size(); ++m) {\n+        if (eigvals(m) > std::pow(10.0, -12.0)) {\n+          eigvals(m) = 1.0 / std::sqrt(eigvals(m));","path":"src/lm_robust_helper.cpp","position":569,"original_position":569,"commit_id":"db11b7560171c2dd5a88d545b8a502fdcaefeb77","original_commit_id":"db11b7560171c2dd5a88d545b8a502fdcaefeb77","user":{"login":"nfultz","id":418638,"avatar_url":"https://avatars2.githubusercontent.com/u/418638?v=4","gravatar_id":"","url":"https://api.github.com/users/nfultz","html_url":"https://github.com/nfultz","followers_url":"https://api.github.com/users/nfultz/followers","following_url":"https://api.github.com/users/nfultz/following{/other_user}","gists_url":"https://api.github.com/users/nfultz/gists{/gist_id}","starred_url":"https://api.github.com/users/nfultz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nfultz/subscriptions","organizations_url":"https://api.github.com/users/nfultz/orgs","repos_url":"https://api.github.com/users/nfultz/repos","events_url":"https://api.github.com/users/nfultz/events{/privacy}","received_events_url":"https://api.github.com/users/nfultz/received_events","type":"User","site_admin":false},"body":":(","created_at":"2018-03-13T03:23:14Z","updated_at":"2018-03-13T03:26:00Z","html_url":"https://github.com/DeclareDesign/estimatr/pull/141#discussion_r174007387","pull_request_url":"https://api.github.com/repos/DeclareDesign/estimatr/pulls/141","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/DeclareDesign/estimatr/pulls/comments/174007387"},"html":{"href":"https://github.com/DeclareDesign/estimatr/pull/141#discussion_r174007387"},"pull_request":{"href":"https://api.github.com/repos/DeclareDesign/estimatr/pulls/141"}}},"pull_request":{"url":"https://api.github.com/repos/DeclareDesign/estimatr/pulls/141","id":170386372,"html_url":"https://github.com/DeclareDesign/estimatr/pull/141","diff_url":"https://github.com/DeclareDesign/estimatr/pull/141.diff","patch_url":"https://github.com/DeclareDesign/estimatr/pull/141.patch","issue_url":"https://api.github.com/repos/DeclareDesign/estimatr/issues/141","number":141,"state":"open","locked":false,"title":"Transfer NSE handling to rlang; implement IV estimator; refactor lm_robust_helper.cpp","user":{"login":"lukesonnet","id":5298599,"avatar_url":"https://avatars0.githubusercontent.com/u/5298599?v=4","gravatar_id":"","url":"https://api.github.com/users/lukesonnet","html_url":"https://github.com/lukesonnet","followers_url":"https://api.github.com/users/lukesonnet/followers","following_url":"https://api.github.com/users/lukesonnet/following{/other_user}","gists_url":"https://api.github.com/users/lukesonnet/gists{/gist_id}","starred_url":"https://api.github.com/users/lukesonnet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lukesonnet/subscriptions","organizations_url":"https://api.github.com/users/lukesonnet/orgs","repos_url":"https://api.github.com/users/lukesonnet/repos","events_url":"https://api.github.com/users/lukesonnet/events{/privacy}","received_events_url":"https://api.github.com/users/lukesonnet/received_events","type":"User","site_admin":false},"body":"This is a doozy of a PR. Each of the following bullet points is a major change:\r\n\r\n- refactor cpp to have separate LS solutions and variance estiamtion\r\n- refactor clean_model_data to use rlang\r\n- add support for multiple outcome variables\r\n- add instrumental variables","created_at":"2018-02-21T06:27:04Z","updated_at":"2018-03-13T03:26:00Z","closed_at":null,"merged_at":null,"merge_commit_sha":"5ec7d4af2be79596187780a7cc4a2bfa4680b84e","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/DeclareDesign/estimatr/pulls/141/commits","review_comments_url":"https://api.github.com/repos/DeclareDesign/estimatr/pulls/141/comments","review_comment_url":"https://api.github.com/repos/DeclareDesign/estimatr/pulls/comments{/number}","comments_url":"https://api.github.com/repos/DeclareDesign/estimatr/issues/141/comments","statuses_url":"https://api.github.com/repos/DeclareDesign/estimatr/statuses/db11b7560171c2dd5a88d545b8a502fdcaefeb77","head":{"label":"DeclareDesign:lukesonnet/iv","ref":"lukesonnet/iv","sha":"db11b7560171c2dd5a88d545b8a502fdcaefeb77","user":{"login":"DeclareDesign","id":15285286,"avatar_url":"https://avatars0.githubusercontent.com/u/15285286?v=4","gravatar_id":"","url":"https://api.github.com/users/DeclareDesign","html_url":"https://github.com/DeclareDesign","followers_url":"https://api.github.com/users/DeclareDesign/followers","following_url":"https://api.github.com/users/DeclareDesign/following{/other_user}","gists_url":"https://api.github.com/users/DeclareDesign/gists{/gist_id}","starred_url":"https://api.github.com/users/DeclareDesign/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/DeclareDesign/subscriptions","organizations_url":"https://api.github.com/users/DeclareDesign/orgs","repos_url":"https://api.github.com/users/DeclareDesign/repos","events_url":"https://api.github.com/users/DeclareDesign/events{/privacy}","received_events_url":"https://api.github.com/users/DeclareDesign/received_events","type":"Organization","site_admin":false},"repo":{"id":86030420,"name":"estimatr","full_name":"DeclareDesign/estimatr","owner":{"login":"DeclareDesign","id":15285286,"avatar_url":"https://avatars0.githubusercontent.com/u/15285286?v=4","gravatar_id":"","url":"https://api.github.com/users/DeclareDesign","html_url":"https://github.com/DeclareDesign","followers_url":"https://api.github.com/users/DeclareDesign/followers","following_url":"https://api.github.com/users/DeclareDesign/following{/other_user}","gists_url":"https://api.github.com/users/DeclareDesign/gists{/gist_id}","starred_url":"https://api.github.com/users/DeclareDesign/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/DeclareDesign/subscriptions","organizations_url":"https://api.github.com/users/DeclareDesign/orgs","repos_url":"https://api.github.com/users/DeclareDesign/repos","events_url":"https://api.github.com/users/DeclareDesign/events{/privacy}","received_events_url":"https://api.github.com/users/DeclareDesign/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/DeclareDesign/estimatr","description":"Fast Estimators for Design-Based Inference","fork":false,"url":"https://api.github.com/repos/DeclareDesign/estimatr","forks_url":"https://api.github.com/repos/DeclareDesign/estimatr/forks","keys_url":"https://api.github.com/repos/DeclareDesign/estimatr/keys{/key_id}","collaborators_url":"https://api.github.com/repos/DeclareDesign/estimatr/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/DeclareDesign/estimatr/teams","hooks_url":"https://api.github.com/repos/DeclareDesign/estimatr/hooks","issue_events_url":"https://api.github.com/repos/DeclareDesign/estimatr/issues/events{/number}","events_url":"https://api.github.com/repos/DeclareDesign/estimatr/events","assignees_url":"https://api.github.com/repos/DeclareDesign/estimatr/assignees{/user}","branches_url":"https://api.github.com/repos/DeclareDesign/estimatr/branches{/branch}","tags_url":"https://api.github.com/repos/DeclareDesign/estimatr/tags","blobs_url":"https://api.github.com/repos/DeclareDesign/estimatr/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/DeclareDesign/estimatr/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/DeclareDesign/estimatr/git/refs{/sha}","trees_url":"https://api.github.com/repos/DeclareDesign/estimatr/git/trees{/sha}","statuses_url":"https://api.github.com/repos/DeclareDesign/estimatr/statuses/{sha}","languages_url":"https://api.github.com/repos/DeclareDesign/estimatr/languages","stargazers_url":"https://api.github.com/repos/DeclareDesign/estimatr/stargazers","contributors_url":"https://api.github.com/repos/DeclareDesign/estimatr/contributors","subscribers_url":"https://api.github.com/repos/DeclareDesign/estimatr/subscribers","subscription_url":"https://api.github.com/repos/DeclareDesign/estimatr/subscription","commits_url":"https://api.github.com/repos/DeclareDesign/estimatr/commits{/sha}","git_commits_url":"https://api.github.com/repos/DeclareDesign/estimatr/git/commits{/sha}","comments_url":"https://api.github.com/repos/DeclareDesign/estimatr/comments{/number}","issue_comment_url":"https://api.github.com/repos/DeclareDesign/estimatr/issues/comments{/number}","contents_url":"https://api.github.com/repos/DeclareDesign/estimatr/contents/{+path}","compare_url":"https://api.github.com/repos/DeclareDesign/estimatr/compare/{base}...{head}","merges_url":"https://api.github.com/repos/DeclareDesign/estimatr/merges","archive_url":"https://api.github.com/repos/DeclareDesign/estimatr/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/DeclareDesign/estimatr/downloads","issues_url":"https://api.github.com/repos/DeclareDesign/estimatr/issues{/number}","pulls_url":"https://api.github.com/repos/DeclareDesign/estimatr/pulls{/number}","milestones_url":"https://api.github.com/repos/DeclareDesign/estimatr/milestones{/number}","notifications_url":"https://api.github.com/repos/DeclareDesign/estimatr/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/DeclareDesign/estimatr/labels{/name}","releases_url":"https://api.github.com/repos/DeclareDesign/estimatr/releases{/id}","deployments_url":"https://api.github.com/repos/DeclareDesign/estimatr/deployments","created_at":"2017-03-24T05:25:49Z","updated_at":"2018-02-27T12:32:38Z","pushed_at":"2018-03-13T02:11:04Z","git_url":"git://github.com/DeclareDesign/estimatr.git","ssh_url":"git@github.com:DeclareDesign/estimatr.git","clone_url":"https://github.com/DeclareDesign/estimatr.git","svn_url":"https://github.com/DeclareDesign/estimatr","homepage":"http://estimatr.declaredesign.org","size":3724,"stargazers_count":26,"watchers_count":26,"language":"R","has_issues":true,"has_projects":false,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":2,"mirror_url":null,"archived":false,"open_issues_count":31,"license":{"key":"other","name":"Other","spdx_id":null,"url":null},"forks":2,"open_issues":31,"watchers":26,"default_branch":"master"}},"base":{"label":"DeclareDesign:master","ref":"master","sha":"5b761f442e6ec18a0aa198309794cf3806228988","user":{"login":"DeclareDesign","id":15285286,"avatar_url":"https://avatars0.githubusercontent.com/u/15285286?v=4","gravatar_id":"","url":"https://api.github.com/users/DeclareDesign","html_url":"https://github.com/DeclareDesign","followers_url":"https://api.github.com/users/DeclareDesign/followers","following_url":"https://api.github.com/users/DeclareDesign/following{/other_user}","gists_url":"https://api.github.com/users/DeclareDesign/gists{/gist_id}","starred_url":"https://api.github.com/users/DeclareDesign/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/DeclareDesign/subscriptions","organizations_url":"https://api.github.com/users/DeclareDesign/orgs","repos_url":"https://api.github.com/users/DeclareDesign/repos","events_url":"https://api.github.com/users/DeclareDesign/events{/privacy}","received_events_url":"https://api.github.com/users/DeclareDesign/received_events","type":"Organization","site_admin":false},"repo":{"id":86030420,"name":"estimatr","full_name":"DeclareDesign/estimatr","owner":{"login":"DeclareDesign","id":15285286,"avatar_url":"https://avatars0.githubusercontent.com/u/15285286?v=4","gravatar_id":"","url":"https://api.github.com/users/DeclareDesign","html_url":"https://github.com/DeclareDesign","followers_url":"https://api.github.com/users/DeclareDesign/followers","following_url":"https://api.github.com/users/DeclareDesign/following{/other_user}","gists_url":"https://api.github.com/users/DeclareDesign/gists{/gist_id}","starred_url":"https://api.github.com/users/DeclareDesign/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/DeclareDesign/subscriptions","organizations_url":"https://api.github.com/users/DeclareDesign/orgs","repos_url":"https://api.github.com/users/DeclareDesign/repos","events_url":"https://api.github.com/users/DeclareDesign/events{/privacy}","received_events_url":"https://api.github.com/users/DeclareDesign/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/DeclareDesign/estimatr","description":"Fast Estimators for Design-Based Inference","fork":false,"url":"https://api.github.com/repos/DeclareDesign/estimatr","forks_url":"https://api.github.com/repos/DeclareDesign/estimatr/forks","keys_url":"https://api.github.com/repos/DeclareDesign/estimatr/keys{/key_id}","collaborators_url":"https://api.github.com/repos/DeclareDesign/estimatr/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/DeclareDesign/estimatr/teams","hooks_url":"https://api.github.com/repos/DeclareDesign/estimatr/hooks","issue_events_url":"https://api.github.com/repos/DeclareDesign/estimatr/issues/events{/number}","events_url":"https://api.github.com/repos/DeclareDesign/estimatr/events","assignees_url":"https://api.github.com/repos/DeclareDesign/estimatr/assignees{/user}","branches_url":"https://api.github.com/repos/DeclareDesign/estimatr/branches{/branch}","tags_url":"https://api.github.com/repos/DeclareDesign/estimatr/tags","blobs_url":"https://api.github.com/repos/DeclareDesign/estimatr/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/DeclareDesign/estimatr/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/DeclareDesign/estimatr/git/refs{/sha}","trees_url":"https://api.github.com/repos/DeclareDesign/estimatr/git/trees{/sha}","statuses_url":"https://api.github.com/repos/DeclareDesign/estimatr/statuses/{sha}","languages_url":"https://api.github.com/repos/DeclareDesign/estimatr/languages","stargazers_url":"https://api.github.com/repos/DeclareDesign/estimatr/stargazers","contributors_url":"https://api.github.com/repos/DeclareDesign/estimatr/contributors","subscribers_url":"https://api.github.com/repos/DeclareDesign/estimatr/subscribers","subscription_url":"https://api.github.com/repos/DeclareDesign/estimatr/subscription","commits_url":"https://api.github.com/repos/DeclareDesign/estimatr/commits{/sha}","git_commits_url":"https://api.github.com/repos/DeclareDesign/estimatr/git/commits{/sha}","comments_url":"https://api.github.com/repos/DeclareDesign/estimatr/comments{/number}","issue_comment_url":"https://api.github.com/repos/DeclareDesign/estimatr/issues/comments{/number}","contents_url":"https://api.github.com/repos/DeclareDesign/estimatr/contents/{+path}","compare_url":"https://api.github.com/repos/DeclareDesign/estimatr/compare/{base}...{head}","merges_url":"https://api.github.com/repos/DeclareDesign/estimatr/merges","archive_url":"https://api.github.com/repos/DeclareDesign/estimatr/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/DeclareDesign/estimatr/downloads","issues_url":"https://api.github.com/repos/DeclareDesign/estimatr/issues{/number}","pulls_url":"https://api.github.com/repos/DeclareDesign/estimatr/pulls{/number}","milestones_url":"https://api.github.com/repos/DeclareDesign/estimatr/milestones{/number}","notifications_url":"https://api.github.com/repos/DeclareDesign/estimatr/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/DeclareDesign/estimatr/labels{/name}","releases_url":"https://api.github.com/repos/DeclareDesign/estimatr/releases{/id}","deployments_url":"https://api.github.com/repos/DeclareDesign/estimatr/deployments","created_at":"2017-03-24T05:25:49Z","updated_at":"2018-02-27T12:32:38Z","pushed_at":"2018-03-13T02:11:04Z","git_url":"git://github.com/DeclareDesign/estimatr.git","ssh_url":"git@github.com:DeclareDesign/estimatr.git","clone_url":"https://github.com/DeclareDesign/estimatr.git","svn_url":"https://github.com/DeclareDesign/estimatr","homepage":"http://estimatr.declaredesign.org","size":3724,"stargazers_count":26,"watchers_count":26,"language":"R","has_issues":true,"has_projects":false,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":2,"mirror_url":null,"archived":false,"open_issues_count":31,"license":{"key":"other","name":"Other","spdx_id":null,"url":null},"forks":2,"open_issues":31,"watchers":26,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/DeclareDesign/estimatr/pulls/141"},"html":{"href":"https://github.com/DeclareDesign/estimatr/pull/141"},"issue":{"href":"https://api.github.com/repos/DeclareDesign/estimatr/issues/141"},"comments":{"href":"https://api.github.com/repos/DeclareDesign/estimatr/issues/141/comments"},"review_comments":{"href":"https://api.github.com/repos/DeclareDesign/estimatr/pulls/141/comments"},"review_comment":{"href":"https://api.github.com/repos/DeclareDesign/estimatr/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/DeclareDesign/estimatr/pulls/141/commits"},"statuses":{"href":"https://api.github.com/repos/DeclareDesign/estimatr/statuses/db11b7560171c2dd5a88d545b8a502fdcaefeb77"}},"author_association":"MEMBER"}}
{"actor":{"display_login":"nfultz"}}