diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..ecee69a --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,19 @@ +name: CI + +on: [push, pull_request] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v1 + - name: Print Directory + run: echo $(pwd) + - name: Docker + run: docker ps; docker ps -a + - name: Install numoy because I don't understand dependencies + run: pip install numpy + - name: Run Tests + run: python3 -m unittest discover -s Projects/project_2_packages diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..8fbe456 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,7 @@ +language: python +# command to install dependencies +install: + - pip install -r requirements.txt +# command to run tests +script: + - unittest diff --git a/Projects/Project_1_HendricksLeukhina.ipynb b/Projects/Project_1_HendricksLeukhina.ipynb index 93013a4..75a665b 100644 --- a/Projects/Project_1_HendricksLeukhina.ipynb +++ b/Projects/Project_1_HendricksLeukhina.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -99,9 +99,34 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 80, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 80, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], "source": [ "# Parameters to use in simulation\n", "gamma_min = 0.35\n", @@ -120,7 +145,28 @@ "x = np.linspace(10, 90, 9)\n", "\n", "ax.bar(x-1.5, y2_totalcredit_deciles, width=2.)\n", - "ax.bar(x+1.50, y2_totalcredit_deciles, width=2.)" + "#ax.bar(x+1.50, y2_totalcredit_deciles, width=2., color = \"red\")\n", + "\n", + "# Simulation\n", + "tc = 6 \n", + "ncoursesattempted = 12\n", + "ncreditspercourse = 3\n", + "ncreditsgrad = 125\n", + "count = 25000\n", + "modelprob = tpy.HeterogeneousProbabilityModel(gamma_min, gamma_1, gamma_2, sigma, tc,\n", + " ncoursesattempted, ncreditspercourse, ncreditsgrad)\n", + "ability, gpa, credits = modelprob.simulate(count)\n", + "twoyears = []\n", + "for array in credits:\n", + " twoyears.append(array[0] + array[1])\n", + "assert len(twoyears) == count\n", + "deciles = []\n", + "xax = []\n", + "for i in range(10,100,10):\n", + " xax.append(i)\n", + " deciles.append(np.percentile(twoyears, i))\n", + "ax.bar(xax, deciles, width = 2, color = \"black\")\n", + "#plt.scatter(deciles, deciles)" ] }, { @@ -136,9 +182,32 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], "source": [ "# Deciles from the data\n", "y2_totalcredit_deciles = np.array([\n", @@ -193,7 +262,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.4" + "version": "3.7.3" } }, "nbformat": 4, diff --git a/Projects/project_2_packages/LICENSE.MD b/Projects/project_2_packages/LICENSE.MD new file mode 100644 index 0000000..f131108 --- /dev/null +++ b/Projects/project_2_packages/LICENSE.MD @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) [2019] [Best Group 2] + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Projects/project_2_packages/README.MD b/Projects/project_2_packages/README.MD new file mode 100644 index 0000000..bbc2d26 --- /dev/null +++ b/Projects/project_2_packages/README.MD @@ -0,0 +1,3 @@ +# iv-reg package + +This is a simple package to perform instrumental variable estimation. diff --git a/Projects/project_2_packages/build/lib/iv_jett/__init__.py b/Projects/project_2_packages/build/lib/iv_jett/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/Projects/project_2_packages/build/lib/iv_jett/iv_init.py b/Projects/project_2_packages/build/lib/iv_jett/iv_init.py new file mode 100644 index 0000000..0b7e727 --- /dev/null +++ b/Projects/project_2_packages/build/lib/iv_jett/iv_init.py @@ -0,0 +1,74 @@ +''' + +Python Package to implement instrumental variables +Author: Group 2 NYU Pre docs +Date Created: December 6, 2019 + +''' +import numpy as np + + +def check_dim(a, b, c): + ''' + Check dimensions + ''' + try: + assert len(a.shape) == 2 & len(b.shape) == 2 & len(c.shape) == 2 + except: + raise Exception('Incorrect data dimension input') + + try: + assert a.shape[0] == b.shape[0] == c.shape[0] + except: + raise Exception('Number of observations not equal') + + try: + assert a.shape[1] <= b.shape[1] + except: + raise Exception('Model underidentified') + +def projection_matrix(b): + ''' + Inputs: + b (matrix) -- z + ''' + + P_b = b @ np.linalg.inv((np.transpose(b) @ b)) @ np.transpose(b) + return P_b + +def estimate_beta_iv(a, b, c, nocons = False): + ''' + Inputs: + a (matrix) -- x + b (matrix) -- z + c (matrix) -- y + ''' + if nocons != True and nocons != False: + raise Exception('nocons option misspecified') + + check_dim(a, b, c) + if nocons == False: + N = a.shape[0] + a_1 = np.ones((N,1)) + a = np.hstack((a_1,a)) + b_1 = np.ones((N,1)) + b = np.hstack((b_1, b)) + + + proj = projection_matrix(b) + b_1 = np.transpose(a) @ proj @ a + b_2 = np.linalg.inv(b_1) + b_3 = np.transpose(a) @ proj @ c + betas_all = b_2 @ b_3 + + if nocons == False: + cons = betas_all[0] + betas = betas_all[1:] + print("_cons: " + str(cons)) + for i in range(0, len(betas)): + print("beta_"+ str(i) + " :" + str(betas[i])) + elif nocons == True: + betas = betas_all[0:] + for i in range(0, len(betas)): + print("beta_"+ str(i) + " :" + str(betas[i])) + return betas_all diff --git a/Projects/project_2_packages/build/lib/iv_jett/iv_standard_error.py b/Projects/project_2_packages/build/lib/iv_jett/iv_standard_error.py new file mode 100644 index 0000000..381fb59 --- /dev/null +++ b/Projects/project_2_packages/build/lib/iv_jett/iv_standard_error.py @@ -0,0 +1,32 @@ +''' +Calculate Covariance Matrix +''' + +import numpy as np +from iv_jett.iv_init import projection_matrix + +def calculate_sigma(Z, X, Y, beta_iv, nocons = False): + + N = Z.shape[0] + + if nocons == False: + X_constant = np.ones((N, 1)) + X = np.hstack((X_constant, X)) + + resid = Y - X @ beta_iv + sigma_iv = (1/N) * np.transpose(resid) @ resid + return np.sqrt(sigma_iv) + +def calculate_var_beta(sigma, X, Z, nocons = False): + + N = Z.shape[0] + + if nocons == False: + X_constant = np.ones((N, 1)) + X = np.hstack((X_constant, X)) + Z_constant = np.ones((N, 1)) + Z = np.hstack((Z_constant, Z)) + + var_beta = (np.asscalar(sigma**2) * np.identity(X.shape[1])) @ np.linalg.inv(np.transpose(X) @ projection_matrix(Z) @ X) + se_beta = np.sqrt(np.diag(var_beta)) + return se_beta diff --git a/Projects/project_2_packages/build/lib/iv_jett/test/__init__.py b/Projects/project_2_packages/build/lib/iv_jett/test/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/Projects/project_2_packages/build/lib/iv_jett/test/test_estimates.py b/Projects/project_2_packages/build/lib/iv_jett/test/test_estimates.py new file mode 100644 index 0000000..2d5329e --- /dev/null +++ b/Projects/project_2_packages/build/lib/iv_jett/test/test_estimates.py @@ -0,0 +1,14 @@ +import unittest +import numpy as np +import iv_reg as iv + +class TestBetas(unittest.TestCase): + def test_square_instruments(self): + z = np.random.rand(5, 5) + x = np.random.rand(1, 20) + y = np.random.rand(1, 20) + betas = np.linalg.inv(np.transpose(z) @ x) @ np.transpose(z) @ y + self.assertEqual(betas, iv.estimate_beta_iv(x, z, y, nocons = True)) + +if __name__ == "__main__": + unittest.main() diff --git a/Projects/project_2_packages/data_test.py b/Projects/project_2_packages/data_test.py new file mode 100644 index 0000000..cf49f51 --- /dev/null +++ b/Projects/project_2_packages/data_test.py @@ -0,0 +1,30 @@ +import numpy as np +from iv_jett.run import * + +mat_x = np.transpose(np.matrix([ [4, .2, 1, 5, 1, 10, 20], + [.4, 2, 2, 2, 2, 11, 25], + [0, 0, .3, 1, 3, 12, 40]])) + +mat_z = np.transpose(np.matrix([[1, .5, 2, 3, 4, 13, 56], + [3, 0, .2, 3, 5, 14, 60], + [1, 0, .4, 3, 6, 15, 77]])) + +mat_y = np.transpose(np.array([[3, 5, 2, 1, 7, 16, 80]])) + + +''' +beta_iv_hat = estimate_beta_iv(mat_x, mat_z, mat_y) +#print(beta_iv_hat) + + +sigma = calculate_sigma(mat_z, mat_x, mat_y, beta_iv_hat) +print("sigma") +print(sigma) + +print("var beta") +var_beta = calculate_var_beta(sigma, mat_x, mat_z) +print(var_beta) +''' +ret = TwoStageLeastSquaresRegress(mat_x, mat_y, mat_z, nocons = False, verbose = True) +#print(ret['Beta IV']) +#print(ret['Standard Error']) diff --git a/Projects/project_2_packages/dist/iv_reg_dnu-0.0.1-py3-none-any.whl b/Projects/project_2_packages/dist/iv_reg_dnu-0.0.1-py3-none-any.whl new file mode 100644 index 0000000..d9cf109 Binary files /dev/null and b/Projects/project_2_packages/dist/iv_reg_dnu-0.0.1-py3-none-any.whl differ diff --git a/Projects/project_2_packages/iv_jett/__init__.py b/Projects/project_2_packages/iv_jett/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/Projects/project_2_packages/iv_jett/iv_init.py b/Projects/project_2_packages/iv_jett/iv_init.py new file mode 100644 index 0000000..a0048d3 --- /dev/null +++ b/Projects/project_2_packages/iv_jett/iv_init.py @@ -0,0 +1,62 @@ +''' + +Python Package to implement instrumental variables +Author: Group 2 NYU Pre docs +Date Created: December 6, 2019 + +''' +import numpy as np + + +def check_dim(a, b, c): + ''' + Check dimensions + ''' + try: + assert len(a.shape) == 2 & len(b.shape) == 2 & len(c.shape) == 2 + except: + raise Exception('Incorrect data dimension input') + + try: + assert a.shape[0] == b.shape[0] == c.shape[0] + except: + raise Exception('Number of observations not equal') + + try: + assert a.shape[1] <= b.shape[1] + except: + raise Exception('Model underidentified') + +def projection_matrix(b): + ''' + Inputs: + b (matrix) -- z + ''' + + P_b = b @ np.linalg.inv((np.transpose(b) @ b)) @ np.transpose(b) + return P_b + +def estimate_beta_iv(a, b, c, nocons = False, verbose = False): + ''' + Inputs: + a (matrix) -- x + b (matrix) -- z + c (matrix) -- y + ''' + if nocons != True and nocons != False: + raise Exception('nocons option misspecified') + + check_dim(a, b, c) + if nocons == False: + N = a.shape[0] + a_1 = np.ones((N,1)) + a = np.hstack((a_1,a)) + b_1 = np.ones((N,1)) + b = np.hstack((b_1, b)) + + proj = projection_matrix(b) + b_1 = np.transpose(a) @ proj @ a + b_2 = np.linalg.inv(b_1) + b_3 = np.transpose(a) @ proj @ c + betas_all = b_2 @ b_3 + return betas_all diff --git a/Projects/project_2_packages/iv_jett/iv_standard_error.py b/Projects/project_2_packages/iv_jett/iv_standard_error.py new file mode 100644 index 0000000..c52ecb4 --- /dev/null +++ b/Projects/project_2_packages/iv_jett/iv_standard_error.py @@ -0,0 +1,71 @@ +''' +Calculate Covariance Matrix +''' + +import numpy as np +from iv_jett.iv_init import projection_matrix + +def calculate_resid(Z, X, Y, beta_iv, nocons = False): + if nocons == False: + X_constant = np.ones((N, 1)) + X = np.hstack((X_constant, X)) + + resid = Y - X @ beta_iv + return resid + +def calculate_sigma(Z, X, Y, beta_iv, nocons = False): + ''' + Description: + Estimates the variance of the errors. + Inputs: + Z (matrix) -- Instrumental Variables + X (matrix) -- Endogenous Variables + Y (matrix) -- Outcome Variable + beta_iv -- IV results + nocons -- Option for constant (default False) + ''' + N = Z.shape[0] + if nocons == False: + X_constant = np.ones((N, 1)) + X = np.hstack((X_constant, X)) + + resid = Y - X @ beta_iv + + sigma_iv = (1/N) * np.transpose(resid) @ resid + return np.sqrt(sigma_iv) + +def calculate_var_beta(sigma, X, Z, resid, nocons = False, robust = False): + + ''' + Description: + Calculates the variance of beta, the IV estimator + Inputs: + sigma + Z (matrix) -- Instrumental Variables + X (matrix) -- Endogenous Variables + nocons -- Option for constant (default False) + Ouputs: + se_beta (array) -- Standard error + ''' + + N = Z.shape[0] + if nocons == False: + X_constant = np.ones((N, 1)) + X = np.hstack((X_constant, X)) + Z_constant = np.ones((N, 1)) + Z = np.hstack((Z_constant, Z)) + + if robust == False: + var_beta = (np.asscalar(sigma**2) * np.identity(X.shape[1])) @ np.linalg.inv(np.transpose(X) @ projection_matrix(Z) @ X) + se_beta = np.sqrt(np.diag(var_beta)) + + if robust == True: + resid_sq = resid @ np.transpose(resid) + print("resid sq:") + print(resid_sq) + sandwich_bread = np.linalg.inv(np.transpose(Z) @ X) + var_beta = (sandwich_bread @ np.transpose(Z) @ np.diag(np.diag(resid_sq)) @ Z @ sandwich_bread) + print("var_beta") + print(var_beta) + se_beta = np.sqrt(np.diag(var_beta)) + return se_beta diff --git a/Projects/project_2_packages/iv_jett/print.py b/Projects/project_2_packages/iv_jett/print.py new file mode 100644 index 0000000..a5bcb00 --- /dev/null +++ b/Projects/project_2_packages/iv_jett/print.py @@ -0,0 +1,42 @@ +''' +Print Option +''' +class color: + PURPLE = '\033[95m' + CYAN = '\033[96m' + DARKCYAN = '\033[36m' + BLUE = '\033[94m' + GREEN = '\033[92m' + YELLOW = '\033[93m' + RED = '\033[91m' + BOLD = '\033[1m' + UNDERLINE = '\033[4m' + END = '\033[0m' + +def print_res(result_dict, nocons = False): + #print("\n\033[4m\tResults\t\t\033[0m\n \033[4m\t\t\t\033[0m \n ") + print( "\n" + color.UNDERLINE + color.BOLD + color.DARKCYAN + \ + "\tResults\t\t\n" + color.END) + SUB = str.maketrans("0123456789", "₀₁₂₃₄₅₆₇₈₉") + if nocons == False: + cons = result_dict['Beta IV'][0] + cons_se = result_dict['Standard Error'][0] + betas = result_dict['Beta IV'][1:] + ses = result_dict['Standard Error'][1:] + print("Cons:\t " + str(round(float(cons), 4))) + print("\t(" + str(round(cons_se, 5)) + ")\t") + print("------------------------") + for i in range(0, len(betas)): + print("\u03B2"+ str(i).translate(SUB) + " : " + \ + str(round(float(betas[i]), 4))) + print("\t(" + str(round(float(ses[i]), 5)) + ")\t") + print("------------------------") + elif nocons: + betas = result_dict['Beta IV'][0:] + ses = result_dict['Standard Error'][0:] + for i in range(0, len(betas)): + print("\u03B2"+ str(i).translate(SUB) + " : " + \ + str(round(float(betas[i]), 4))) + print("\t(" + str(round(float(ses[i]), 5)) + ")\t") + print("------------------------") + print("\n") diff --git a/Projects/project_2_packages/iv_jett/run.py b/Projects/project_2_packages/iv_jett/run.py new file mode 100644 index 0000000..381aaaf --- /dev/null +++ b/Projects/project_2_packages/iv_jett/run.py @@ -0,0 +1,18 @@ +''' +Run Package +''' + +from iv_jett.iv_standard_error import * +from iv_jett.iv_init import * +from iv_jett.print import* + +def TwoStageLeastSquaresRegress(X, Y, Z, nocons = False, verbose = False): + beta_iv_hat = estimate_beta_iv(X, Z, Y, nocons) + resid = calculate_resid(Z, X, Y, beta_iv_hat, nocons) + sigma = calculate_sigma(Z, X, Y, beta_iv_hat, nocons) + var_beta = calculate_var_beta(sigma, X, Z, resid, nocons) + result_dict = {'Beta IV' : beta_iv_hat, + 'Standard Error': var_beta} + if verbose: + print_res(result_dict, nocons) + return result_dict diff --git a/Projects/project_2_packages/iv_jett/test/__init__.py b/Projects/project_2_packages/iv_jett/test/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/Projects/project_2_packages/iv_jett/test/test_estimates.py b/Projects/project_2_packages/iv_jett/test/test_estimates.py new file mode 100644 index 0000000..a781005 --- /dev/null +++ b/Projects/project_2_packages/iv_jett/test/test_estimates.py @@ -0,0 +1,27 @@ +import unittest +import numpy as np +from iv_jett import iv_init + +class TestBetas(unittest.TestCase): + def test_square_instruments(self): + z = np.random.rand(255, 5) + x = np.random.rand(255, 5) + y = np.random.rand(255, 5) + + betas = np.linalg.inv(np.transpose(z) @ x) @ np.transpose(z) @ y + x2 = iv_init.estimate_beta_iv(x, z, y, nocons = True) + + self.assertIsNone(np.testing.assert_allclose(betas, x2)) + + def test_large_data(self): + z = np.random.rand(10^8, 2) + x = np.random.rand(10^8, 2) + y = np.random.rand(10^8, 2) + + betas = np.linalg.inv(np.transpose(z) @ x) @ np.transpose(z) @ y + x2 = iv_init.estimate_beta_iv(x, z, y, nocons = True) + + self.assertIsNone(np.testing.assert_allclose(betas, x2)) + +if __name__ == "__main__": + unittest.main() diff --git a/Projects/project_2_packages/iv_reg_dnu.egg-info/PKG-INFO b/Projects/project_2_packages/iv_reg_dnu.egg-info/PKG-INFO new file mode 100644 index 0000000..39f5b71 --- /dev/null +++ b/Projects/project_2_packages/iv_reg_dnu.egg-info/PKG-INFO @@ -0,0 +1,14 @@ +Metadata-Version: 2.1 +Name: iv-reg-dnu +Version: 0.0.1 +Summary: Package for Instrumental Variable Estimation +Home-page: https://github.com/jettpettus/modularizationandtesting +Author: Best Group 2 +License: UNKNOWN +Description: # iv-reg package + + This is a simple package to perform instrumental variable estimation. + +Platform: UNKNOWN +Requires-Python: >=3.6 +Description-Content-Type: text/markdown diff --git a/Projects/project_2_packages/iv_reg_dnu.egg-info/SOURCES.txt b/Projects/project_2_packages/iv_reg_dnu.egg-info/SOURCES.txt new file mode 100644 index 0000000..8870933 --- /dev/null +++ b/Projects/project_2_packages/iv_reg_dnu.egg-info/SOURCES.txt @@ -0,0 +1,10 @@ +setup.py +iv_jett/__init__.py +iv_jett/iv_init.py +iv_jett/iv_standard_error.py +iv_jett/test/__init__.py +iv_jett/test/test_estimates.py +iv_reg_dnu.egg-info/PKG-INFO +iv_reg_dnu.egg-info/SOURCES.txt +iv_reg_dnu.egg-info/dependency_links.txt +iv_reg_dnu.egg-info/top_level.txt \ No newline at end of file diff --git a/Projects/project_2_packages/iv_reg_dnu.egg-info/dependency_links.txt b/Projects/project_2_packages/iv_reg_dnu.egg-info/dependency_links.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/Projects/project_2_packages/iv_reg_dnu.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/Projects/project_2_packages/iv_reg_dnu.egg-info/top_level.txt b/Projects/project_2_packages/iv_reg_dnu.egg-info/top_level.txt new file mode 100644 index 0000000..a5d75b1 --- /dev/null +++ b/Projects/project_2_packages/iv_reg_dnu.egg-info/top_level.txt @@ -0,0 +1 @@ +iv_jett diff --git a/Projects/project_2_packages/logit/main.py b/Projects/project_2_packages/logit/main.py new file mode 100644 index 0000000..6f16225 --- /dev/null +++ b/Projects/project_2_packages/logit/main.py @@ -0,0 +1,31 @@ +import numpy as np +import math +from scipy.optimize import minimize + + +def ll_function (x, y, beta): + # Reshape beta + beta = beta[:, None] + beta_prime = np.transpose(beta) + fun_1 = y @ beta_prime @ x + fun_2 = math.log(1 + math.exp(beta_prime @ x)) + fun = np.subtract(fun_1, fun_2) + fun = fun.sum() + return fun + + +def fit_logit(x, y): + beta_init = np.random.rand(len(x), 1) + min_func = (lambda beta: ll_function(x, y, beta)) + res = minimize(min_func, x0 = beta_init) + return res + + +if __name__ == "__main__": + x = np.transpose(np.matrix([0, 1, 3, 0.5, 3, -1, 2])) + y = np.transpose(np.matrix([9, 4, 23, 4, 4, -2, 1])) + + print(fit_logit(x, y)) + + + diff --git a/Projects/project_2_packages/requirements.txt b/Projects/project_2_packages/requirements.txt new file mode 100644 index 0000000..2a09ceb --- /dev/null +++ b/Projects/project_2_packages/requirements.txt @@ -0,0 +1,2 @@ +numpy==1.15.4 +scipy==1.2.1 diff --git a/Projects/project_2_packages/setup.py b/Projects/project_2_packages/setup.py new file mode 100644 index 0000000..6ebe60e --- /dev/null +++ b/Projects/project_2_packages/setup.py @@ -0,0 +1,16 @@ +import setuptools + +with open("README.md", "r") as fh: + long_description = fh.read() + +setuptools.setup( + name="iv_reg_dnu", # Replace with your own username + version="0.0.1", + author="Best Group 2", + description="Package for Instrumental Variable Estimation", + long_description=long_description, + long_description_content_type="text/markdown", + url="https://github.com/jettpettus/modularizationandtesting", + packages=setuptools.find_packages(), + python_requires='>=3.6', +) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..2a09ceb --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +numpy==1.15.4 +scipy==1.2.1