├── .coveragerc ├── .github └── workflows │ └── tests.yml ├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── data └── titanic.csv ├── mypy.ini ├── poetry.lock ├── pylintrc ├── pyproject.toml ├── src ├── __init__.py ├── data_prep │ ├── __init__.py │ ├── categorical.py │ ├── continuous.py │ └── prep_titanic.py ├── tree │ ├── __init__.py │ ├── decision_tree.py │ └── random_forest.py └── utils │ ├── __init__.py │ ├── logger.py │ └── timer.py ├── testing-ml-flow.png └── tests ├── __init__.py ├── data_prep ├── __init__.py ├── test_categorical.py ├── test_continuous.py └── test_prep_titanic.py └── tree ├── __init__.py ├── fixtures.py ├── test_decision_tree_1pre.py ├── test_decision_tree_2post.py ├── test_decision_tree_3eval.py ├── test_random_forest_1pre.py ├── test_random_forest_2post.py └── test_random_forest_3eval.py /.coveragerc: -------------------------------------------------------------------------------- 1 | [report] 2 | omit=src/utils/* 3 | fail_under=100 4 | show_missing=True 5 | 6 | [xml] 7 | output=coverage.xml -------------------------------------------------------------------------------- /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | # .github/workflows/tests.yml 2 | name: Tests 3 | on: push 4 | jobs: 5 | tests: 6 | runs-on: ubuntu-latest 7 | steps: 8 | - uses: actions/checkout@v2 9 | - uses: actions/setup-python@v1 10 | with: 11 | python-version: 3.8 12 | architecture: x64 13 | - run: make setup 14 | - run: make check 15 | - run: bash <(curl -s https://codecov.io/bash) -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .idea/ 3 | .ipynb_checkpoints/ 4 | notebooks/ 5 | readme.txt 6 | *.pyc 7 | .coverage 8 | coverage.xml -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Eugene Yan Ziyou 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | setup: 2 | pip install poetry 3 | poetry install 4 | 5 | clean-pyc: 6 | find . -name '*.pyc' -exec rm -f {} + 7 | find . -name '*.pyo' -exec rm -f {} + 8 | find . -name '*~' -exec rm -f {} + 9 | find . -name '__pycache__' -exec rm -fr {} + 10 | 11 | clean-test: 12 | rm -f .coverage 13 | rm -f coverage.* 14 | 15 | clean: clean-pyc clean-test 16 | 17 | test: clean 18 | poetry run py.test tests --cov-config=.coveragerc --cov=src --cov-report xml 19 | 20 | mypy: 21 | poetry run mypy src 22 | 23 | lint: 24 | poetry run pylint src -j 4 --reports=y 25 | 26 | check: test lint mypy -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # testing-ml 2 | 3 | ![Tests](https://github.com/eugeneyan/testing-ml/workflows/Tests/badge.svg?branch=master) [![codecov](https://codecov.io/gh/eugeneyan/testing-ml/branch/master/graph/badge.svg)](https://codecov.io/gh/eugeneyan/testing-ml) [![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://github.com/eugeneyan/testing-ml/pulls) 4 | 5 | How to test machine learning code. In this example, we'll test a `numpy` implementation of `DecisionTree` and `RandomForest` via: 6 | - [Pre-train tests](#pre-train-tests-to-ensure-correct-implementation) to ensure correct implementation 7 | - [Post-train tests](#post-train-tests-to-ensure-expected-learned-behaviour) to ensure expected learned behaviour 8 | - [Evaluation](#evaluation-to-ensure-satisfactory-model-performance) to ensure satisfactory model performance 9 | 10 | ![](https://raw.githubusercontent.com/eugeneyan/testing-ml/master/testing-ml-flow.png) 11 | 12 | Accompanying article: [How to Test Machine Learning Code and Systems](https://eugeneyan.com/writing/testing-ml/). Inspired by [@jeremyjordan](https://twitter.com/jeremyjordan)'s [Effective Testing for Machine Learning Systems](https://www.jeremyjordan.me/testing-ml/). 13 | 14 | ## Quick Start 15 | ``` 16 | # Clone and setup environment 17 | git clone https://github.com/eugeneyan/testing-ml.git 18 | cd testing-ml 19 | make setup 20 | 21 | # Run test suite 22 | make check 23 | ``` 24 | 25 | ## Standard software habits 26 | - Unit test [fixture reuse](https://github.com/eugeneyan/testing-ml/blob/master/tests/tree/fixtures.py), [exceptions testing](https://github.com/eugeneyan/testing-ml/blob/master/tests/data_prep/test_continuous.py#L44) with [`pytest`](https://docs.pytest.org/en/latest/) 27 | - [Code coverage](https://github.com/eugeneyan/testing-ml/blob/master/Makefile#L17) with [`Coverage.py`](https://coverage.readthedocs.io/en/coverage-5.2.1/) and [`pytest-cov`](https://pytest-cov.readthedocs.io/en/latest/) 28 | - [Linting](https://github.com/eugeneyan/testing-ml/blob/master/Makefile#L23) to ensure code consistency with [`pylint`](https://www.pylint.org) 29 | - [Type checks](https://github.com/eugeneyan/testing-ml/blob/master/Makefile#L20) to verify type correctness with [`mypy`](http://mypy-lang.org) 30 | 31 | More details here: [How to Set Up a Python Project For Automation and Collaboration](https://eugeneyan.com/writing/setting-up-python-project-for-automation-and-collaboration/) ([GitHub repo](https://github.com/eugeneyan/python-collab-template)) 32 | 33 | 34 | ## Pre-train tests to ensure correct implementation 35 | 36 | - Test implementation of [Gini impurity](https://github.com/eugeneyan/testing-ml/blob/master/tests/tree/test_decision_tree_1pre.py#L8) and [gain](https://github.com/eugeneyan/testing-ml/blob/master/tests/tree/test_decision_tree_1pre.py#L17) 37 | 38 | ``` 39 | def test_gini_impurity(): 40 | assert round(gini_impurity([1, 1, 1, 1, 1, 1, 1, 1]), 3) == 0 41 | assert round(gini_impurity([1, 1, 1, 1, 1, 1, 0, 0]), 3) == 0.375 42 | assert round(gini_impurity([1, 1, 1, 1, 0, 0, 0, 0]), 3) == 0.500 43 | 44 | 45 | def test_gini_gain(): 46 | assert round(gini_gain([1, 1, 1, 1, 0, 0, 0, 0], [[1, 1, 1, 1], [0, 0, 0, 0]]), 3) == 0.5 47 | assert round(gini_gain([1, 1, 1, 1, 0, 0, 0, 0], [[1, 1, 1, 0], [0, 0, 0, 1]]), 3) == 0.125 48 | assert round(gini_gain([1, 1, 1, 1, 0, 0, 0, 0], [[1, 1, 0, 0], [0, 0, 1, 1]]), 3) == 0.0 49 | ``` 50 | 51 | - Test [output shape](https://github.com/eugeneyan/testing-ml/blob/master/tests/tree/test_decision_tree_1pre.py#L25) 52 | 53 | ``` 54 | def test_dt_output_shape(dummy_titanic): 55 | X_train, y_train, X_test, y_test = dummy_titanic 56 | dt = DecisionTree() 57 | dt.fit(X_train, y_train) 58 | pred_train, pred_test = dt.predict(X_train), dt.predict(X_test) 59 | 60 | assert pred_train.shape == (X_train.shape[0],), 'DecisionTree output should be same as training labels.' 61 | assert pred_test.shape == (X_test.shape[0],), 'DecisionTree output should be same as testing labels.' 62 | ``` 63 | 64 | - Test [data leak](https://github.com/eugeneyan/testing-ml/blob/master/tests/tree/test_decision_tree_1pre.py#103) between train and test set 65 | 66 | ``` 67 | def test_data_leak_in_test_data(dummy_titanic_df): 68 | train, test = dummy_titanic_df 69 | 70 | concat_df = pd.concat([train, test]) 71 | concat_df.drop_duplicates(inplace=True) 72 | 73 | assert concat_df.shape[0] == train.shape[0] + test.shape[0] 74 | ``` 75 | 76 | - Test [output range](https://github.com/eugeneyan/testing-ml/blob/master/tests/tree/test_decision_tree_1pre.py#L44) 77 | 78 | ``` 79 | def test_dt_output_range(dummy_titanic): 80 | X_train, y_train, X_test, y_test = dummy_titanic 81 | dt = DecisionTree() 82 | dt.fit(X_train, y_train) 83 | pred_train, pred_test = dt.predict(X_train), dt.predict(X_test) 84 | 85 | assert (pred_train <= 1).all() & (pred_train >= 0).all(), 'Decision tree output should range from 0 to 1 inclusive' 86 | assert (pred_test <= 1).all() & (pred_test >= 0).all(), 'Decision tree output should range from 0 to 1 inclusive' 87 | ``` 88 | 89 | - Test model able to [overfit on perfectly separable data](https://github.com/eugeneyan/testing-ml/blob/master/tests/tree/test_decision_tree_1pre.py#L63) 90 | 91 | ``` 92 | def test_dt_overfit(dummy_feats_and_labels): 93 | feats, labels = dummy_feats_and_labels 94 | dt = DecisionTree() 95 | dt.fit(feats, labels) 96 | pred = np.round(dt.predict(feats)) 97 | 98 | assert np.array_equal(labels, pred), 'DecisionTree should fit data perfectly and prediction should == labels.' 99 | ``` 100 | 101 | - Test additional tree depth [increases training accuracy and AUC ROC](https://github.com/eugeneyan/testing-ml/blob/master/tests/tree/test_decision_tree_1pre.py#L85) 102 | 103 | ``` 104 | def test_dt_increase_acc(dummy_titanic): 105 | X_train, y_train, _, _ = dummy_titanic 106 | 107 | acc_list, auc_list = [], [] 108 | for depth in range(1, 10): 109 | dt = DecisionTree(depth_limit=depth) 110 | dt.fit(X_train, y_train) 111 | pred = dt.predict(X_train) 112 | pred_binary = np.round(pred) 113 | acc_list.append(accuracy_score(y_train, pred_binary)) 114 | auc_list.append(roc_auc_score(y_train, pred)) 115 | 116 | assert sorted(acc_list) == acc_list, 'Accuracy should increase as tree depth increases.' 117 | assert sorted(auc_list) == auc_list, 'AUC ROC should increase as tree depth increases.' 118 | ``` 119 | 120 | - Test additional trees in `RandomForest` [improves validation accuracy and AUC ROC](https://github.com/eugeneyan/testing-ml/blob/master/tests/tree/test_random_forest_1pre.py#L18) 121 | 122 | ``` 123 | def test_dt_increase_acc(dummy_titanic): 124 | X_train, y_train, X_test, y_test = dummy_titanic 125 | 126 | acc_list, auc_list = [], [] 127 | for num_trees in [1, 3, 7, 15]: 128 | rf = RandomForest(num_trees=num_trees, depth_limit=7, col_subsampling=0.7, row_subsampling=0.7) 129 | rf.fit(X_train, y_train) 130 | pred = rf.predict(X_test) 131 | pred_binary = np.round(pred) 132 | acc_list.append(accuracy_score(y_test, pred_binary)) 133 | auc_list.append(roc_auc_score(y_test, pred)) 134 | 135 | assert sorted(acc_list) == acc_list, 'Accuracy should increase as number of trees increases.' 136 | assert sorted(auc_list) == auc_list, 'AUC ROC should increase as number of trees increases.' 137 | ``` 138 | 139 | - Test `RandomForest` [outperforms](https://github.com/eugeneyan/testing-ml/blob/master/tests/tree/test_random_forest_1pre.py#L36) `DecisionTree` given the same tree depth 140 | 141 | ``` 142 | def test_rf_better_than_dt(dummy_titanic): 143 | X_train, y_train, X_test, y_test = dummy_titanic 144 | 145 | dt = DecisionTree(depth_limit=10) 146 | dt.fit(X_train, y_train) 147 | 148 | rf = RandomForest(depth_limit=10, num_trees=7, col_subsampling=0.8, row_subsampling=0.8) 149 | rf.fit(X_train, y_train) 150 | 151 | pred_test_dt = dt.predict(X_test) 152 | pred_test_binary_dt = np.round(pred_test_dt) 153 | acc_test_dt = accuracy_score(y_test, pred_test_binary_dt) 154 | auc_test_dt = roc_auc_score(y_test, pred_test_dt) 155 | 156 | pred_test_rf = rf.predict(X_test) 157 | pred_test_binary_rf = np.round(pred_test_rf) 158 | acc_test_rf = accuracy_score(y_test, pred_test_binary_rf) 159 | auc_test_rf = roc_auc_score(y_test, pred_test_rf) 160 | 161 | assert acc_test_rf > acc_test_dt, 'RandomForest should have higher accuracy than DecisionTree on test set.' 162 | assert auc_test_rf > auc_test_dt, 'RandomForest should have higher AUC ROC than DecisionTree on test set.' 163 | ``` 164 | 165 | ## Post-train tests to ensure expected learned behaviour 166 | - Test [invariance](https://github.com/eugeneyan/testing-ml/blob/master/tests/tree/test_decision_tree_2post.py#L8) (e.g., ticket number should not affect survival probability) 167 | 168 | ``` 169 | def test_dt_invariance(dummy_titanic_dt, dummy_passengers): 170 | model = dummy_titanic_dt 171 | _, p2 = dummy_passengers 172 | 173 | # Get original survival probability of passenger 2 174 | test_df = pd.DataFrame.from_dict([p2], orient='columns') 175 | X, y = get_feats_and_labels(prep_df(test_df)) 176 | p2_prob = model.predict(X)[0] # 1.0 177 | 178 | # Change ticket number from 'PC 17599' to 'A/5 21171' 179 | p2_ticket = p2.copy() 180 | p2_ticket['ticket'] = 'A/5 21171' 181 | test_df = pd.DataFrame.from_dict([p2_ticket], orient='columns') 182 | X, y = get_feats_and_labels(prep_df(test_df)) 183 | p2_ticket_prob = model.predict(X)[0] # 1.0 184 | 185 | assert p2_prob == p2_ticket_prob 186 | ``` 187 | 188 | - Test [directional expectation](https://github.com/eugeneyan/testing-ml/blob/master/tests/tree/test_decision_tree_2post.py#L69) (e.g., females should have higher survival probability than males) 189 | 190 | ``` 191 | def test_dt_directional_expectation(dummy_titanic_dt, dummy_passengers): 192 | model = dummy_titanic_dt 193 | _, p2 = dummy_passengers 194 | 195 | # Get original survival probability of passenger 2 196 | test_df = pd.DataFrame.from_dict([p2], orient='columns') 197 | X, y = get_feats_and_labels(prep_df(test_df)) 198 | p2_prob = model.predict(X)[0] # 1.0 199 | 200 | # Change gender from female to male 201 | p2_male = p2.copy() 202 | p2_male['Name'] = ' Mr. John' 203 | p2_male['Sex'] = 'male' 204 | test_df = pd.DataFrame.from_dict([p2_male], orient='columns') 205 | X, y = get_feats_and_labels(prep_df(test_df)) 206 | p2_male_prob = model.predict(X)[0] # 0.56 207 | 208 | # Change class from 1 to 3 209 | p2_class = p2.copy() 210 | p2_class['Pclass'] = 3 211 | test_df = pd.DataFrame.from_dict([p2_class], orient='columns') 212 | X, y = get_feats_and_labels(prep_df(test_df)) 213 | p2_class_prob = model.predict(X)[0] # 0.0 214 | 215 | assert p2_prob > p2_male_prob, 'Changing gender from female to male should decrease survival probability.' 216 | assert p2_prob > p2_class_prob, 'Changing class from 1 to 3 should decrease survival probability.' 217 | ``` 218 | 219 | ## Evaluation to ensure satisfactory model performance 220 | 221 | - Evaluation on [accuracy and AUC ROC](https://github.com/eugeneyan/testing-ml/blob/master/tests/tree/test_decision_tree_3eval.py#L10) 222 | 223 | ``` 224 | def test_dt_evaluation(dummy_titanic_dt, dummy_titanic): 225 | model = dummy_titanic_dt 226 | X_train, y_train, X_test, y_test = dummy_titanic 227 | pred_test = model.predict(X_test) 228 | pred_test_binary = np.round(pred_test) 229 | acc_test = accuracy_score(y_test, pred_test_binary) 230 | auc_test = roc_auc_score(y_test, pred_test) 231 | 232 | assert acc_test > 0.82, 'Accuracy on test should be > 0.82' 233 | assert auc_test > 0.84, 'AUC ROC on test should be > 0.84' 234 | ``` 235 | 236 | - Evaluation on [training](https://github.com/eugeneyan/testing-ml/blob/master/tests/tree/test_decision_tree_3eval.py#L31) and [inference](https://github.com/eugeneyan/testing-ml/blob/master/tests/tree/test_decision_tree_3eval.py#L41) times 237 | 238 | ``` 239 | def test_dt_training_time(dummy_titanic): 240 | X_train, y_train, X_test, y_test = dummy_titanic 241 | 242 | # Standardize to use depth = 10 243 | dt = DecisionTree(depth_limit=10) 244 | latency_array = np.array([train_with_time(dt, X_train, y_train)[1] for i in range(100)]) 245 | time_p95 = np.quantile(latency_array, 0.95) 246 | assert time_p95 < 1.0, 'Training time at 95th percentile should be < 1.0 sec' 247 | 248 | 249 | def test_dt_serving_latency(dummy_titanic): 250 | X_train, y_train, X_test, y_test = dummy_titanic 251 | 252 | # Standardize to use depth = 10 253 | dt = DecisionTree(depth_limit=10) 254 | dt.fit(X_train, y_train) 255 | 256 | latency_array = np.array([predict_with_time(dt, X_test)[1] for i in range(500)]) 257 | latency_p99 = np.quantile(latency_array, 0.99) 258 | assert latency_p99 < 0.004, 'Serving latency at 99th percentile should be < 0.004 sec' 259 | ``` 260 | -------------------------------------------------------------------------------- /data/titanic.csv: -------------------------------------------------------------------------------- 1 | PassengerId,Survived,Pclass,Name,Sex,Age,SibSp,Parch,Ticket,Fare,Cabin,Embarked 2 | 1,0,3,"Braund, Mr. Owen Harris",male,22,1,0,A/5 21171,7.25,,S 3 | 2,1,1,"Cumings, Mrs. John Bradley (Florence Briggs Thayer)",female,38,1,0,PC 17599,71.2833,C85,C 4 | 3,1,3,"Heikkinen, Miss. Laina",female,26,0,0,STON/O2. 3101282,7.925,,S 5 | 4,1,1,"Futrelle, Mrs. Jacques Heath (Lily May Peel)",female,35,1,0,113803,53.1,C123,S 6 | 5,0,3,"Allen, Mr. William Henry",male,35,0,0,373450,8.05,,S 7 | 6,0,3,"Moran, Mr. James",male,,0,0,330877,8.4583,,Q 8 | 7,0,1,"McCarthy, Mr. Timothy J",male,54,0,0,17463,51.8625,E46,S 9 | 8,0,3,"Palsson, Master. Gosta Leonard",male,2,3,1,349909,21.075,,S 10 | 9,1,3,"Johnson, Mrs. Oscar W (Elisabeth Vilhelmina Berg)",female,27,0,2,347742,11.1333,,S 11 | 10,1,2,"Nasser, Mrs. Nicholas (Adele Achem)",female,14,1,0,237736,30.0708,,C 12 | 11,1,3,"Sandstrom, Miss. Marguerite Rut",female,4,1,1,PP 9549,16.7,G6,S 13 | 12,1,1,"Bonnell, Miss. Elizabeth",female,58,0,0,113783,26.55,C103,S 14 | 13,0,3,"Saundercock, Mr. William Henry",male,20,0,0,A/5. 2151,8.05,,S 15 | 14,0,3,"Andersson, Mr. Anders Johan",male,39,1,5,347082,31.275,,S 16 | 15,0,3,"Vestrom, Miss. Hulda Amanda Adolfina",female,14,0,0,350406,7.8542,,S 17 | 16,1,2,"Hewlett, Mrs. (Mary D Kingcome) ",female,55,0,0,248706,16,,S 18 | 17,0,3,"Rice, Master. Eugene",male,2,4,1,382652,29.125,,Q 19 | 18,1,2,"Williams, Mr. Charles Eugene",male,,0,0,244373,13,,S 20 | 19,0,3,"Vander Planke, Mrs. Julius (Emelia Maria Vandemoortele)",female,31,1,0,345763,18,,S 21 | 20,1,3,"Masselmani, Mrs. Fatima",female,,0,0,2649,7.225,,C 22 | 21,0,2,"Fynney, Mr. Joseph J",male,35,0,0,239865,26,,S 23 | 22,1,2,"Beesley, Mr. Lawrence",male,34,0,0,248698,13,D56,S 24 | 23,1,3,"McGowan, Miss. Anna ""Annie""",female,15,0,0,330923,8.0292,,Q 25 | 24,1,1,"Sloper, Mr. William Thompson",male,28,0,0,113788,35.5,A6,S 26 | 25,0,3,"Palsson, Miss. Torborg Danira",female,8,3,1,349909,21.075,,S 27 | 26,1,3,"Asplund, Mrs. Carl Oscar (Selma Augusta Emilia Johansson)",female,38,1,5,347077,31.3875,,S 28 | 27,0,3,"Emir, Mr. Farred Chehab",male,,0,0,2631,7.225,,C 29 | 28,0,1,"Fortune, Mr. Charles Alexander",male,19,3,2,19950,263,C23 C25 C27,S 30 | 29,1,3,"O'Dwyer, Miss. Ellen ""Nellie""",female,,0,0,330959,7.8792,,Q 31 | 30,0,3,"Todoroff, Mr. Lalio",male,,0,0,349216,7.8958,,S 32 | 31,0,1,"Uruchurtu, Don. Manuel E",male,40,0,0,PC 17601,27.7208,,C 33 | 32,1,1,"Spencer, Mrs. William Augustus (Marie Eugenie)",female,,1,0,PC 17569,146.5208,B78,C 34 | 33,1,3,"Glynn, Miss. Mary Agatha",female,,0,0,335677,7.75,,Q 35 | 34,0,2,"Wheadon, Mr. Edward H",male,66,0,0,C.A. 24579,10.5,,S 36 | 35,0,1,"Meyer, Mr. Edgar Joseph",male,28,1,0,PC 17604,82.1708,,C 37 | 36,0,1,"Holverson, Mr. Alexander Oskar",male,42,1,0,113789,52,,S 38 | 37,1,3,"Mamee, Mr. Hanna",male,,0,0,2677,7.2292,,C 39 | 38,0,3,"Cann, Mr. Ernest Charles",male,21,0,0,A./5. 2152,8.05,,S 40 | 39,0,3,"Vander Planke, Miss. Augusta Maria",female,18,2,0,345764,18,,S 41 | 40,1,3,"Nicola-Yarred, Miss. Jamila",female,14,1,0,2651,11.2417,,C 42 | 41,0,3,"Ahlin, Mrs. Johan (Johanna Persdotter Larsson)",female,40,1,0,7546,9.475,,S 43 | 42,0,2,"Turpin, Mrs. William John Robert (Dorothy Ann Wonnacott)",female,27,1,0,11668,21,,S 44 | 43,0,3,"Kraeff, Mr. Theodor",male,,0,0,349253,7.8958,,C 45 | 44,1,2,"Laroche, Miss. Simonne Marie Anne Andree",female,3,1,2,SC/Paris 2123,41.5792,,C 46 | 45,1,3,"Devaney, Miss. Margaret Delia",female,19,0,0,330958,7.8792,,Q 47 | 46,0,3,"Rogers, Mr. William John",male,,0,0,S.C./A.4. 23567,8.05,,S 48 | 47,0,3,"Lennon, Mr. Denis",male,,1,0,370371,15.5,,Q 49 | 48,1,3,"O'Driscoll, Miss. Bridget",female,,0,0,14311,7.75,,Q 50 | 49,0,3,"Samaan, Mr. Youssef",male,,2,0,2662,21.6792,,C 51 | 50,0,3,"Arnold-Franchi, Mrs. Josef (Josefine Franchi)",female,18,1,0,349237,17.8,,S 52 | 51,0,3,"Panula, Master. Juha Niilo",male,7,4,1,3101295,39.6875,,S 53 | 52,0,3,"Nosworthy, Mr. Richard Cater",male,21,0,0,A/4. 39886,7.8,,S 54 | 53,1,1,"Harper, Mrs. Henry Sleeper (Myna Haxtun)",female,49,1,0,PC 17572,76.7292,D33,C 55 | 54,1,2,"Faunthorpe, Mrs. Lizzie (Elizabeth Anne Wilkinson)",female,29,1,0,2926,26,,S 56 | 55,0,1,"Ostby, Mr. Engelhart Cornelius",male,65,0,1,113509,61.9792,B30,C 57 | 56,1,1,"Woolner, Mr. Hugh",male,,0,0,19947,35.5,C52,S 58 | 57,1,2,"Rugg, Miss. Emily",female,21,0,0,C.A. 31026,10.5,,S 59 | 58,0,3,"Novel, Mr. Mansouer",male,28.5,0,0,2697,7.2292,,C 60 | 59,1,2,"West, Miss. Constance Mirium",female,5,1,2,C.A. 34651,27.75,,S 61 | 60,0,3,"Goodwin, Master. William Frederick",male,11,5,2,CA 2144,46.9,,S 62 | 61,0,3,"Sirayanian, Mr. Orsen",male,22,0,0,2669,7.2292,,C 63 | 62,1,1,"Icard, Miss. Amelie",female,38,0,0,113572,80,B28, 64 | 63,0,1,"Harris, Mr. Henry Birkhardt",male,45,1,0,36973,83.475,C83,S 65 | 64,0,3,"Skoog, Master. Harald",male,4,3,2,347088,27.9,,S 66 | 65,0,1,"Stewart, Mr. Albert A",male,,0,0,PC 17605,27.7208,,C 67 | 66,1,3,"Moubarek, Master. Gerios",male,,1,1,2661,15.2458,,C 68 | 67,1,2,"Nye, Mrs. (Elizabeth Ramell)",female,29,0,0,C.A. 29395,10.5,F33,S 69 | 68,0,3,"Crease, Mr. Ernest James",male,19,0,0,S.P. 3464,8.1583,,S 70 | 69,1,3,"Andersson, Miss. Erna Alexandra",female,17,4,2,3101281,7.925,,S 71 | 70,0,3,"Kink, Mr. Vincenz",male,26,2,0,315151,8.6625,,S 72 | 71,0,2,"Jenkin, Mr. Stephen Curnow",male,32,0,0,C.A. 33111,10.5,,S 73 | 72,0,3,"Goodwin, Miss. Lillian Amy",female,16,5,2,CA 2144,46.9,,S 74 | 73,0,2,"Hood, Mr. Ambrose Jr",male,21,0,0,S.O.C. 14879,73.5,,S 75 | 74,0,3,"Chronopoulos, Mr. Apostolos",male,26,1,0,2680,14.4542,,C 76 | 75,1,3,"Bing, Mr. Lee",male,32,0,0,1601,56.4958,,S 77 | 76,0,3,"Moen, Mr. Sigurd Hansen",male,25,0,0,348123,7.65,F G73,S 78 | 77,0,3,"Staneff, Mr. Ivan",male,,0,0,349208,7.8958,,S 79 | 78,0,3,"Moutal, Mr. Rahamin Haim",male,,0,0,374746,8.05,,S 80 | 79,1,2,"Caldwell, Master. Alden Gates",male,0.83,0,2,248738,29,,S 81 | 80,1,3,"Dowdell, Miss. Elizabeth",female,30,0,0,364516,12.475,,S 82 | 81,0,3,"Waelens, Mr. Achille",male,22,0,0,345767,9,,S 83 | 82,1,3,"Sheerlinck, Mr. Jan Baptist",male,29,0,0,345779,9.5,,S 84 | 83,1,3,"McDermott, Miss. Brigdet Delia",female,,0,0,330932,7.7875,,Q 85 | 84,0,1,"Carrau, Mr. Francisco M",male,28,0,0,113059,47.1,,S 86 | 85,1,2,"Ilett, Miss. Bertha",female,17,0,0,SO/C 14885,10.5,,S 87 | 86,1,3,"Backstrom, Mrs. Karl Alfred (Maria Mathilda Gustafsson)",female,33,3,0,3101278,15.85,,S 88 | 87,0,3,"Ford, Mr. William Neal",male,16,1,3,W./C. 6608,34.375,,S 89 | 88,0,3,"Slocovski, Mr. Selman Francis",male,,0,0,SOTON/OQ 392086,8.05,,S 90 | 89,1,1,"Fortune, Miss. Mabel Helen",female,23,3,2,19950,263,C23 C25 C27,S 91 | 90,0,3,"Celotti, Mr. Francesco",male,24,0,0,343275,8.05,,S 92 | 91,0,3,"Christmann, Mr. Emil",male,29,0,0,343276,8.05,,S 93 | 92,0,3,"Andreasson, Mr. Paul Edvin",male,20,0,0,347466,7.8542,,S 94 | 93,0,1,"Chaffee, Mr. Herbert Fuller",male,46,1,0,W.E.P. 5734,61.175,E31,S 95 | 94,0,3,"Dean, Mr. Bertram Frank",male,26,1,2,C.A. 2315,20.575,,S 96 | 95,0,3,"Coxon, Mr. Daniel",male,59,0,0,364500,7.25,,S 97 | 96,0,3,"Shorney, Mr. Charles Joseph",male,,0,0,374910,8.05,,S 98 | 97,0,1,"Goldschmidt, Mr. George B",male,71,0,0,PC 17754,34.6542,A5,C 99 | 98,1,1,"Greenfield, Mr. William Bertram",male,23,0,1,PC 17759,63.3583,D10 D12,C 100 | 99,1,2,"Doling, Mrs. John T (Ada Julia Bone)",female,34,0,1,231919,23,,S 101 | 100,0,2,"Kantor, Mr. Sinai",male,34,1,0,244367,26,,S 102 | 101,0,3,"Petranec, Miss. Matilda",female,28,0,0,349245,7.8958,,S 103 | 102,0,3,"Petroff, Mr. Pastcho (""Pentcho"")",male,,0,0,349215,7.8958,,S 104 | 103,0,1,"White, Mr. Richard Frasar",male,21,0,1,35281,77.2875,D26,S 105 | 104,0,3,"Johansson, Mr. Gustaf Joel",male,33,0,0,7540,8.6542,,S 106 | 105,0,3,"Gustafsson, Mr. Anders Vilhelm",male,37,2,0,3101276,7.925,,S 107 | 106,0,3,"Mionoff, Mr. Stoytcho",male,28,0,0,349207,7.8958,,S 108 | 107,1,3,"Salkjelsvik, Miss. Anna Kristine",female,21,0,0,343120,7.65,,S 109 | 108,1,3,"Moss, Mr. Albert Johan",male,,0,0,312991,7.775,,S 110 | 109,0,3,"Rekic, Mr. Tido",male,38,0,0,349249,7.8958,,S 111 | 110,1,3,"Moran, Miss. Bertha",female,,1,0,371110,24.15,,Q 112 | 111,0,1,"Porter, Mr. Walter Chamberlain",male,47,0,0,110465,52,C110,S 113 | 112,0,3,"Zabour, Miss. Hileni",female,14.5,1,0,2665,14.4542,,C 114 | 113,0,3,"Barton, Mr. David John",male,22,0,0,324669,8.05,,S 115 | 114,0,3,"Jussila, Miss. Katriina",female,20,1,0,4136,9.825,,S 116 | 115,0,3,"Attalah, Miss. Malake",female,17,0,0,2627,14.4583,,C 117 | 116,0,3,"Pekoniemi, Mr. Edvard",male,21,0,0,STON/O 2. 3101294,7.925,,S 118 | 117,0,3,"Connors, Mr. Patrick",male,70.5,0,0,370369,7.75,,Q 119 | 118,0,2,"Turpin, Mr. William John Robert",male,29,1,0,11668,21,,S 120 | 119,0,1,"Baxter, Mr. Quigg Edmond",male,24,0,1,PC 17558,247.5208,B58 B60,C 121 | 120,0,3,"Andersson, Miss. Ellis Anna Maria",female,2,4,2,347082,31.275,,S 122 | 121,0,2,"Hickman, Mr. Stanley George",male,21,2,0,S.O.C. 14879,73.5,,S 123 | 122,0,3,"Moore, Mr. Leonard Charles",male,,0,0,A4. 54510,8.05,,S 124 | 123,0,2,"Nasser, Mr. Nicholas",male,32.5,1,0,237736,30.0708,,C 125 | 124,1,2,"Webber, Miss. Susan",female,32.5,0,0,27267,13,E101,S 126 | 125,0,1,"White, Mr. Percival Wayland",male,54,0,1,35281,77.2875,D26,S 127 | 126,1,3,"Nicola-Yarred, Master. Elias",male,12,1,0,2651,11.2417,,C 128 | 127,0,3,"McMahon, Mr. Martin",male,,0,0,370372,7.75,,Q 129 | 128,1,3,"Madsen, Mr. Fridtjof Arne",male,24,0,0,C 17369,7.1417,,S 130 | 129,1,3,"Peter, Miss. Anna",female,,1,1,2668,22.3583,F E69,C 131 | 130,0,3,"Ekstrom, Mr. Johan",male,45,0,0,347061,6.975,,S 132 | 131,0,3,"Drazenoic, Mr. Jozef",male,33,0,0,349241,7.8958,,C 133 | 132,0,3,"Coelho, Mr. Domingos Fernandeo",male,20,0,0,SOTON/O.Q. 3101307,7.05,,S 134 | 133,0,3,"Robins, Mrs. Alexander A (Grace Charity Laury)",female,47,1,0,A/5. 3337,14.5,,S 135 | 134,1,2,"Weisz, Mrs. Leopold (Mathilde Francoise Pede)",female,29,1,0,228414,26,,S 136 | 135,0,2,"Sobey, Mr. Samuel James Hayden",male,25,0,0,C.A. 29178,13,,S 137 | 136,0,2,"Richard, Mr. Emile",male,23,0,0,SC/PARIS 2133,15.0458,,C 138 | 137,1,1,"Newsom, Miss. Helen Monypeny",female,19,0,2,11752,26.2833,D47,S 139 | 138,0,1,"Futrelle, Mr. Jacques Heath",male,37,1,0,113803,53.1,C123,S 140 | 139,0,3,"Osen, Mr. Olaf Elon",male,16,0,0,7534,9.2167,,S 141 | 140,0,1,"Giglio, Mr. Victor",male,24,0,0,PC 17593,79.2,B86,C 142 | 141,0,3,"Boulos, Mrs. Joseph (Sultana)",female,,0,2,2678,15.2458,,C 143 | 142,1,3,"Nysten, Miss. Anna Sofia",female,22,0,0,347081,7.75,,S 144 | 143,1,3,"Hakkarainen, Mrs. Pekka Pietari (Elin Matilda Dolck)",female,24,1,0,STON/O2. 3101279,15.85,,S 145 | 144,0,3,"Burke, Mr. Jeremiah",male,19,0,0,365222,6.75,,Q 146 | 145,0,2,"Andrew, Mr. Edgardo Samuel",male,18,0,0,231945,11.5,,S 147 | 146,0,2,"Nicholls, Mr. Joseph Charles",male,19,1,1,C.A. 33112,36.75,,S 148 | 147,1,3,"Andersson, Mr. August Edvard (""Wennerstrom"")",male,27,0,0,350043,7.7958,,S 149 | 148,0,3,"Ford, Miss. Robina Maggie ""Ruby""",female,9,2,2,W./C. 6608,34.375,,S 150 | 149,0,2,"Navratil, Mr. Michel (""Louis M Hoffman"")",male,36.5,0,2,230080,26,F2,S 151 | 150,0,2,"Byles, Rev. Thomas Roussel Davids",male,42,0,0,244310,13,,S 152 | 151,0,2,"Bateman, Rev. Robert James",male,51,0,0,S.O.P. 1166,12.525,,S 153 | 152,1,1,"Pears, Mrs. Thomas (Edith Wearne)",female,22,1,0,113776,66.6,C2,S 154 | 153,0,3,"Meo, Mr. Alfonzo",male,55.5,0,0,A.5. 11206,8.05,,S 155 | 154,0,3,"van Billiard, Mr. Austin Blyler",male,40.5,0,2,A/5. 851,14.5,,S 156 | 155,0,3,"Olsen, Mr. Ole Martin",male,,0,0,Fa 265302,7.3125,,S 157 | 156,0,1,"Williams, Mr. Charles Duane",male,51,0,1,PC 17597,61.3792,,C 158 | 157,1,3,"Gilnagh, Miss. Katherine ""Katie""",female,16,0,0,35851,7.7333,,Q 159 | 158,0,3,"Corn, Mr. Harry",male,30,0,0,SOTON/OQ 392090,8.05,,S 160 | 159,0,3,"Smiljanic, Mr. Mile",male,,0,0,315037,8.6625,,S 161 | 160,0,3,"Sage, Master. Thomas Henry",male,,8,2,CA. 2343,69.55,,S 162 | 161,0,3,"Cribb, Mr. John Hatfield",male,44,0,1,371362,16.1,,S 163 | 162,1,2,"Watt, Mrs. James (Elizabeth ""Bessie"" Inglis Milne)",female,40,0,0,C.A. 33595,15.75,,S 164 | 163,0,3,"Bengtsson, Mr. John Viktor",male,26,0,0,347068,7.775,,S 165 | 164,0,3,"Calic, Mr. Jovo",male,17,0,0,315093,8.6625,,S 166 | 165,0,3,"Panula, Master. Eino Viljami",male,1,4,1,3101295,39.6875,,S 167 | 166,1,3,"Goldsmith, Master. Frank John William ""Frankie""",male,9,0,2,363291,20.525,,S 168 | 167,1,1,"Chibnall, Mrs. (Edith Martha Bowerman)",female,,0,1,113505,55,E33,S 169 | 168,0,3,"Skoog, Mrs. William (Anna Bernhardina Karlsson)",female,45,1,4,347088,27.9,,S 170 | 169,0,1,"Baumann, Mr. John D",male,,0,0,PC 17318,25.925,,S 171 | 170,0,3,"Ling, Mr. Lee",male,28,0,0,1601,56.4958,,S 172 | 171,0,1,"Van der hoef, Mr. Wyckoff",male,61,0,0,111240,33.5,B19,S 173 | 172,0,3,"Rice, Master. Arthur",male,4,4,1,382652,29.125,,Q 174 | 173,1,3,"Johnson, Miss. Eleanor Ileen",female,1,1,1,347742,11.1333,,S 175 | 174,0,3,"Sivola, Mr. Antti Wilhelm",male,21,0,0,STON/O 2. 3101280,7.925,,S 176 | 175,0,1,"Smith, Mr. James Clinch",male,56,0,0,17764,30.6958,A7,C 177 | 176,0,3,"Klasen, Mr. Klas Albin",male,18,1,1,350404,7.8542,,S 178 | 177,0,3,"Lefebre, Master. Henry Forbes",male,,3,1,4133,25.4667,,S 179 | 178,0,1,"Isham, Miss. Ann Elizabeth",female,50,0,0,PC 17595,28.7125,C49,C 180 | 179,0,2,"Hale, Mr. Reginald",male,30,0,0,250653,13,,S 181 | 180,0,3,"Leonard, Mr. Lionel",male,36,0,0,LINE,0,,S 182 | 181,0,3,"Sage, Miss. Constance Gladys",female,,8,2,CA. 2343,69.55,,S 183 | 182,0,2,"Pernot, Mr. Rene",male,,0,0,SC/PARIS 2131,15.05,,C 184 | 183,0,3,"Asplund, Master. Clarence Gustaf Hugo",male,9,4,2,347077,31.3875,,S 185 | 184,1,2,"Becker, Master. Richard F",male,1,2,1,230136,39,F4,S 186 | 185,1,3,"Kink-Heilmann, Miss. Luise Gretchen",female,4,0,2,315153,22.025,,S 187 | 186,0,1,"Rood, Mr. Hugh Roscoe",male,,0,0,113767,50,A32,S 188 | 187,1,3,"O'Brien, Mrs. Thomas (Johanna ""Hannah"" Godfrey)",female,,1,0,370365,15.5,,Q 189 | 188,1,1,"Romaine, Mr. Charles Hallace (""Mr C Rolmane"")",male,45,0,0,111428,26.55,,S 190 | 189,0,3,"Bourke, Mr. John",male,40,1,1,364849,15.5,,Q 191 | 190,0,3,"Turcin, Mr. Stjepan",male,36,0,0,349247,7.8958,,S 192 | 191,1,2,"Pinsky, Mrs. (Rosa)",female,32,0,0,234604,13,,S 193 | 192,0,2,"Carbines, Mr. William",male,19,0,0,28424,13,,S 194 | 193,1,3,"Andersen-Jensen, Miss. Carla Christine Nielsine",female,19,1,0,350046,7.8542,,S 195 | 194,1,2,"Navratil, Master. Michel M",male,3,1,1,230080,26,F2,S 196 | 195,1,1,"Brown, Mrs. James Joseph (Margaret Tobin)",female,44,0,0,PC 17610,27.7208,B4,C 197 | 196,1,1,"Lurette, Miss. Elise",female,58,0,0,PC 17569,146.5208,B80,C 198 | 197,0,3,"Mernagh, Mr. Robert",male,,0,0,368703,7.75,,Q 199 | 198,0,3,"Olsen, Mr. Karl Siegwart Andreas",male,42,0,1,4579,8.4042,,S 200 | 199,1,3,"Madigan, Miss. Margaret ""Maggie""",female,,0,0,370370,7.75,,Q 201 | 200,0,2,"Yrois, Miss. Henriette (""Mrs Harbeck"")",female,24,0,0,248747,13,,S 202 | 201,0,3,"Vande Walle, Mr. Nestor Cyriel",male,28,0,0,345770,9.5,,S 203 | 202,0,3,"Sage, Mr. Frederick",male,,8,2,CA. 2343,69.55,,S 204 | 203,0,3,"Johanson, Mr. Jakob Alfred",male,34,0,0,3101264,6.4958,,S 205 | 204,0,3,"Youseff, Mr. Gerious",male,45.5,0,0,2628,7.225,,C 206 | 205,1,3,"Cohen, Mr. Gurshon ""Gus""",male,18,0,0,A/5 3540,8.05,,S 207 | 206,0,3,"Strom, Miss. Telma Matilda",female,2,0,1,347054,10.4625,G6,S 208 | 207,0,3,"Backstrom, Mr. Karl Alfred",male,32,1,0,3101278,15.85,,S 209 | 208,1,3,"Albimona, Mr. Nassef Cassem",male,26,0,0,2699,18.7875,,C 210 | 209,1,3,"Carr, Miss. Helen ""Ellen""",female,16,0,0,367231,7.75,,Q 211 | 210,1,1,"Blank, Mr. Henry",male,40,0,0,112277,31,A31,C 212 | 211,0,3,"Ali, Mr. Ahmed",male,24,0,0,SOTON/O.Q. 3101311,7.05,,S 213 | 212,1,2,"Cameron, Miss. Clear Annie",female,35,0,0,F.C.C. 13528,21,,S 214 | 213,0,3,"Perkin, Mr. John Henry",male,22,0,0,A/5 21174,7.25,,S 215 | 214,0,2,"Givard, Mr. Hans Kristensen",male,30,0,0,250646,13,,S 216 | 215,0,3,"Kiernan, Mr. Philip",male,,1,0,367229,7.75,,Q 217 | 216,1,1,"Newell, Miss. Madeleine",female,31,1,0,35273,113.275,D36,C 218 | 217,1,3,"Honkanen, Miss. Eliina",female,27,0,0,STON/O2. 3101283,7.925,,S 219 | 218,0,2,"Jacobsohn, Mr. Sidney Samuel",male,42,1,0,243847,27,,S 220 | 219,1,1,"Bazzani, Miss. Albina",female,32,0,0,11813,76.2917,D15,C 221 | 220,0,2,"Harris, Mr. Walter",male,30,0,0,W/C 14208,10.5,,S 222 | 221,1,3,"Sunderland, Mr. Victor Francis",male,16,0,0,SOTON/OQ 392089,8.05,,S 223 | 222,0,2,"Bracken, Mr. James H",male,27,0,0,220367,13,,S 224 | 223,0,3,"Green, Mr. George Henry",male,51,0,0,21440,8.05,,S 225 | 224,0,3,"Nenkoff, Mr. Christo",male,,0,0,349234,7.8958,,S 226 | 225,1,1,"Hoyt, Mr. Frederick Maxfield",male,38,1,0,19943,90,C93,S 227 | 226,0,3,"Berglund, Mr. Karl Ivar Sven",male,22,0,0,PP 4348,9.35,,S 228 | 227,1,2,"Mellors, Mr. William John",male,19,0,0,SW/PP 751,10.5,,S 229 | 228,0,3,"Lovell, Mr. John Hall (""Henry"")",male,20.5,0,0,A/5 21173,7.25,,S 230 | 229,0,2,"Fahlstrom, Mr. Arne Jonas",male,18,0,0,236171,13,,S 231 | 230,0,3,"Lefebre, Miss. Mathilde",female,,3,1,4133,25.4667,,S 232 | 231,1,1,"Harris, Mrs. Henry Birkhardt (Irene Wallach)",female,35,1,0,36973,83.475,C83,S 233 | 232,0,3,"Larsson, Mr. Bengt Edvin",male,29,0,0,347067,7.775,,S 234 | 233,0,2,"Sjostedt, Mr. Ernst Adolf",male,59,0,0,237442,13.5,,S 235 | 234,1,3,"Asplund, Miss. Lillian Gertrud",female,5,4,2,347077,31.3875,,S 236 | 235,0,2,"Leyson, Mr. Robert William Norman",male,24,0,0,C.A. 29566,10.5,,S 237 | 236,0,3,"Harknett, Miss. Alice Phoebe",female,,0,0,W./C. 6609,7.55,,S 238 | 237,0,2,"Hold, Mr. Stephen",male,44,1,0,26707,26,,S 239 | 238,1,2,"Collyer, Miss. Marjorie ""Lottie""",female,8,0,2,C.A. 31921,26.25,,S 240 | 239,0,2,"Pengelly, Mr. Frederick William",male,19,0,0,28665,10.5,,S 241 | 240,0,2,"Hunt, Mr. George Henry",male,33,0,0,SCO/W 1585,12.275,,S 242 | 241,0,3,"Zabour, Miss. Thamine",female,,1,0,2665,14.4542,,C 243 | 242,1,3,"Murphy, Miss. Katherine ""Kate""",female,,1,0,367230,15.5,,Q 244 | 243,0,2,"Coleridge, Mr. Reginald Charles",male,29,0,0,W./C. 14263,10.5,,S 245 | 244,0,3,"Maenpaa, Mr. Matti Alexanteri",male,22,0,0,STON/O 2. 3101275,7.125,,S 246 | 245,0,3,"Attalah, Mr. Sleiman",male,30,0,0,2694,7.225,,C 247 | 246,0,1,"Minahan, Dr. William Edward",male,44,2,0,19928,90,C78,Q 248 | 247,0,3,"Lindahl, Miss. Agda Thorilda Viktoria",female,25,0,0,347071,7.775,,S 249 | 248,1,2,"Hamalainen, Mrs. William (Anna)",female,24,0,2,250649,14.5,,S 250 | 249,1,1,"Beckwith, Mr. Richard Leonard",male,37,1,1,11751,52.5542,D35,S 251 | 250,0,2,"Carter, Rev. Ernest Courtenay",male,54,1,0,244252,26,,S 252 | 251,0,3,"Reed, Mr. James George",male,,0,0,362316,7.25,,S 253 | 252,0,3,"Strom, Mrs. Wilhelm (Elna Matilda Persson)",female,29,1,1,347054,10.4625,G6,S 254 | 253,0,1,"Stead, Mr. William Thomas",male,62,0,0,113514,26.55,C87,S 255 | 254,0,3,"Lobb, Mr. William Arthur",male,30,1,0,A/5. 3336,16.1,,S 256 | 255,0,3,"Rosblom, Mrs. Viktor (Helena Wilhelmina)",female,41,0,2,370129,20.2125,,S 257 | 256,1,3,"Touma, Mrs. Darwis (Hanne Youssef Razi)",female,29,0,2,2650,15.2458,,C 258 | 257,1,1,"Thorne, Mrs. Gertrude Maybelle",female,,0,0,PC 17585,79.2,,C 259 | 258,1,1,"Cherry, Miss. Gladys",female,30,0,0,110152,86.5,B77,S 260 | 259,1,1,"Ward, Miss. Anna",female,35,0,0,PC 17755,512.3292,,C 261 | 260,1,2,"Parrish, Mrs. (Lutie Davis)",female,50,0,1,230433,26,,S 262 | 261,0,3,"Smith, Mr. Thomas",male,,0,0,384461,7.75,,Q 263 | 262,1,3,"Asplund, Master. Edvin Rojj Felix",male,3,4,2,347077,31.3875,,S 264 | 263,0,1,"Taussig, Mr. Emil",male,52,1,1,110413,79.65,E67,S 265 | 264,0,1,"Harrison, Mr. William",male,40,0,0,112059,0,B94,S 266 | 265,0,3,"Henry, Miss. Delia",female,,0,0,382649,7.75,,Q 267 | 266,0,2,"Reeves, Mr. David",male,36,0,0,C.A. 17248,10.5,,S 268 | 267,0,3,"Panula, Mr. Ernesti Arvid",male,16,4,1,3101295,39.6875,,S 269 | 268,1,3,"Persson, Mr. Ernst Ulrik",male,25,1,0,347083,7.775,,S 270 | 269,1,1,"Graham, Mrs. William Thompson (Edith Junkins)",female,58,0,1,PC 17582,153.4625,C125,S 271 | 270,1,1,"Bissette, Miss. Amelia",female,35,0,0,PC 17760,135.6333,C99,S 272 | 271,0,1,"Cairns, Mr. Alexander",male,,0,0,113798,31,,S 273 | 272,1,3,"Tornquist, Mr. William Henry",male,25,0,0,LINE,0,,S 274 | 273,1,2,"Mellinger, Mrs. (Elizabeth Anne Maidment)",female,41,0,1,250644,19.5,,S 275 | 274,0,1,"Natsch, Mr. Charles H",male,37,0,1,PC 17596,29.7,C118,C 276 | 275,1,3,"Healy, Miss. Hanora ""Nora""",female,,0,0,370375,7.75,,Q 277 | 276,1,1,"Andrews, Miss. Kornelia Theodosia",female,63,1,0,13502,77.9583,D7,S 278 | 277,0,3,"Lindblom, Miss. Augusta Charlotta",female,45,0,0,347073,7.75,,S 279 | 278,0,2,"Parkes, Mr. Francis ""Frank""",male,,0,0,239853,0,,S 280 | 279,0,3,"Rice, Master. Eric",male,7,4,1,382652,29.125,,Q 281 | 280,1,3,"Abbott, Mrs. Stanton (Rosa Hunt)",female,35,1,1,C.A. 2673,20.25,,S 282 | 281,0,3,"Duane, Mr. Frank",male,65,0,0,336439,7.75,,Q 283 | 282,0,3,"Olsson, Mr. Nils Johan Goransson",male,28,0,0,347464,7.8542,,S 284 | 283,0,3,"de Pelsmaeker, Mr. Alfons",male,16,0,0,345778,9.5,,S 285 | 284,1,3,"Dorking, Mr. Edward Arthur",male,19,0,0,A/5. 10482,8.05,,S 286 | 285,0,1,"Smith, Mr. Richard William",male,,0,0,113056,26,A19,S 287 | 286,0,3,"Stankovic, Mr. Ivan",male,33,0,0,349239,8.6625,,C 288 | 287,1,3,"de Mulder, Mr. Theodore",male,30,0,0,345774,9.5,,S 289 | 288,0,3,"Naidenoff, Mr. Penko",male,22,0,0,349206,7.8958,,S 290 | 289,1,2,"Hosono, Mr. Masabumi",male,42,0,0,237798,13,,S 291 | 290,1,3,"Connolly, Miss. Kate",female,22,0,0,370373,7.75,,Q 292 | 291,1,1,"Barber, Miss. Ellen ""Nellie""",female,26,0,0,19877,78.85,,S 293 | 292,1,1,"Bishop, Mrs. Dickinson H (Helen Walton)",female,19,1,0,11967,91.0792,B49,C 294 | 293,0,2,"Levy, Mr. Rene Jacques",male,36,0,0,SC/Paris 2163,12.875,D,C 295 | 294,0,3,"Haas, Miss. Aloisia",female,24,0,0,349236,8.85,,S 296 | 295,0,3,"Mineff, Mr. Ivan",male,24,0,0,349233,7.8958,,S 297 | 296,0,1,"Lewy, Mr. Ervin G",male,,0,0,PC 17612,27.7208,,C 298 | 297,0,3,"Hanna, Mr. Mansour",male,23.5,0,0,2693,7.2292,,C 299 | 298,0,1,"Allison, Miss. Helen Loraine",female,2,1,2,113781,151.55,C22 C26,S 300 | 299,1,1,"Saalfeld, Mr. Adolphe",male,,0,0,19988,30.5,C106,S 301 | 300,1,1,"Baxter, Mrs. James (Helene DeLaudeniere Chaput)",female,50,0,1,PC 17558,247.5208,B58 B60,C 302 | 301,1,3,"Kelly, Miss. Anna Katherine ""Annie Kate""",female,,0,0,9234,7.75,,Q 303 | 302,1,3,"McCoy, Mr. Bernard",male,,2,0,367226,23.25,,Q 304 | 303,0,3,"Johnson, Mr. William Cahoone Jr",male,19,0,0,LINE,0,,S 305 | 304,1,2,"Keane, Miss. Nora A",female,,0,0,226593,12.35,E101,Q 306 | 305,0,3,"Williams, Mr. Howard Hugh ""Harry""",male,,0,0,A/5 2466,8.05,,S 307 | 306,1,1,"Allison, Master. Hudson Trevor",male,0.92,1,2,113781,151.55,C22 C26,S 308 | 307,1,1,"Fleming, Miss. Margaret",female,,0,0,17421,110.8833,,C 309 | 308,1,1,"Penasco y Castellana, Mrs. Victor de Satode (Maria Josefa Perez de Soto y Vallejo)",female,17,1,0,PC 17758,108.9,C65,C 310 | 309,0,2,"Abelson, Mr. Samuel",male,30,1,0,P/PP 3381,24,,C 311 | 310,1,1,"Francatelli, Miss. Laura Mabel",female,30,0,0,PC 17485,56.9292,E36,C 312 | 311,1,1,"Hays, Miss. Margaret Bechstein",female,24,0,0,11767,83.1583,C54,C 313 | 312,1,1,"Ryerson, Miss. Emily Borie",female,18,2,2,PC 17608,262.375,B57 B59 B63 B66,C 314 | 313,0,2,"Lahtinen, Mrs. William (Anna Sylfven)",female,26,1,1,250651,26,,S 315 | 314,0,3,"Hendekovic, Mr. Ignjac",male,28,0,0,349243,7.8958,,S 316 | 315,0,2,"Hart, Mr. Benjamin",male,43,1,1,F.C.C. 13529,26.25,,S 317 | 316,1,3,"Nilsson, Miss. Helmina Josefina",female,26,0,0,347470,7.8542,,S 318 | 317,1,2,"Kantor, Mrs. Sinai (Miriam Sternin)",female,24,1,0,244367,26,,S 319 | 318,0,2,"Moraweck, Dr. Ernest",male,54,0,0,29011,14,,S 320 | 319,1,1,"Wick, Miss. Mary Natalie",female,31,0,2,36928,164.8667,C7,S 321 | 320,1,1,"Spedden, Mrs. Frederic Oakley (Margaretta Corning Stone)",female,40,1,1,16966,134.5,E34,C 322 | 321,0,3,"Dennis, Mr. Samuel",male,22,0,0,A/5 21172,7.25,,S 323 | 322,0,3,"Danoff, Mr. Yoto",male,27,0,0,349219,7.8958,,S 324 | 323,1,2,"Slayter, Miss. Hilda Mary",female,30,0,0,234818,12.35,,Q 325 | 324,1,2,"Caldwell, Mrs. Albert Francis (Sylvia Mae Harbaugh)",female,22,1,1,248738,29,,S 326 | 325,0,3,"Sage, Mr. George John Jr",male,,8,2,CA. 2343,69.55,,S 327 | 326,1,1,"Young, Miss. Marie Grice",female,36,0,0,PC 17760,135.6333,C32,C 328 | 327,0,3,"Nysveen, Mr. Johan Hansen",male,61,0,0,345364,6.2375,,S 329 | 328,1,2,"Ball, Mrs. (Ada E Hall)",female,36,0,0,28551,13,D,S 330 | 329,1,3,"Goldsmith, Mrs. Frank John (Emily Alice Brown)",female,31,1,1,363291,20.525,,S 331 | 330,1,1,"Hippach, Miss. Jean Gertrude",female,16,0,1,111361,57.9792,B18,C 332 | 331,1,3,"McCoy, Miss. Agnes",female,,2,0,367226,23.25,,Q 333 | 332,0,1,"Partner, Mr. Austen",male,45.5,0,0,113043,28.5,C124,S 334 | 333,0,1,"Graham, Mr. George Edward",male,38,0,1,PC 17582,153.4625,C91,S 335 | 334,0,3,"Vander Planke, Mr. Leo Edmondus",male,16,2,0,345764,18,,S 336 | 335,1,1,"Frauenthal, Mrs. Henry William (Clara Heinsheimer)",female,,1,0,PC 17611,133.65,,S 337 | 336,0,3,"Denkoff, Mr. Mitto",male,,0,0,349225,7.8958,,S 338 | 337,0,1,"Pears, Mr. Thomas Clinton",male,29,1,0,113776,66.6,C2,S 339 | 338,1,1,"Burns, Miss. Elizabeth Margaret",female,41,0,0,16966,134.5,E40,C 340 | 339,1,3,"Dahl, Mr. Karl Edwart",male,45,0,0,7598,8.05,,S 341 | 340,0,1,"Blackwell, Mr. Stephen Weart",male,45,0,0,113784,35.5,T,S 342 | 341,1,2,"Navratil, Master. Edmond Roger",male,2,1,1,230080,26,F2,S 343 | 342,1,1,"Fortune, Miss. Alice Elizabeth",female,24,3,2,19950,263,C23 C25 C27,S 344 | 343,0,2,"Collander, Mr. Erik Gustaf",male,28,0,0,248740,13,,S 345 | 344,0,2,"Sedgwick, Mr. Charles Frederick Waddington",male,25,0,0,244361,13,,S 346 | 345,0,2,"Fox, Mr. Stanley Hubert",male,36,0,0,229236,13,,S 347 | 346,1,2,"Brown, Miss. Amelia ""Mildred""",female,24,0,0,248733,13,F33,S 348 | 347,1,2,"Smith, Miss. Marion Elsie",female,40,0,0,31418,13,,S 349 | 348,1,3,"Davison, Mrs. Thomas Henry (Mary E Finck)",female,,1,0,386525,16.1,,S 350 | 349,1,3,"Coutts, Master. William Loch ""William""",male,3,1,1,C.A. 37671,15.9,,S 351 | 350,0,3,"Dimic, Mr. Jovan",male,42,0,0,315088,8.6625,,S 352 | 351,0,3,"Odahl, Mr. Nils Martin",male,23,0,0,7267,9.225,,S 353 | 352,0,1,"Williams-Lambert, Mr. Fletcher Fellows",male,,0,0,113510,35,C128,S 354 | 353,0,3,"Elias, Mr. Tannous",male,15,1,1,2695,7.2292,,C 355 | 354,0,3,"Arnold-Franchi, Mr. Josef",male,25,1,0,349237,17.8,,S 356 | 355,0,3,"Yousif, Mr. Wazli",male,,0,0,2647,7.225,,C 357 | 356,0,3,"Vanden Steen, Mr. Leo Peter",male,28,0,0,345783,9.5,,S 358 | 357,1,1,"Bowerman, Miss. Elsie Edith",female,22,0,1,113505,55,E33,S 359 | 358,0,2,"Funk, Miss. Annie Clemmer",female,38,0,0,237671,13,,S 360 | 359,1,3,"McGovern, Miss. Mary",female,,0,0,330931,7.8792,,Q 361 | 360,1,3,"Mockler, Miss. Helen Mary ""Ellie""",female,,0,0,330980,7.8792,,Q 362 | 361,0,3,"Skoog, Mr. Wilhelm",male,40,1,4,347088,27.9,,S 363 | 362,0,2,"del Carlo, Mr. Sebastiano",male,29,1,0,SC/PARIS 2167,27.7208,,C 364 | 363,0,3,"Barbara, Mrs. (Catherine David)",female,45,0,1,2691,14.4542,,C 365 | 364,0,3,"Asim, Mr. Adola",male,35,0,0,SOTON/O.Q. 3101310,7.05,,S 366 | 365,0,3,"O'Brien, Mr. Thomas",male,,1,0,370365,15.5,,Q 367 | 366,0,3,"Adahl, Mr. Mauritz Nils Martin",male,30,0,0,C 7076,7.25,,S 368 | 367,1,1,"Warren, Mrs. Frank Manley (Anna Sophia Atkinson)",female,60,1,0,110813,75.25,D37,C 369 | 368,1,3,"Moussa, Mrs. (Mantoura Boulos)",female,,0,0,2626,7.2292,,C 370 | 369,1,3,"Jermyn, Miss. Annie",female,,0,0,14313,7.75,,Q 371 | 370,1,1,"Aubart, Mme. Leontine Pauline",female,24,0,0,PC 17477,69.3,B35,C 372 | 371,1,1,"Harder, Mr. George Achilles",male,25,1,0,11765,55.4417,E50,C 373 | 372,0,3,"Wiklund, Mr. Jakob Alfred",male,18,1,0,3101267,6.4958,,S 374 | 373,0,3,"Beavan, Mr. William Thomas",male,19,0,0,323951,8.05,,S 375 | 374,0,1,"Ringhini, Mr. Sante",male,22,0,0,PC 17760,135.6333,,C 376 | 375,0,3,"Palsson, Miss. Stina Viola",female,3,3,1,349909,21.075,,S 377 | 376,1,1,"Meyer, Mrs. Edgar Joseph (Leila Saks)",female,,1,0,PC 17604,82.1708,,C 378 | 377,1,3,"Landergren, Miss. Aurora Adelia",female,22,0,0,C 7077,7.25,,S 379 | 378,0,1,"Widener, Mr. Harry Elkins",male,27,0,2,113503,211.5,C82,C 380 | 379,0,3,"Betros, Mr. Tannous",male,20,0,0,2648,4.0125,,C 381 | 380,0,3,"Gustafsson, Mr. Karl Gideon",male,19,0,0,347069,7.775,,S 382 | 381,1,1,"Bidois, Miss. Rosalie",female,42,0,0,PC 17757,227.525,,C 383 | 382,1,3,"Nakid, Miss. Maria (""Mary"")",female,1,0,2,2653,15.7417,,C 384 | 383,0,3,"Tikkanen, Mr. Juho",male,32,0,0,STON/O 2. 3101293,7.925,,S 385 | 384,1,1,"Holverson, Mrs. Alexander Oskar (Mary Aline Towner)",female,35,1,0,113789,52,,S 386 | 385,0,3,"Plotcharsky, Mr. Vasil",male,,0,0,349227,7.8958,,S 387 | 386,0,2,"Davies, Mr. Charles Henry",male,18,0,0,S.O.C. 14879,73.5,,S 388 | 387,0,3,"Goodwin, Master. Sidney Leonard",male,1,5,2,CA 2144,46.9,,S 389 | 388,1,2,"Buss, Miss. Kate",female,36,0,0,27849,13,,S 390 | 389,0,3,"Sadlier, Mr. Matthew",male,,0,0,367655,7.7292,,Q 391 | 390,1,2,"Lehmann, Miss. Bertha",female,17,0,0,SC 1748,12,,C 392 | 391,1,1,"Carter, Mr. William Ernest",male,36,1,2,113760,120,B96 B98,S 393 | 392,1,3,"Jansson, Mr. Carl Olof",male,21,0,0,350034,7.7958,,S 394 | 393,0,3,"Gustafsson, Mr. Johan Birger",male,28,2,0,3101277,7.925,,S 395 | 394,1,1,"Newell, Miss. Marjorie",female,23,1,0,35273,113.275,D36,C 396 | 395,1,3,"Sandstrom, Mrs. Hjalmar (Agnes Charlotta Bengtsson)",female,24,0,2,PP 9549,16.7,G6,S 397 | 396,0,3,"Johansson, Mr. Erik",male,22,0,0,350052,7.7958,,S 398 | 397,0,3,"Olsson, Miss. Elina",female,31,0,0,350407,7.8542,,S 399 | 398,0,2,"McKane, Mr. Peter David",male,46,0,0,28403,26,,S 400 | 399,0,2,"Pain, Dr. Alfred",male,23,0,0,244278,10.5,,S 401 | 400,1,2,"Trout, Mrs. William H (Jessie L)",female,28,0,0,240929,12.65,,S 402 | 401,1,3,"Niskanen, Mr. Juha",male,39,0,0,STON/O 2. 3101289,7.925,,S 403 | 402,0,3,"Adams, Mr. John",male,26,0,0,341826,8.05,,S 404 | 403,0,3,"Jussila, Miss. Mari Aina",female,21,1,0,4137,9.825,,S 405 | 404,0,3,"Hakkarainen, Mr. Pekka Pietari",male,28,1,0,STON/O2. 3101279,15.85,,S 406 | 405,0,3,"Oreskovic, Miss. Marija",female,20,0,0,315096,8.6625,,S 407 | 406,0,2,"Gale, Mr. Shadrach",male,34,1,0,28664,21,,S 408 | 407,0,3,"Widegren, Mr. Carl/Charles Peter",male,51,0,0,347064,7.75,,S 409 | 408,1,2,"Richards, Master. William Rowe",male,3,1,1,29106,18.75,,S 410 | 409,0,3,"Birkeland, Mr. Hans Martin Monsen",male,21,0,0,312992,7.775,,S 411 | 410,0,3,"Lefebre, Miss. Ida",female,,3,1,4133,25.4667,,S 412 | 411,0,3,"Sdycoff, Mr. Todor",male,,0,0,349222,7.8958,,S 413 | 412,0,3,"Hart, Mr. Henry",male,,0,0,394140,6.8583,,Q 414 | 413,1,1,"Minahan, Miss. Daisy E",female,33,1,0,19928,90,C78,Q 415 | 414,0,2,"Cunningham, Mr. Alfred Fleming",male,,0,0,239853,0,,S 416 | 415,1,3,"Sundman, Mr. Johan Julian",male,44,0,0,STON/O 2. 3101269,7.925,,S 417 | 416,0,3,"Meek, Mrs. Thomas (Annie Louise Rowley)",female,,0,0,343095,8.05,,S 418 | 417,1,2,"Drew, Mrs. James Vivian (Lulu Thorne Christian)",female,34,1,1,28220,32.5,,S 419 | 418,1,2,"Silven, Miss. Lyyli Karoliina",female,18,0,2,250652,13,,S 420 | 419,0,2,"Matthews, Mr. William John",male,30,0,0,28228,13,,S 421 | 420,0,3,"Van Impe, Miss. Catharina",female,10,0,2,345773,24.15,,S 422 | 421,0,3,"Gheorgheff, Mr. Stanio",male,,0,0,349254,7.8958,,C 423 | 422,0,3,"Charters, Mr. David",male,21,0,0,A/5. 13032,7.7333,,Q 424 | 423,0,3,"Zimmerman, Mr. Leo",male,29,0,0,315082,7.875,,S 425 | 424,0,3,"Danbom, Mrs. Ernst Gilbert (Anna Sigrid Maria Brogren)",female,28,1,1,347080,14.4,,S 426 | 425,0,3,"Rosblom, Mr. Viktor Richard",male,18,1,1,370129,20.2125,,S 427 | 426,0,3,"Wiseman, Mr. Phillippe",male,,0,0,A/4. 34244,7.25,,S 428 | 427,1,2,"Clarke, Mrs. Charles V (Ada Maria Winfield)",female,28,1,0,2003,26,,S 429 | 428,1,2,"Phillips, Miss. Kate Florence (""Mrs Kate Louise Phillips Marshall"")",female,19,0,0,250655,26,,S 430 | 429,0,3,"Flynn, Mr. James",male,,0,0,364851,7.75,,Q 431 | 430,1,3,"Pickard, Mr. Berk (Berk Trembisky)",male,32,0,0,SOTON/O.Q. 392078,8.05,E10,S 432 | 431,1,1,"Bjornstrom-Steffansson, Mr. Mauritz Hakan",male,28,0,0,110564,26.55,C52,S 433 | 432,1,3,"Thorneycroft, Mrs. Percival (Florence Kate White)",female,,1,0,376564,16.1,,S 434 | 433,1,2,"Louch, Mrs. Charles Alexander (Alice Adelaide Slow)",female,42,1,0,SC/AH 3085,26,,S 435 | 434,0,3,"Kallio, Mr. Nikolai Erland",male,17,0,0,STON/O 2. 3101274,7.125,,S 436 | 435,0,1,"Silvey, Mr. William Baird",male,50,1,0,13507,55.9,E44,S 437 | 436,1,1,"Carter, Miss. Lucile Polk",female,14,1,2,113760,120,B96 B98,S 438 | 437,0,3,"Ford, Miss. Doolina Margaret ""Daisy""",female,21,2,2,W./C. 6608,34.375,,S 439 | 438,1,2,"Richards, Mrs. Sidney (Emily Hocking)",female,24,2,3,29106,18.75,,S 440 | 439,0,1,"Fortune, Mr. Mark",male,64,1,4,19950,263,C23 C25 C27,S 441 | 440,0,2,"Kvillner, Mr. Johan Henrik Johannesson",male,31,0,0,C.A. 18723,10.5,,S 442 | 441,1,2,"Hart, Mrs. Benjamin (Esther Ada Bloomfield)",female,45,1,1,F.C.C. 13529,26.25,,S 443 | 442,0,3,"Hampe, Mr. Leon",male,20,0,0,345769,9.5,,S 444 | 443,0,3,"Petterson, Mr. Johan Emil",male,25,1,0,347076,7.775,,S 445 | 444,1,2,"Reynaldo, Ms. Encarnacion",female,28,0,0,230434,13,,S 446 | 445,1,3,"Johannesen-Bratthammer, Mr. Bernt",male,,0,0,65306,8.1125,,S 447 | 446,1,1,"Dodge, Master. Washington",male,4,0,2,33638,81.8583,A34,S 448 | 447,1,2,"Mellinger, Miss. Madeleine Violet",female,13,0,1,250644,19.5,,S 449 | 448,1,1,"Seward, Mr. Frederic Kimber",male,34,0,0,113794,26.55,,S 450 | 449,1,3,"Baclini, Miss. Marie Catherine",female,5,2,1,2666,19.2583,,C 451 | 450,1,1,"Peuchen, Major. Arthur Godfrey",male,52,0,0,113786,30.5,C104,S 452 | 451,0,2,"West, Mr. Edwy Arthur",male,36,1,2,C.A. 34651,27.75,,S 453 | 452,0,3,"Hagland, Mr. Ingvald Olai Olsen",male,,1,0,65303,19.9667,,S 454 | 453,0,1,"Foreman, Mr. Benjamin Laventall",male,30,0,0,113051,27.75,C111,C 455 | 454,1,1,"Goldenberg, Mr. Samuel L",male,49,1,0,17453,89.1042,C92,C 456 | 455,0,3,"Peduzzi, Mr. Joseph",male,,0,0,A/5 2817,8.05,,S 457 | 456,1,3,"Jalsevac, Mr. Ivan",male,29,0,0,349240,7.8958,,C 458 | 457,0,1,"Millet, Mr. Francis Davis",male,65,0,0,13509,26.55,E38,S 459 | 458,1,1,"Kenyon, Mrs. Frederick R (Marion)",female,,1,0,17464,51.8625,D21,S 460 | 459,1,2,"Toomey, Miss. Ellen",female,50,0,0,F.C.C. 13531,10.5,,S 461 | 460,0,3,"O'Connor, Mr. Maurice",male,,0,0,371060,7.75,,Q 462 | 461,1,1,"Anderson, Mr. Harry",male,48,0,0,19952,26.55,E12,S 463 | 462,0,3,"Morley, Mr. William",male,34,0,0,364506,8.05,,S 464 | 463,0,1,"Gee, Mr. Arthur H",male,47,0,0,111320,38.5,E63,S 465 | 464,0,2,"Milling, Mr. Jacob Christian",male,48,0,0,234360,13,,S 466 | 465,0,3,"Maisner, Mr. Simon",male,,0,0,A/S 2816,8.05,,S 467 | 466,0,3,"Goncalves, Mr. Manuel Estanslas",male,38,0,0,SOTON/O.Q. 3101306,7.05,,S 468 | 467,0,2,"Campbell, Mr. William",male,,0,0,239853,0,,S 469 | 468,0,1,"Smart, Mr. John Montgomery",male,56,0,0,113792,26.55,,S 470 | 469,0,3,"Scanlan, Mr. James",male,,0,0,36209,7.725,,Q 471 | 470,1,3,"Baclini, Miss. Helene Barbara",female,0.75,2,1,2666,19.2583,,C 472 | 471,0,3,"Keefe, Mr. Arthur",male,,0,0,323592,7.25,,S 473 | 472,0,3,"Cacic, Mr. Luka",male,38,0,0,315089,8.6625,,S 474 | 473,1,2,"West, Mrs. Edwy Arthur (Ada Mary Worth)",female,33,1,2,C.A. 34651,27.75,,S 475 | 474,1,2,"Jerwan, Mrs. Amin S (Marie Marthe Thuillard)",female,23,0,0,SC/AH Basle 541,13.7917,D,C 476 | 475,0,3,"Strandberg, Miss. Ida Sofia",female,22,0,0,7553,9.8375,,S 477 | 476,0,1,"Clifford, Mr. George Quincy",male,,0,0,110465,52,A14,S 478 | 477,0,2,"Renouf, Mr. Peter Henry",male,34,1,0,31027,21,,S 479 | 478,0,3,"Braund, Mr. Lewis Richard",male,29,1,0,3460,7.0458,,S 480 | 479,0,3,"Karlsson, Mr. Nils August",male,22,0,0,350060,7.5208,,S 481 | 480,1,3,"Hirvonen, Miss. Hildur E",female,2,0,1,3101298,12.2875,,S 482 | 481,0,3,"Goodwin, Master. Harold Victor",male,9,5,2,CA 2144,46.9,,S 483 | 482,0,2,"Frost, Mr. Anthony Wood ""Archie""",male,,0,0,239854,0,,S 484 | 483,0,3,"Rouse, Mr. Richard Henry",male,50,0,0,A/5 3594,8.05,,S 485 | 484,1,3,"Turkula, Mrs. (Hedwig)",female,63,0,0,4134,9.5875,,S 486 | 485,1,1,"Bishop, Mr. Dickinson H",male,25,1,0,11967,91.0792,B49,C 487 | 486,0,3,"Lefebre, Miss. Jeannie",female,,3,1,4133,25.4667,,S 488 | 487,1,1,"Hoyt, Mrs. Frederick Maxfield (Jane Anne Forby)",female,35,1,0,19943,90,C93,S 489 | 488,0,1,"Kent, Mr. Edward Austin",male,58,0,0,11771,29.7,B37,C 490 | 489,0,3,"Somerton, Mr. Francis William",male,30,0,0,A.5. 18509,8.05,,S 491 | 490,1,3,"Coutts, Master. Eden Leslie ""Neville""",male,9,1,1,C.A. 37671,15.9,,S 492 | 491,0,3,"Hagland, Mr. Konrad Mathias Reiersen",male,,1,0,65304,19.9667,,S 493 | 492,0,3,"Windelov, Mr. Einar",male,21,0,0,SOTON/OQ 3101317,7.25,,S 494 | 493,0,1,"Molson, Mr. Harry Markland",male,55,0,0,113787,30.5,C30,S 495 | 494,0,1,"Artagaveytia, Mr. Ramon",male,71,0,0,PC 17609,49.5042,,C 496 | 495,0,3,"Stanley, Mr. Edward Roland",male,21,0,0,A/4 45380,8.05,,S 497 | 496,0,3,"Yousseff, Mr. Gerious",male,,0,0,2627,14.4583,,C 498 | 497,1,1,"Eustis, Miss. Elizabeth Mussey",female,54,1,0,36947,78.2667,D20,C 499 | 498,0,3,"Shellard, Mr. Frederick William",male,,0,0,C.A. 6212,15.1,,S 500 | 499,0,1,"Allison, Mrs. Hudson J C (Bessie Waldo Daniels)",female,25,1,2,113781,151.55,C22 C26,S 501 | 500,0,3,"Svensson, Mr. Olof",male,24,0,0,350035,7.7958,,S 502 | 501,0,3,"Calic, Mr. Petar",male,17,0,0,315086,8.6625,,S 503 | 502,0,3,"Canavan, Miss. Mary",female,21,0,0,364846,7.75,,Q 504 | 503,0,3,"O'Sullivan, Miss. Bridget Mary",female,,0,0,330909,7.6292,,Q 505 | 504,0,3,"Laitinen, Miss. Kristina Sofia",female,37,0,0,4135,9.5875,,S 506 | 505,1,1,"Maioni, Miss. Roberta",female,16,0,0,110152,86.5,B79,S 507 | 506,0,1,"Penasco y Castellana, Mr. Victor de Satode",male,18,1,0,PC 17758,108.9,C65,C 508 | 507,1,2,"Quick, Mrs. Frederick Charles (Jane Richards)",female,33,0,2,26360,26,,S 509 | 508,1,1,"Bradley, Mr. George (""George Arthur Brayton"")",male,,0,0,111427,26.55,,S 510 | 509,0,3,"Olsen, Mr. Henry Margido",male,28,0,0,C 4001,22.525,,S 511 | 510,1,3,"Lang, Mr. Fang",male,26,0,0,1601,56.4958,,S 512 | 511,1,3,"Daly, Mr. Eugene Patrick",male,29,0,0,382651,7.75,,Q 513 | 512,0,3,"Webber, Mr. James",male,,0,0,SOTON/OQ 3101316,8.05,,S 514 | 513,1,1,"McGough, Mr. James Robert",male,36,0,0,PC 17473,26.2875,E25,S 515 | 514,1,1,"Rothschild, Mrs. Martin (Elizabeth L. Barrett)",female,54,1,0,PC 17603,59.4,,C 516 | 515,0,3,"Coleff, Mr. Satio",male,24,0,0,349209,7.4958,,S 517 | 516,0,1,"Walker, Mr. William Anderson",male,47,0,0,36967,34.0208,D46,S 518 | 517,1,2,"Lemore, Mrs. (Amelia Milley)",female,34,0,0,C.A. 34260,10.5,F33,S 519 | 518,0,3,"Ryan, Mr. Patrick",male,,0,0,371110,24.15,,Q 520 | 519,1,2,"Angle, Mrs. William A (Florence ""Mary"" Agnes Hughes)",female,36,1,0,226875,26,,S 521 | 520,0,3,"Pavlovic, Mr. Stefo",male,32,0,0,349242,7.8958,,S 522 | 521,1,1,"Perreault, Miss. Anne",female,30,0,0,12749,93.5,B73,S 523 | 522,0,3,"Vovk, Mr. Janko",male,22,0,0,349252,7.8958,,S 524 | 523,0,3,"Lahoud, Mr. Sarkis",male,,0,0,2624,7.225,,C 525 | 524,1,1,"Hippach, Mrs. Louis Albert (Ida Sophia Fischer)",female,44,0,1,111361,57.9792,B18,C 526 | 525,0,3,"Kassem, Mr. Fared",male,,0,0,2700,7.2292,,C 527 | 526,0,3,"Farrell, Mr. James",male,40.5,0,0,367232,7.75,,Q 528 | 527,1,2,"Ridsdale, Miss. Lucy",female,50,0,0,W./C. 14258,10.5,,S 529 | 528,0,1,"Farthing, Mr. John",male,,0,0,PC 17483,221.7792,C95,S 530 | 529,0,3,"Salonen, Mr. Johan Werner",male,39,0,0,3101296,7.925,,S 531 | 530,0,2,"Hocking, Mr. Richard George",male,23,2,1,29104,11.5,,S 532 | 531,1,2,"Quick, Miss. Phyllis May",female,2,1,1,26360,26,,S 533 | 532,0,3,"Toufik, Mr. Nakli",male,,0,0,2641,7.2292,,C 534 | 533,0,3,"Elias, Mr. Joseph Jr",male,17,1,1,2690,7.2292,,C 535 | 534,1,3,"Peter, Mrs. Catherine (Catherine Rizk)",female,,0,2,2668,22.3583,,C 536 | 535,0,3,"Cacic, Miss. Marija",female,30,0,0,315084,8.6625,,S 537 | 536,1,2,"Hart, Miss. Eva Miriam",female,7,0,2,F.C.C. 13529,26.25,,S 538 | 537,0,1,"Butt, Major. Archibald Willingham",male,45,0,0,113050,26.55,B38,S 539 | 538,1,1,"LeRoy, Miss. Bertha",female,30,0,0,PC 17761,106.425,,C 540 | 539,0,3,"Risien, Mr. Samuel Beard",male,,0,0,364498,14.5,,S 541 | 540,1,1,"Frolicher, Miss. Hedwig Margaritha",female,22,0,2,13568,49.5,B39,C 542 | 541,1,1,"Crosby, Miss. Harriet R",female,36,0,2,WE/P 5735,71,B22,S 543 | 542,0,3,"Andersson, Miss. Ingeborg Constanzia",female,9,4,2,347082,31.275,,S 544 | 543,0,3,"Andersson, Miss. Sigrid Elisabeth",female,11,4,2,347082,31.275,,S 545 | 544,1,2,"Beane, Mr. Edward",male,32,1,0,2908,26,,S 546 | 545,0,1,"Douglas, Mr. Walter Donald",male,50,1,0,PC 17761,106.425,C86,C 547 | 546,0,1,"Nicholson, Mr. Arthur Ernest",male,64,0,0,693,26,,S 548 | 547,1,2,"Beane, Mrs. Edward (Ethel Clarke)",female,19,1,0,2908,26,,S 549 | 548,1,2,"Padro y Manent, Mr. Julian",male,,0,0,SC/PARIS 2146,13.8625,,C 550 | 549,0,3,"Goldsmith, Mr. Frank John",male,33,1,1,363291,20.525,,S 551 | 550,1,2,"Davies, Master. John Morgan Jr",male,8,1,1,C.A. 33112,36.75,,S 552 | 551,1,1,"Thayer, Mr. John Borland Jr",male,17,0,2,17421,110.8833,C70,C 553 | 552,0,2,"Sharp, Mr. Percival James R",male,27,0,0,244358,26,,S 554 | 553,0,3,"O'Brien, Mr. Timothy",male,,0,0,330979,7.8292,,Q 555 | 554,1,3,"Leeni, Mr. Fahim (""Philip Zenni"")",male,22,0,0,2620,7.225,,C 556 | 555,1,3,"Ohman, Miss. Velin",female,22,0,0,347085,7.775,,S 557 | 556,0,1,"Wright, Mr. George",male,62,0,0,113807,26.55,,S 558 | 557,1,1,"Duff Gordon, Lady. (Lucille Christiana Sutherland) (""Mrs Morgan"")",female,48,1,0,11755,39.6,A16,C 559 | 558,0,1,"Robbins, Mr. Victor",male,,0,0,PC 17757,227.525,,C 560 | 559,1,1,"Taussig, Mrs. Emil (Tillie Mandelbaum)",female,39,1,1,110413,79.65,E67,S 561 | 560,1,3,"de Messemaeker, Mrs. Guillaume Joseph (Emma)",female,36,1,0,345572,17.4,,S 562 | 561,0,3,"Morrow, Mr. Thomas Rowan",male,,0,0,372622,7.75,,Q 563 | 562,0,3,"Sivic, Mr. Husein",male,40,0,0,349251,7.8958,,S 564 | 563,0,2,"Norman, Mr. Robert Douglas",male,28,0,0,218629,13.5,,S 565 | 564,0,3,"Simmons, Mr. John",male,,0,0,SOTON/OQ 392082,8.05,,S 566 | 565,0,3,"Meanwell, Miss. (Marion Ogden)",female,,0,0,SOTON/O.Q. 392087,8.05,,S 567 | 566,0,3,"Davies, Mr. Alfred J",male,24,2,0,A/4 48871,24.15,,S 568 | 567,0,3,"Stoytcheff, Mr. Ilia",male,19,0,0,349205,7.8958,,S 569 | 568,0,3,"Palsson, Mrs. Nils (Alma Cornelia Berglund)",female,29,0,4,349909,21.075,,S 570 | 569,0,3,"Doharr, Mr. Tannous",male,,0,0,2686,7.2292,,C 571 | 570,1,3,"Jonsson, Mr. Carl",male,32,0,0,350417,7.8542,,S 572 | 571,1,2,"Harris, Mr. George",male,62,0,0,S.W./PP 752,10.5,,S 573 | 572,1,1,"Appleton, Mrs. Edward Dale (Charlotte Lamson)",female,53,2,0,11769,51.4792,C101,S 574 | 573,1,1,"Flynn, Mr. John Irwin (""Irving"")",male,36,0,0,PC 17474,26.3875,E25,S 575 | 574,1,3,"Kelly, Miss. Mary",female,,0,0,14312,7.75,,Q 576 | 575,0,3,"Rush, Mr. Alfred George John",male,16,0,0,A/4. 20589,8.05,,S 577 | 576,0,3,"Patchett, Mr. George",male,19,0,0,358585,14.5,,S 578 | 577,1,2,"Garside, Miss. Ethel",female,34,0,0,243880,13,,S 579 | 578,1,1,"Silvey, Mrs. William Baird (Alice Munger)",female,39,1,0,13507,55.9,E44,S 580 | 579,0,3,"Caram, Mrs. Joseph (Maria Elias)",female,,1,0,2689,14.4583,,C 581 | 580,1,3,"Jussila, Mr. Eiriik",male,32,0,0,STON/O 2. 3101286,7.925,,S 582 | 581,1,2,"Christy, Miss. Julie Rachel",female,25,1,1,237789,30,,S 583 | 582,1,1,"Thayer, Mrs. John Borland (Marian Longstreth Morris)",female,39,1,1,17421,110.8833,C68,C 584 | 583,0,2,"Downton, Mr. William James",male,54,0,0,28403,26,,S 585 | 584,0,1,"Ross, Mr. John Hugo",male,36,0,0,13049,40.125,A10,C 586 | 585,0,3,"Paulner, Mr. Uscher",male,,0,0,3411,8.7125,,C 587 | 586,1,1,"Taussig, Miss. Ruth",female,18,0,2,110413,79.65,E68,S 588 | 587,0,2,"Jarvis, Mr. John Denzil",male,47,0,0,237565,15,,S 589 | 588,1,1,"Frolicher-Stehli, Mr. Maxmillian",male,60,1,1,13567,79.2,B41,C 590 | 589,0,3,"Gilinski, Mr. Eliezer",male,22,0,0,14973,8.05,,S 591 | 590,0,3,"Murdlin, Mr. Joseph",male,,0,0,A./5. 3235,8.05,,S 592 | 591,0,3,"Rintamaki, Mr. Matti",male,35,0,0,STON/O 2. 3101273,7.125,,S 593 | 592,1,1,"Stephenson, Mrs. Walter Bertram (Martha Eustis)",female,52,1,0,36947,78.2667,D20,C 594 | 593,0,3,"Elsbury, Mr. William James",male,47,0,0,A/5 3902,7.25,,S 595 | 594,0,3,"Bourke, Miss. Mary",female,,0,2,364848,7.75,,Q 596 | 595,0,2,"Chapman, Mr. John Henry",male,37,1,0,SC/AH 29037,26,,S 597 | 596,0,3,"Van Impe, Mr. Jean Baptiste",male,36,1,1,345773,24.15,,S 598 | 597,1,2,"Leitch, Miss. Jessie Wills",female,,0,0,248727,33,,S 599 | 598,0,3,"Johnson, Mr. Alfred",male,49,0,0,LINE,0,,S 600 | 599,0,3,"Boulos, Mr. Hanna",male,,0,0,2664,7.225,,C 601 | 600,1,1,"Duff Gordon, Sir. Cosmo Edmund (""Mr Morgan"")",male,49,1,0,PC 17485,56.9292,A20,C 602 | 601,1,2,"Jacobsohn, Mrs. Sidney Samuel (Amy Frances Christy)",female,24,2,1,243847,27,,S 603 | 602,0,3,"Slabenoff, Mr. Petco",male,,0,0,349214,7.8958,,S 604 | 603,0,1,"Harrington, Mr. Charles H",male,,0,0,113796,42.4,,S 605 | 604,0,3,"Torber, Mr. Ernst William",male,44,0,0,364511,8.05,,S 606 | 605,1,1,"Homer, Mr. Harry (""Mr E Haven"")",male,35,0,0,111426,26.55,,C 607 | 606,0,3,"Lindell, Mr. Edvard Bengtsson",male,36,1,0,349910,15.55,,S 608 | 607,0,3,"Karaic, Mr. Milan",male,30,0,0,349246,7.8958,,S 609 | 608,1,1,"Daniel, Mr. Robert Williams",male,27,0,0,113804,30.5,,S 610 | 609,1,2,"Laroche, Mrs. Joseph (Juliette Marie Louise Lafargue)",female,22,1,2,SC/Paris 2123,41.5792,,C 611 | 610,1,1,"Shutes, Miss. Elizabeth W",female,40,0,0,PC 17582,153.4625,C125,S 612 | 611,0,3,"Andersson, Mrs. Anders Johan (Alfrida Konstantia Brogren)",female,39,1,5,347082,31.275,,S 613 | 612,0,3,"Jardin, Mr. Jose Neto",male,,0,0,SOTON/O.Q. 3101305,7.05,,S 614 | 613,1,3,"Murphy, Miss. Margaret Jane",female,,1,0,367230,15.5,,Q 615 | 614,0,3,"Horgan, Mr. John",male,,0,0,370377,7.75,,Q 616 | 615,0,3,"Brocklebank, Mr. William Alfred",male,35,0,0,364512,8.05,,S 617 | 616,1,2,"Herman, Miss. Alice",female,24,1,2,220845,65,,S 618 | 617,0,3,"Danbom, Mr. Ernst Gilbert",male,34,1,1,347080,14.4,,S 619 | 618,0,3,"Lobb, Mrs. William Arthur (Cordelia K Stanlick)",female,26,1,0,A/5. 3336,16.1,,S 620 | 619,1,2,"Becker, Miss. Marion Louise",female,4,2,1,230136,39,F4,S 621 | 620,0,2,"Gavey, Mr. Lawrence",male,26,0,0,31028,10.5,,S 622 | 621,0,3,"Yasbeck, Mr. Antoni",male,27,1,0,2659,14.4542,,C 623 | 622,1,1,"Kimball, Mr. Edwin Nelson Jr",male,42,1,0,11753,52.5542,D19,S 624 | 623,1,3,"Nakid, Mr. Sahid",male,20,1,1,2653,15.7417,,C 625 | 624,0,3,"Hansen, Mr. Henry Damsgaard",male,21,0,0,350029,7.8542,,S 626 | 625,0,3,"Bowen, Mr. David John ""Dai""",male,21,0,0,54636,16.1,,S 627 | 626,0,1,"Sutton, Mr. Frederick",male,61,0,0,36963,32.3208,D50,S 628 | 627,0,2,"Kirkland, Rev. Charles Leonard",male,57,0,0,219533,12.35,,Q 629 | 628,1,1,"Longley, Miss. Gretchen Fiske",female,21,0,0,13502,77.9583,D9,S 630 | 629,0,3,"Bostandyeff, Mr. Guentcho",male,26,0,0,349224,7.8958,,S 631 | 630,0,3,"O'Connell, Mr. Patrick D",male,,0,0,334912,7.7333,,Q 632 | 631,1,1,"Barkworth, Mr. Algernon Henry Wilson",male,80,0,0,27042,30,A23,S 633 | 632,0,3,"Lundahl, Mr. Johan Svensson",male,51,0,0,347743,7.0542,,S 634 | 633,1,1,"Stahelin-Maeglin, Dr. Max",male,32,0,0,13214,30.5,B50,C 635 | 634,0,1,"Parr, Mr. William Henry Marsh",male,,0,0,112052,0,,S 636 | 635,0,3,"Skoog, Miss. Mabel",female,9,3,2,347088,27.9,,S 637 | 636,1,2,"Davis, Miss. Mary",female,28,0,0,237668,13,,S 638 | 637,0,3,"Leinonen, Mr. Antti Gustaf",male,32,0,0,STON/O 2. 3101292,7.925,,S 639 | 638,0,2,"Collyer, Mr. Harvey",male,31,1,1,C.A. 31921,26.25,,S 640 | 639,0,3,"Panula, Mrs. Juha (Maria Emilia Ojala)",female,41,0,5,3101295,39.6875,,S 641 | 640,0,3,"Thorneycroft, Mr. Percival",male,,1,0,376564,16.1,,S 642 | 641,0,3,"Jensen, Mr. Hans Peder",male,20,0,0,350050,7.8542,,S 643 | 642,1,1,"Sagesser, Mlle. Emma",female,24,0,0,PC 17477,69.3,B35,C 644 | 643,0,3,"Skoog, Miss. Margit Elizabeth",female,2,3,2,347088,27.9,,S 645 | 644,1,3,"Foo, Mr. Choong",male,,0,0,1601,56.4958,,S 646 | 645,1,3,"Baclini, Miss. Eugenie",female,0.75,2,1,2666,19.2583,,C 647 | 646,1,1,"Harper, Mr. Henry Sleeper",male,48,1,0,PC 17572,76.7292,D33,C 648 | 647,0,3,"Cor, Mr. Liudevit",male,19,0,0,349231,7.8958,,S 649 | 648,1,1,"Simonius-Blumer, Col. Oberst Alfons",male,56,0,0,13213,35.5,A26,C 650 | 649,0,3,"Willey, Mr. Edward",male,,0,0,S.O./P.P. 751,7.55,,S 651 | 650,1,3,"Stanley, Miss. Amy Zillah Elsie",female,23,0,0,CA. 2314,7.55,,S 652 | 651,0,3,"Mitkoff, Mr. Mito",male,,0,0,349221,7.8958,,S 653 | 652,1,2,"Doling, Miss. Elsie",female,18,0,1,231919,23,,S 654 | 653,0,3,"Kalvik, Mr. Johannes Halvorsen",male,21,0,0,8475,8.4333,,S 655 | 654,1,3,"O'Leary, Miss. Hanora ""Norah""",female,,0,0,330919,7.8292,,Q 656 | 655,0,3,"Hegarty, Miss. Hanora ""Nora""",female,18,0,0,365226,6.75,,Q 657 | 656,0,2,"Hickman, Mr. Leonard Mark",male,24,2,0,S.O.C. 14879,73.5,,S 658 | 657,0,3,"Radeff, Mr. Alexander",male,,0,0,349223,7.8958,,S 659 | 658,0,3,"Bourke, Mrs. John (Catherine)",female,32,1,1,364849,15.5,,Q 660 | 659,0,2,"Eitemiller, Mr. George Floyd",male,23,0,0,29751,13,,S 661 | 660,0,1,"Newell, Mr. Arthur Webster",male,58,0,2,35273,113.275,D48,C 662 | 661,1,1,"Frauenthal, Dr. Henry William",male,50,2,0,PC 17611,133.65,,S 663 | 662,0,3,"Badt, Mr. Mohamed",male,40,0,0,2623,7.225,,C 664 | 663,0,1,"Colley, Mr. Edward Pomeroy",male,47,0,0,5727,25.5875,E58,S 665 | 664,0,3,"Coleff, Mr. Peju",male,36,0,0,349210,7.4958,,S 666 | 665,1,3,"Lindqvist, Mr. Eino William",male,20,1,0,STON/O 2. 3101285,7.925,,S 667 | 666,0,2,"Hickman, Mr. Lewis",male,32,2,0,S.O.C. 14879,73.5,,S 668 | 667,0,2,"Butler, Mr. Reginald Fenton",male,25,0,0,234686,13,,S 669 | 668,0,3,"Rommetvedt, Mr. Knud Paust",male,,0,0,312993,7.775,,S 670 | 669,0,3,"Cook, Mr. Jacob",male,43,0,0,A/5 3536,8.05,,S 671 | 670,1,1,"Taylor, Mrs. Elmer Zebley (Juliet Cummins Wright)",female,,1,0,19996,52,C126,S 672 | 671,1,2,"Brown, Mrs. Thomas William Solomon (Elizabeth Catherine Ford)",female,40,1,1,29750,39,,S 673 | 672,0,1,"Davidson, Mr. Thornton",male,31,1,0,F.C. 12750,52,B71,S 674 | 673,0,2,"Mitchell, Mr. Henry Michael",male,70,0,0,C.A. 24580,10.5,,S 675 | 674,1,2,"Wilhelms, Mr. Charles",male,31,0,0,244270,13,,S 676 | 675,0,2,"Watson, Mr. Ennis Hastings",male,,0,0,239856,0,,S 677 | 676,0,3,"Edvardsson, Mr. Gustaf Hjalmar",male,18,0,0,349912,7.775,,S 678 | 677,0,3,"Sawyer, Mr. Frederick Charles",male,24.5,0,0,342826,8.05,,S 679 | 678,1,3,"Turja, Miss. Anna Sofia",female,18,0,0,4138,9.8417,,S 680 | 679,0,3,"Goodwin, Mrs. Frederick (Augusta Tyler)",female,43,1,6,CA 2144,46.9,,S 681 | 680,1,1,"Cardeza, Mr. Thomas Drake Martinez",male,36,0,1,PC 17755,512.3292,B51 B53 B55,C 682 | 681,0,3,"Peters, Miss. Katie",female,,0,0,330935,8.1375,,Q 683 | 682,1,1,"Hassab, Mr. Hammad",male,27,0,0,PC 17572,76.7292,D49,C 684 | 683,0,3,"Olsvigen, Mr. Thor Anderson",male,20,0,0,6563,9.225,,S 685 | 684,0,3,"Goodwin, Mr. Charles Edward",male,14,5,2,CA 2144,46.9,,S 686 | 685,0,2,"Brown, Mr. Thomas William Solomon",male,60,1,1,29750,39,,S 687 | 686,0,2,"Laroche, Mr. Joseph Philippe Lemercier",male,25,1,2,SC/Paris 2123,41.5792,,C 688 | 687,0,3,"Panula, Mr. Jaako Arnold",male,14,4,1,3101295,39.6875,,S 689 | 688,0,3,"Dakic, Mr. Branko",male,19,0,0,349228,10.1708,,S 690 | 689,0,3,"Fischer, Mr. Eberhard Thelander",male,18,0,0,350036,7.7958,,S 691 | 690,1,1,"Madill, Miss. Georgette Alexandra",female,15,0,1,24160,211.3375,B5,S 692 | 691,1,1,"Dick, Mr. Albert Adrian",male,31,1,0,17474,57,B20,S 693 | 692,1,3,"Karun, Miss. Manca",female,4,0,1,349256,13.4167,,C 694 | 693,1,3,"Lam, Mr. Ali",male,,0,0,1601,56.4958,,S 695 | 694,0,3,"Saad, Mr. Khalil",male,25,0,0,2672,7.225,,C 696 | 695,0,1,"Weir, Col. John",male,60,0,0,113800,26.55,,S 697 | 696,0,2,"Chapman, Mr. Charles Henry",male,52,0,0,248731,13.5,,S 698 | 697,0,3,"Kelly, Mr. James",male,44,0,0,363592,8.05,,S 699 | 698,1,3,"Mullens, Miss. Katherine ""Katie""",female,,0,0,35852,7.7333,,Q 700 | 699,0,1,"Thayer, Mr. John Borland",male,49,1,1,17421,110.8833,C68,C 701 | 700,0,3,"Humblen, Mr. Adolf Mathias Nicolai Olsen",male,42,0,0,348121,7.65,F G63,S 702 | 701,1,1,"Astor, Mrs. John Jacob (Madeleine Talmadge Force)",female,18,1,0,PC 17757,227.525,C62 C64,C 703 | 702,1,1,"Silverthorne, Mr. Spencer Victor",male,35,0,0,PC 17475,26.2875,E24,S 704 | 703,0,3,"Barbara, Miss. Saiide",female,18,0,1,2691,14.4542,,C 705 | 704,0,3,"Gallagher, Mr. Martin",male,25,0,0,36864,7.7417,,Q 706 | 705,0,3,"Hansen, Mr. Henrik Juul",male,26,1,0,350025,7.8542,,S 707 | 706,0,2,"Morley, Mr. Henry Samuel (""Mr Henry Marshall"")",male,39,0,0,250655,26,,S 708 | 707,1,2,"Kelly, Mrs. Florence ""Fannie""",female,45,0,0,223596,13.5,,S 709 | 708,1,1,"Calderhead, Mr. Edward Pennington",male,42,0,0,PC 17476,26.2875,E24,S 710 | 709,1,1,"Cleaver, Miss. Alice",female,22,0,0,113781,151.55,,S 711 | 710,1,3,"Moubarek, Master. Halim Gonios (""William George"")",male,,1,1,2661,15.2458,,C 712 | 711,1,1,"Mayne, Mlle. Berthe Antonine (""Mrs de Villiers"")",female,24,0,0,PC 17482,49.5042,C90,C 713 | 712,0,1,"Klaber, Mr. Herman",male,,0,0,113028,26.55,C124,S 714 | 713,1,1,"Taylor, Mr. Elmer Zebley",male,48,1,0,19996,52,C126,S 715 | 714,0,3,"Larsson, Mr. August Viktor",male,29,0,0,7545,9.4833,,S 716 | 715,0,2,"Greenberg, Mr. Samuel",male,52,0,0,250647,13,,S 717 | 716,0,3,"Soholt, Mr. Peter Andreas Lauritz Andersen",male,19,0,0,348124,7.65,F G73,S 718 | 717,1,1,"Endres, Miss. Caroline Louise",female,38,0,0,PC 17757,227.525,C45,C 719 | 718,1,2,"Troutt, Miss. Edwina Celia ""Winnie""",female,27,0,0,34218,10.5,E101,S 720 | 719,0,3,"McEvoy, Mr. Michael",male,,0,0,36568,15.5,,Q 721 | 720,0,3,"Johnson, Mr. Malkolm Joackim",male,33,0,0,347062,7.775,,S 722 | 721,1,2,"Harper, Miss. Annie Jessie ""Nina""",female,6,0,1,248727,33,,S 723 | 722,0,3,"Jensen, Mr. Svend Lauritz",male,17,1,0,350048,7.0542,,S 724 | 723,0,2,"Gillespie, Mr. William Henry",male,34,0,0,12233,13,,S 725 | 724,0,2,"Hodges, Mr. Henry Price",male,50,0,0,250643,13,,S 726 | 725,1,1,"Chambers, Mr. Norman Campbell",male,27,1,0,113806,53.1,E8,S 727 | 726,0,3,"Oreskovic, Mr. Luka",male,20,0,0,315094,8.6625,,S 728 | 727,1,2,"Renouf, Mrs. Peter Henry (Lillian Jefferys)",female,30,3,0,31027,21,,S 729 | 728,1,3,"Mannion, Miss. Margareth",female,,0,0,36866,7.7375,,Q 730 | 729,0,2,"Bryhl, Mr. Kurt Arnold Gottfrid",male,25,1,0,236853,26,,S 731 | 730,0,3,"Ilmakangas, Miss. Pieta Sofia",female,25,1,0,STON/O2. 3101271,7.925,,S 732 | 731,1,1,"Allen, Miss. Elisabeth Walton",female,29,0,0,24160,211.3375,B5,S 733 | 732,0,3,"Hassan, Mr. Houssein G N",male,11,0,0,2699,18.7875,,C 734 | 733,0,2,"Knight, Mr. Robert J",male,,0,0,239855,0,,S 735 | 734,0,2,"Berriman, Mr. William John",male,23,0,0,28425,13,,S 736 | 735,0,2,"Troupiansky, Mr. Moses Aaron",male,23,0,0,233639,13,,S 737 | 736,0,3,"Williams, Mr. Leslie",male,28.5,0,0,54636,16.1,,S 738 | 737,0,3,"Ford, Mrs. Edward (Margaret Ann Watson)",female,48,1,3,W./C. 6608,34.375,,S 739 | 738,1,1,"Lesurer, Mr. Gustave J",male,35,0,0,PC 17755,512.3292,B101,C 740 | 739,0,3,"Ivanoff, Mr. Kanio",male,,0,0,349201,7.8958,,S 741 | 740,0,3,"Nankoff, Mr. Minko",male,,0,0,349218,7.8958,,S 742 | 741,1,1,"Hawksford, Mr. Walter James",male,,0,0,16988,30,D45,S 743 | 742,0,1,"Cavendish, Mr. Tyrell William",male,36,1,0,19877,78.85,C46,S 744 | 743,1,1,"Ryerson, Miss. Susan Parker ""Suzette""",female,21,2,2,PC 17608,262.375,B57 B59 B63 B66,C 745 | 744,0,3,"McNamee, Mr. Neal",male,24,1,0,376566,16.1,,S 746 | 745,1,3,"Stranden, Mr. Juho",male,31,0,0,STON/O 2. 3101288,7.925,,S 747 | 746,0,1,"Crosby, Capt. Edward Gifford",male,70,1,1,WE/P 5735,71,B22,S 748 | 747,0,3,"Abbott, Mr. Rossmore Edward",male,16,1,1,C.A. 2673,20.25,,S 749 | 748,1,2,"Sinkkonen, Miss. Anna",female,30,0,0,250648,13,,S 750 | 749,0,1,"Marvin, Mr. Daniel Warner",male,19,1,0,113773,53.1,D30,S 751 | 750,0,3,"Connaghton, Mr. Michael",male,31,0,0,335097,7.75,,Q 752 | 751,1,2,"Wells, Miss. Joan",female,4,1,1,29103,23,,S 753 | 752,1,3,"Moor, Master. Meier",male,6,0,1,392096,12.475,E121,S 754 | 753,0,3,"Vande Velde, Mr. Johannes Joseph",male,33,0,0,345780,9.5,,S 755 | 754,0,3,"Jonkoff, Mr. Lalio",male,23,0,0,349204,7.8958,,S 756 | 755,1,2,"Herman, Mrs. Samuel (Jane Laver)",female,48,1,2,220845,65,,S 757 | 756,1,2,"Hamalainen, Master. Viljo",male,0.67,1,1,250649,14.5,,S 758 | 757,0,3,"Carlsson, Mr. August Sigfrid",male,28,0,0,350042,7.7958,,S 759 | 758,0,2,"Bailey, Mr. Percy Andrew",male,18,0,0,29108,11.5,,S 760 | 759,0,3,"Theobald, Mr. Thomas Leonard",male,34,0,0,363294,8.05,,S 761 | 760,1,1,"Rothes, the Countess. of (Lucy Noel Martha Dyer-Edwards)",female,33,0,0,110152,86.5,B77,S 762 | 761,0,3,"Garfirth, Mr. John",male,,0,0,358585,14.5,,S 763 | 762,0,3,"Nirva, Mr. Iisakki Antino Aijo",male,41,0,0,SOTON/O2 3101272,7.125,,S 764 | 763,1,3,"Barah, Mr. Hanna Assi",male,20,0,0,2663,7.2292,,C 765 | 764,1,1,"Carter, Mrs. William Ernest (Lucile Polk)",female,36,1,2,113760,120,B96 B98,S 766 | 765,0,3,"Eklund, Mr. Hans Linus",male,16,0,0,347074,7.775,,S 767 | 766,1,1,"Hogeboom, Mrs. John C (Anna Andrews)",female,51,1,0,13502,77.9583,D11,S 768 | 767,0,1,"Brewe, Dr. Arthur Jackson",male,,0,0,112379,39.6,,C 769 | 768,0,3,"Mangan, Miss. Mary",female,30.5,0,0,364850,7.75,,Q 770 | 769,0,3,"Moran, Mr. Daniel J",male,,1,0,371110,24.15,,Q 771 | 770,0,3,"Gronnestad, Mr. Daniel Danielsen",male,32,0,0,8471,8.3625,,S 772 | 771,0,3,"Lievens, Mr. Rene Aime",male,24,0,0,345781,9.5,,S 773 | 772,0,3,"Jensen, Mr. Niels Peder",male,48,0,0,350047,7.8542,,S 774 | 773,0,2,"Mack, Mrs. (Mary)",female,57,0,0,S.O./P.P. 3,10.5,E77,S 775 | 774,0,3,"Elias, Mr. Dibo",male,,0,0,2674,7.225,,C 776 | 775,1,2,"Hocking, Mrs. Elizabeth (Eliza Needs)",female,54,1,3,29105,23,,S 777 | 776,0,3,"Myhrman, Mr. Pehr Fabian Oliver Malkolm",male,18,0,0,347078,7.75,,S 778 | 777,0,3,"Tobin, Mr. Roger",male,,0,0,383121,7.75,F38,Q 779 | 778,1,3,"Emanuel, Miss. Virginia Ethel",female,5,0,0,364516,12.475,,S 780 | 779,0,3,"Kilgannon, Mr. Thomas J",male,,0,0,36865,7.7375,,Q 781 | 780,1,1,"Robert, Mrs. Edward Scott (Elisabeth Walton McMillan)",female,43,0,1,24160,211.3375,B3,S 782 | 781,1,3,"Ayoub, Miss. Banoura",female,13,0,0,2687,7.2292,,C 783 | 782,1,1,"Dick, Mrs. Albert Adrian (Vera Gillespie)",female,17,1,0,17474,57,B20,S 784 | 783,0,1,"Long, Mr. Milton Clyde",male,29,0,0,113501,30,D6,S 785 | 784,0,3,"Johnston, Mr. Andrew G",male,,1,2,W./C. 6607,23.45,,S 786 | 785,0,3,"Ali, Mr. William",male,25,0,0,SOTON/O.Q. 3101312,7.05,,S 787 | 786,0,3,"Harmer, Mr. Abraham (David Lishin)",male,25,0,0,374887,7.25,,S 788 | 787,1,3,"Sjoblom, Miss. Anna Sofia",female,18,0,0,3101265,7.4958,,S 789 | 788,0,3,"Rice, Master. George Hugh",male,8,4,1,382652,29.125,,Q 790 | 789,1,3,"Dean, Master. Bertram Vere",male,1,1,2,C.A. 2315,20.575,,S 791 | 790,0,1,"Guggenheim, Mr. Benjamin",male,46,0,0,PC 17593,79.2,B82 B84,C 792 | 791,0,3,"Keane, Mr. Andrew ""Andy""",male,,0,0,12460,7.75,,Q 793 | 792,0,2,"Gaskell, Mr. Alfred",male,16,0,0,239865,26,,S 794 | 793,0,3,"Sage, Miss. Stella Anna",female,,8,2,CA. 2343,69.55,,S 795 | 794,0,1,"Hoyt, Mr. William Fisher",male,,0,0,PC 17600,30.6958,,C 796 | 795,0,3,"Dantcheff, Mr. Ristiu",male,25,0,0,349203,7.8958,,S 797 | 796,0,2,"Otter, Mr. Richard",male,39,0,0,28213,13,,S 798 | 797,1,1,"Leader, Dr. Alice (Farnham)",female,49,0,0,17465,25.9292,D17,S 799 | 798,1,3,"Osman, Mrs. Mara",female,31,0,0,349244,8.6833,,S 800 | 799,0,3,"Ibrahim Shawah, Mr. Yousseff",male,30,0,0,2685,7.2292,,C 801 | 800,0,3,"Van Impe, Mrs. Jean Baptiste (Rosalie Paula Govaert)",female,30,1,1,345773,24.15,,S 802 | 801,0,2,"Ponesell, Mr. Martin",male,34,0,0,250647,13,,S 803 | 802,1,2,"Collyer, Mrs. Harvey (Charlotte Annie Tate)",female,31,1,1,C.A. 31921,26.25,,S 804 | 803,1,1,"Carter, Master. William Thornton II",male,11,1,2,113760,120,B96 B98,S 805 | 804,1,3,"Thomas, Master. Assad Alexander",male,0.42,0,1,2625,8.5167,,C 806 | 805,1,3,"Hedman, Mr. Oskar Arvid",male,27,0,0,347089,6.975,,S 807 | 806,0,3,"Johansson, Mr. Karl Johan",male,31,0,0,347063,7.775,,S 808 | 807,0,1,"Andrews, Mr. Thomas Jr",male,39,0,0,112050,0,A36,S 809 | 808,0,3,"Pettersson, Miss. Ellen Natalia",female,18,0,0,347087,7.775,,S 810 | 809,0,2,"Meyer, Mr. August",male,39,0,0,248723,13,,S 811 | 810,1,1,"Chambers, Mrs. Norman Campbell (Bertha Griggs)",female,33,1,0,113806,53.1,E8,S 812 | 811,0,3,"Alexander, Mr. William",male,26,0,0,3474,7.8875,,S 813 | 812,0,3,"Lester, Mr. James",male,39,0,0,A/4 48871,24.15,,S 814 | 813,0,2,"Slemen, Mr. Richard James",male,35,0,0,28206,10.5,,S 815 | 814,0,3,"Andersson, Miss. Ebba Iris Alfrida",female,6,4,2,347082,31.275,,S 816 | 815,0,3,"Tomlin, Mr. Ernest Portage",male,30.5,0,0,364499,8.05,,S 817 | 816,0,1,"Fry, Mr. Richard",male,,0,0,112058,0,B102,S 818 | 817,0,3,"Heininen, Miss. Wendla Maria",female,23,0,0,STON/O2. 3101290,7.925,,S 819 | 818,0,2,"Mallet, Mr. Albert",male,31,1,1,S.C./PARIS 2079,37.0042,,C 820 | 819,0,3,"Holm, Mr. John Fredrik Alexander",male,43,0,0,C 7075,6.45,,S 821 | 820,0,3,"Skoog, Master. Karl Thorsten",male,10,3,2,347088,27.9,,S 822 | 821,1,1,"Hays, Mrs. Charles Melville (Clara Jennings Gregg)",female,52,1,1,12749,93.5,B69,S 823 | 822,1,3,"Lulic, Mr. Nikola",male,27,0,0,315098,8.6625,,S 824 | 823,0,1,"Reuchlin, Jonkheer. John George",male,38,0,0,19972,0,,S 825 | 824,1,3,"Moor, Mrs. (Beila)",female,27,0,1,392096,12.475,E121,S 826 | 825,0,3,"Panula, Master. Urho Abraham",male,2,4,1,3101295,39.6875,,S 827 | 826,0,3,"Flynn, Mr. John",male,,0,0,368323,6.95,,Q 828 | 827,0,3,"Lam, Mr. Len",male,,0,0,1601,56.4958,,S 829 | 828,1,2,"Mallet, Master. Andre",male,1,0,2,S.C./PARIS 2079,37.0042,,C 830 | 829,1,3,"McCormack, Mr. Thomas Joseph",male,,0,0,367228,7.75,,Q 831 | 830,1,1,"Stone, Mrs. George Nelson (Martha Evelyn)",female,62,0,0,113572,80,B28, 832 | 831,1,3,"Yasbeck, Mrs. Antoni (Selini Alexander)",female,15,1,0,2659,14.4542,,C 833 | 832,1,2,"Richards, Master. George Sibley",male,0.83,1,1,29106,18.75,,S 834 | 833,0,3,"Saad, Mr. Amin",male,,0,0,2671,7.2292,,C 835 | 834,0,3,"Augustsson, Mr. Albert",male,23,0,0,347468,7.8542,,S 836 | 835,0,3,"Allum, Mr. Owen George",male,18,0,0,2223,8.3,,S 837 | 836,1,1,"Compton, Miss. Sara Rebecca",female,39,1,1,PC 17756,83.1583,E49,C 838 | 837,0,3,"Pasic, Mr. Jakob",male,21,0,0,315097,8.6625,,S 839 | 838,0,3,"Sirota, Mr. Maurice",male,,0,0,392092,8.05,,S 840 | 839,1,3,"Chip, Mr. Chang",male,32,0,0,1601,56.4958,,S 841 | 840,1,1,"Marechal, Mr. Pierre",male,,0,0,11774,29.7,C47,C 842 | 841,0,3,"Alhomaki, Mr. Ilmari Rudolf",male,20,0,0,SOTON/O2 3101287,7.925,,S 843 | 842,0,2,"Mudd, Mr. Thomas Charles",male,16,0,0,S.O./P.P. 3,10.5,,S 844 | 843,1,1,"Serepeca, Miss. Augusta",female,30,0,0,113798,31,,C 845 | 844,0,3,"Lemberopolous, Mr. Peter L",male,34.5,0,0,2683,6.4375,,C 846 | 845,0,3,"Culumovic, Mr. Jeso",male,17,0,0,315090,8.6625,,S 847 | 846,0,3,"Abbing, Mr. Anthony",male,42,0,0,C.A. 5547,7.55,,S 848 | 847,0,3,"Sage, Mr. Douglas Bullen",male,,8,2,CA. 2343,69.55,,S 849 | 848,0,3,"Markoff, Mr. Marin",male,35,0,0,349213,7.8958,,C 850 | 849,0,2,"Harper, Rev. John",male,28,0,1,248727,33,,S 851 | 850,1,1,"Goldenberg, Mrs. Samuel L (Edwiga Grabowska)",female,,1,0,17453,89.1042,C92,C 852 | 851,0,3,"Andersson, Master. Sigvard Harald Elias",male,4,4,2,347082,31.275,,S 853 | 852,0,3,"Svensson, Mr. Johan",male,74,0,0,347060,7.775,,S 854 | 853,0,3,"Boulos, Miss. Nourelain",female,9,1,1,2678,15.2458,,C 855 | 854,1,1,"Lines, Miss. Mary Conover",female,16,0,1,PC 17592,39.4,D28,S 856 | 855,0,2,"Carter, Mrs. Ernest Courtenay (Lilian Hughes)",female,44,1,0,244252,26,,S 857 | 856,1,3,"Aks, Mrs. Sam (Leah Rosen)",female,18,0,1,392091,9.35,,S 858 | 857,1,1,"Wick, Mrs. George Dennick (Mary Hitchcock)",female,45,1,1,36928,164.8667,,S 859 | 858,1,1,"Daly, Mr. Peter Denis ",male,51,0,0,113055,26.55,E17,S 860 | 859,1,3,"Baclini, Mrs. Solomon (Latifa Qurban)",female,24,0,3,2666,19.2583,,C 861 | 860,0,3,"Razi, Mr. Raihed",male,,0,0,2629,7.2292,,C 862 | 861,0,3,"Hansen, Mr. Claus Peter",male,41,2,0,350026,14.1083,,S 863 | 862,0,2,"Giles, Mr. Frederick Edward",male,21,1,0,28134,11.5,,S 864 | 863,1,1,"Swift, Mrs. Frederick Joel (Margaret Welles Barron)",female,48,0,0,17466,25.9292,D17,S 865 | 864,0,3,"Sage, Miss. Dorothy Edith ""Dolly""",female,,8,2,CA. 2343,69.55,,S 866 | 865,0,2,"Gill, Mr. John William",male,24,0,0,233866,13,,S 867 | 866,1,2,"Bystrom, Mrs. (Karolina)",female,42,0,0,236852,13,,S 868 | 867,1,2,"Duran y More, Miss. Asuncion",female,27,1,0,SC/PARIS 2149,13.8583,,C 869 | 868,0,1,"Roebling, Mr. Washington Augustus II",male,31,0,0,PC 17590,50.4958,A24,S 870 | 869,0,3,"van Melkebeke, Mr. Philemon",male,,0,0,345777,9.5,,S 871 | 870,1,3,"Johnson, Master. Harold Theodor",male,4,1,1,347742,11.1333,,S 872 | 871,0,3,"Balkic, Mr. Cerin",male,26,0,0,349248,7.8958,,S 873 | 872,1,1,"Beckwith, Mrs. Richard Leonard (Sallie Monypeny)",female,47,1,1,11751,52.5542,D35,S 874 | 873,0,1,"Carlsson, Mr. Frans Olof",male,33,0,0,695,5,B51 B53 B55,S 875 | 874,0,3,"Vander Cruyssen, Mr. Victor",male,47,0,0,345765,9,,S 876 | 875,1,2,"Abelson, Mrs. Samuel (Hannah Wizosky)",female,28,1,0,P/PP 3381,24,,C 877 | 876,1,3,"Najib, Miss. Adele Kiamie ""Jane""",female,15,0,0,2667,7.225,,C 878 | 877,0,3,"Gustafsson, Mr. Alfred Ossian",male,20,0,0,7534,9.8458,,S 879 | 878,0,3,"Petroff, Mr. Nedelio",male,19,0,0,349212,7.8958,,S 880 | 879,0,3,"Laleff, Mr. Kristo",male,,0,0,349217,7.8958,,S 881 | 880,1,1,"Potter, Mrs. Thomas Jr (Lily Alexenia Wilson)",female,56,0,1,11767,83.1583,C50,C 882 | 881,1,2,"Shelley, Mrs. William (Imanita Parrish Hall)",female,25,0,1,230433,26,,S 883 | 882,0,3,"Markun, Mr. Johann",male,33,0,0,349257,7.8958,,S 884 | 883,0,3,"Dahlberg, Miss. Gerda Ulrika",female,22,0,0,7552,10.5167,,S 885 | 884,0,2,"Banfield, Mr. Frederick James",male,28,0,0,C.A./SOTON 34068,10.5,,S 886 | 885,0,3,"Sutehall, Mr. Henry Jr",male,25,0,0,SOTON/OQ 392076,7.05,,S 887 | 886,0,3,"Rice, Mrs. William (Margaret Norton)",female,39,0,5,382652,29.125,,Q 888 | 887,0,2,"Montvila, Rev. Juozas",male,27,0,0,211536,13,,S 889 | 888,1,1,"Graham, Miss. Margaret Edith",female,19,0,0,112053,30,B42,S 890 | 889,0,3,"Johnston, Miss. Catherine Helen ""Carrie""",female,,1,2,W./C. 6607,23.45,,S 891 | 890,1,1,"Behr, Mr. Karl Howell",male,26,0,0,111369,30,C148,C 892 | 891,0,3,"Dooley, Mr. Patrick",male,32,0,0,370376,7.75,,Q 893 | -------------------------------------------------------------------------------- /mypy.ini: -------------------------------------------------------------------------------- 1 | # Global options 2 | 3 | [mypy] 4 | python_version = 3.8 5 | ignore_missing_imports = True -------------------------------------------------------------------------------- /poetry.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "astroid" 3 | version = "2.4.2" 4 | description = "An abstract syntax tree for Python with inference support." 5 | category = "main" 6 | optional = false 7 | python-versions = ">=3.5" 8 | 9 | [package.dependencies] 10 | lazy-object-proxy = ">=1.4.0,<1.5.0" 11 | six = ">=1.12,<2.0" 12 | wrapt = ">=1.11,<2.0" 13 | 14 | [[package]] 15 | name = "atomicwrites" 16 | version = "1.4.0" 17 | description = "Atomic file writes." 18 | category = "main" 19 | optional = false 20 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 21 | 22 | [[package]] 23 | name = "attrs" 24 | version = "20.1.0" 25 | description = "Classes Without Boilerplate" 26 | category = "main" 27 | optional = false 28 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 29 | 30 | [package.extras] 31 | dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pre-commit", "pympler", "pytest (>=4.3.0)", "six", "sphinx", "sphinx-rtd-theme", "zope.interface"] 32 | docs = ["sphinx", "sphinx-rtd-theme", "zope.interface"] 33 | tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface"] 34 | 35 | [[package]] 36 | name = "certifi" 37 | version = "2020.6.20" 38 | description = "Python package for providing Mozilla's CA Bundle." 39 | category = "main" 40 | optional = false 41 | python-versions = "*" 42 | 43 | [[package]] 44 | name = "charset-normalizer" 45 | version = "2.1.1" 46 | description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." 47 | category = "main" 48 | optional = false 49 | python-versions = ">=3.6.0" 50 | 51 | [package.extras] 52 | unicode_backport = ["unicodedata2"] 53 | 54 | [[package]] 55 | name = "codecov" 56 | version = "2.1.9" 57 | description = "Hosted coverage reports for GitHub, Bitbucket and Gitlab" 58 | category = "main" 59 | optional = false 60 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 61 | 62 | [package.dependencies] 63 | coverage = "*" 64 | requests = ">=2.7.9" 65 | 66 | [[package]] 67 | name = "colorama" 68 | version = "0.4.3" 69 | description = "Cross-platform colored terminal text." 70 | category = "main" 71 | optional = false 72 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 73 | 74 | [[package]] 75 | name = "coverage" 76 | version = "5.2.1" 77 | description = "Code coverage measurement for Python" 78 | category = "main" 79 | optional = false 80 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" 81 | 82 | [package.extras] 83 | toml = ["toml"] 84 | 85 | [[package]] 86 | name = "idna" 87 | version = "2.10" 88 | description = "Internationalized Domain Names in Applications (IDNA)" 89 | category = "main" 90 | optional = false 91 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 92 | 93 | [[package]] 94 | name = "iniconfig" 95 | version = "1.0.1" 96 | description = "iniconfig: brain-dead simple config-ini parsing" 97 | category = "main" 98 | optional = false 99 | python-versions = "*" 100 | 101 | [[package]] 102 | name = "isort" 103 | version = "5.4.2" 104 | description = "A Python utility / library to sort Python imports." 105 | category = "main" 106 | optional = false 107 | python-versions = ">=3.6,<4.0" 108 | 109 | [package.extras] 110 | colors = ["colorama (>=0.4.3,<0.5.0)"] 111 | pipfile_deprecated_finder = ["pipreqs", "requirementslib", "tomlkit (>=0.5.3)"] 112 | requirements_deprecated_finder = ["pip-api", "pipreqs"] 113 | 114 | [[package]] 115 | name = "joblib" 116 | version = "0.16.0" 117 | description = "Lightweight pipelining: using Python functions as pipeline jobs." 118 | category = "main" 119 | optional = false 120 | python-versions = ">=3.6" 121 | 122 | [[package]] 123 | name = "lazy-object-proxy" 124 | version = "1.4.3" 125 | description = "A fast and thorough lazy object proxy." 126 | category = "main" 127 | optional = false 128 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 129 | 130 | [[package]] 131 | name = "mccabe" 132 | version = "0.6.1" 133 | description = "McCabe checker, plugin for flake8" 134 | category = "main" 135 | optional = false 136 | python-versions = "*" 137 | 138 | [[package]] 139 | name = "more-itertools" 140 | version = "8.5.0" 141 | description = "More routines for operating on iterables, beyond itertools" 142 | category = "main" 143 | optional = false 144 | python-versions = ">=3.5" 145 | 146 | [[package]] 147 | name = "mypy" 148 | version = "0.782" 149 | description = "Optional static typing for Python" 150 | category = "main" 151 | optional = false 152 | python-versions = ">=3.5" 153 | 154 | [package.dependencies] 155 | mypy-extensions = ">=0.4.3,<0.5.0" 156 | typed-ast = ">=1.4.0,<1.5.0" 157 | typing-extensions = ">=3.7.4" 158 | 159 | [package.extras] 160 | dmypy = ["psutil (>=4.0)"] 161 | 162 | [[package]] 163 | name = "mypy-extensions" 164 | version = "0.4.3" 165 | description = "Experimental type system extensions for programs checked with the mypy typechecker." 166 | category = "main" 167 | optional = false 168 | python-versions = "*" 169 | 170 | [[package]] 171 | name = "numpy" 172 | version = "1.19.1" 173 | description = "NumPy is the fundamental package for array computing with Python." 174 | category = "main" 175 | optional = false 176 | python-versions = ">=3.6" 177 | 178 | [[package]] 179 | name = "packaging" 180 | version = "20.4" 181 | description = "Core utilities for Python packages" 182 | category = "main" 183 | optional = false 184 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 185 | 186 | [package.dependencies] 187 | pyparsing = ">=2.0.2" 188 | six = "*" 189 | 190 | [[package]] 191 | name = "pandas" 192 | version = "1.1.1" 193 | description = "Powerful data structures for data analysis, time series, and statistics" 194 | category = "main" 195 | optional = false 196 | python-versions = ">=3.6.1" 197 | 198 | [package.dependencies] 199 | numpy = ">=1.15.4" 200 | python-dateutil = ">=2.7.3" 201 | pytz = ">=2017.2" 202 | 203 | [package.extras] 204 | test = ["hypothesis (>=3.58)", "pytest (>=4.0.2)", "pytest-xdist"] 205 | 206 | [[package]] 207 | name = "pluggy" 208 | version = "0.13.1" 209 | description = "plugin and hook calling mechanisms for python" 210 | category = "main" 211 | optional = false 212 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 213 | 214 | [package.extras] 215 | dev = ["pre-commit", "tox"] 216 | 217 | [[package]] 218 | name = "py" 219 | version = "1.10.0" 220 | description = "library with cross-python path, ini-parsing, io, code, log facilities" 221 | category = "main" 222 | optional = false 223 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 224 | 225 | [[package]] 226 | name = "pylint" 227 | version = "2.6.0" 228 | description = "python code static checker" 229 | category = "main" 230 | optional = false 231 | python-versions = ">=3.5.*" 232 | 233 | [package.dependencies] 234 | astroid = ">=2.4.0,<=2.5" 235 | colorama = {version = "*", markers = "sys_platform == \"win32\""} 236 | isort = ">=4.2.5,<6" 237 | mccabe = ">=0.6,<0.7" 238 | toml = ">=0.7.1" 239 | 240 | [[package]] 241 | name = "pyparsing" 242 | version = "2.4.7" 243 | description = "Python parsing module" 244 | category = "main" 245 | optional = false 246 | python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" 247 | 248 | [[package]] 249 | name = "pytest" 250 | version = "6.0.1" 251 | description = "pytest: simple powerful testing with Python" 252 | category = "main" 253 | optional = false 254 | python-versions = ">=3.5" 255 | 256 | [package.dependencies] 257 | atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} 258 | attrs = ">=17.4.0" 259 | colorama = {version = "*", markers = "sys_platform == \"win32\""} 260 | iniconfig = "*" 261 | more-itertools = ">=4.0.0" 262 | packaging = "*" 263 | pluggy = ">=0.12,<1.0" 264 | py = ">=1.8.2" 265 | toml = "*" 266 | 267 | [package.extras] 268 | checkqa_mypy = ["mypy (==0.780)"] 269 | testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"] 270 | 271 | [[package]] 272 | name = "pytest-cov" 273 | version = "2.10.1" 274 | description = "Pytest plugin for measuring coverage." 275 | category = "main" 276 | optional = false 277 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 278 | 279 | [package.dependencies] 280 | coverage = ">=4.4" 281 | pytest = ">=4.6" 282 | 283 | [package.extras] 284 | testing = ["fields", "hunter", "process-tests (==2.0.2)", "pytest-xdist", "six", "virtualenv"] 285 | 286 | [[package]] 287 | name = "python-dateutil" 288 | version = "2.8.1" 289 | description = "Extensions to the standard Python datetime module" 290 | category = "main" 291 | optional = false 292 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" 293 | 294 | [package.dependencies] 295 | six = ">=1.5" 296 | 297 | [[package]] 298 | name = "pytz" 299 | version = "2020.1" 300 | description = "World timezone definitions, modern and historical" 301 | category = "main" 302 | optional = false 303 | python-versions = "*" 304 | 305 | [[package]] 306 | name = "requests" 307 | version = "2.28.1" 308 | description = "Python HTTP for Humans." 309 | category = "main" 310 | optional = false 311 | python-versions = ">=3.7, <4" 312 | 313 | [package.dependencies] 314 | certifi = ">=2017.4.17" 315 | charset-normalizer = ">=2,<3" 316 | idna = ">=2.5,<4" 317 | urllib3 = ">=1.21.1,<1.27" 318 | 319 | [package.extras] 320 | socks = ["PySocks (>=1.5.6,!=1.5.7)"] 321 | use_chardet_on_py3 = ["chardet (>=3.0.2,<6)"] 322 | 323 | [[package]] 324 | name = "scikit-learn" 325 | version = "0.23.2" 326 | description = "A set of python modules for machine learning and data mining" 327 | category = "main" 328 | optional = false 329 | python-versions = ">=3.6" 330 | 331 | [package.dependencies] 332 | joblib = ">=0.11" 333 | numpy = ">=1.13.3" 334 | scipy = ">=0.19.1" 335 | threadpoolctl = ">=2.0.0" 336 | 337 | [package.extras] 338 | alldeps = ["numpy (>=1.13.3)", "scipy (>=0.19.1)"] 339 | 340 | [[package]] 341 | name = "scipy" 342 | version = "1.5.2" 343 | description = "SciPy: Scientific Library for Python" 344 | category = "main" 345 | optional = false 346 | python-versions = ">=3.6" 347 | 348 | [package.dependencies] 349 | numpy = ">=1.14.5" 350 | 351 | [[package]] 352 | name = "six" 353 | version = "1.15.0" 354 | description = "Python 2 and 3 compatibility utilities" 355 | category = "main" 356 | optional = false 357 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" 358 | 359 | [[package]] 360 | name = "threadpoolctl" 361 | version = "2.1.0" 362 | description = "threadpoolctl" 363 | category = "main" 364 | optional = false 365 | python-versions = ">=3.5" 366 | 367 | [[package]] 368 | name = "toml" 369 | version = "0.10.1" 370 | description = "Python Library for Tom's Obvious, Minimal Language" 371 | category = "main" 372 | optional = false 373 | python-versions = "*" 374 | 375 | [[package]] 376 | name = "typed-ast" 377 | version = "1.4.1" 378 | description = "a fork of Python 2 and 3 ast modules with type comment support" 379 | category = "main" 380 | optional = false 381 | python-versions = "*" 382 | 383 | [[package]] 384 | name = "typing-extensions" 385 | version = "3.7.4.3" 386 | description = "Backported and Experimental Type Hints for Python 3.5+" 387 | category = "main" 388 | optional = false 389 | python-versions = "*" 390 | 391 | [[package]] 392 | name = "urllib3" 393 | version = "1.26.5" 394 | description = "HTTP library with thread-safe connection pooling, file post, and more." 395 | category = "main" 396 | optional = false 397 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" 398 | 399 | [package.extras] 400 | brotli = ["brotlipy (>=0.6.0)"] 401 | secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)"] 402 | socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] 403 | 404 | [[package]] 405 | name = "wrapt" 406 | version = "1.12.1" 407 | description = "Module for decorators, wrappers and monkey patching." 408 | category = "main" 409 | optional = false 410 | python-versions = "*" 411 | 412 | [metadata] 413 | lock-version = "1.1" 414 | python-versions = "^3.8" 415 | content-hash = "33ae89c7c3c8f2ea059d06060dc90914a9135f44e491dd691f0d37b41c6c3c8d" 416 | 417 | [metadata.files] 418 | astroid = [ 419 | {file = "astroid-2.4.2-py3-none-any.whl", hash = "sha256:bc58d83eb610252fd8de6363e39d4f1d0619c894b0ed24603b881c02e64c7386"}, 420 | {file = "astroid-2.4.2.tar.gz", hash = "sha256:2f4078c2a41bf377eea06d71c9d2ba4eb8f6b1af2135bec27bbbb7d8f12bb703"}, 421 | ] 422 | atomicwrites = [ 423 | {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"}, 424 | {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"}, 425 | ] 426 | attrs = [ 427 | {file = "attrs-20.1.0-py2.py3-none-any.whl", hash = "sha256:2867b7b9f8326499ab5b0e2d12801fa5c98842d2cbd22b35112ae04bf85b4dff"}, 428 | {file = "attrs-20.1.0.tar.gz", hash = "sha256:0ef97238856430dcf9228e07f316aefc17e8939fc8507e18c6501b761ef1a42a"}, 429 | ] 430 | certifi = [ 431 | {file = "certifi-2020.6.20-py2.py3-none-any.whl", hash = "sha256:8fc0819f1f30ba15bdb34cceffb9ef04d99f420f68eb75d901e9560b8749fc41"}, 432 | {file = "certifi-2020.6.20.tar.gz", hash = "sha256:5930595817496dd21bb8dc35dad090f1c2cd0adfaf21204bf6732ca5d8ee34d3"}, 433 | ] 434 | charset-normalizer = [ 435 | {file = "charset-normalizer-2.1.1.tar.gz", hash = "sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845"}, 436 | {file = "charset_normalizer-2.1.1-py3-none-any.whl", hash = "sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f"}, 437 | ] 438 | codecov = [ 439 | {file = "codecov-2.1.9-py2.py3-none-any.whl", hash = "sha256:24545847177a893716b3455ac5bfbafe0465f38d4eb86ea922c09adc7f327e65"}, 440 | {file = "codecov-2.1.9-py3.8.egg", hash = "sha256:7877f68effde3c2baadcff807a5d13f01019a337f9596eece0d64e57393adf3a"}, 441 | {file = "codecov-2.1.9.tar.gz", hash = "sha256:355fc7e0c0b8a133045f0d6089bde351c845e7b52b99fec5903b4ea3ab5f6aab"}, 442 | ] 443 | colorama = [ 444 | {file = "colorama-0.4.3-py2.py3-none-any.whl", hash = "sha256:7d73d2a99753107a36ac6b455ee49046802e59d9d076ef8e47b61499fa29afff"}, 445 | {file = "colorama-0.4.3.tar.gz", hash = "sha256:e96da0d330793e2cb9485e9ddfd918d456036c7149416295932478192f4436a1"}, 446 | ] 447 | coverage = [ 448 | {file = "coverage-5.2.1-cp27-cp27m-macosx_10_13_intel.whl", hash = "sha256:40f70f81be4d34f8d491e55936904db5c527b0711b2a46513641a5729783c2e4"}, 449 | {file = "coverage-5.2.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:675192fca634f0df69af3493a48224f211f8db4e84452b08d5fcebb9167adb01"}, 450 | {file = "coverage-5.2.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:2fcc8b58953d74d199a1a4d633df8146f0ac36c4e720b4a1997e9b6327af43a8"}, 451 | {file = "coverage-5.2.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:64c4f340338c68c463f1b56e3f2f0423f7b17ba6c3febae80b81f0e093077f59"}, 452 | {file = "coverage-5.2.1-cp27-cp27m-win32.whl", hash = "sha256:52f185ffd3291196dc1aae506b42e178a592b0b60a8610b108e6ad892cfc1bb3"}, 453 | {file = "coverage-5.2.1-cp27-cp27m-win_amd64.whl", hash = "sha256:30bc103587e0d3df9e52cd9da1dd915265a22fad0b72afe54daf840c984b564f"}, 454 | {file = "coverage-5.2.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:9ea749fd447ce7fb1ac71f7616371f04054d969d412d37611716721931e36efd"}, 455 | {file = "coverage-5.2.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:ce7866f29d3025b5b34c2e944e66ebef0d92e4a4f2463f7266daa03a1332a651"}, 456 | {file = "coverage-5.2.1-cp35-cp35m-macosx_10_13_x86_64.whl", hash = "sha256:4869ab1c1ed33953bb2433ce7b894a28d724b7aa76c19b11e2878034a4e4680b"}, 457 | {file = "coverage-5.2.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:a3ee9c793ffefe2944d3a2bd928a0e436cd0ac2d9e3723152d6fd5398838ce7d"}, 458 | {file = "coverage-5.2.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:28f42dc5172ebdc32622a2c3f7ead1b836cdbf253569ae5673f499e35db0bac3"}, 459 | {file = "coverage-5.2.1-cp35-cp35m-win32.whl", hash = "sha256:e26c993bd4b220429d4ec8c1468eca445a4064a61c74ca08da7429af9bc53bb0"}, 460 | {file = "coverage-5.2.1-cp35-cp35m-win_amd64.whl", hash = "sha256:4186fc95c9febeab5681bc3248553d5ec8c2999b8424d4fc3a39c9cba5796962"}, 461 | {file = "coverage-5.2.1-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:b360d8fd88d2bad01cb953d81fd2edd4be539df7bfec41e8753fe9f4456a5082"}, 462 | {file = "coverage-5.2.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:1adb6be0dcef0cf9434619d3b892772fdb48e793300f9d762e480e043bd8e716"}, 463 | {file = "coverage-5.2.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:098a703d913be6fbd146a8c50cc76513d726b022d170e5e98dc56d958fd592fb"}, 464 | {file = "coverage-5.2.1-cp36-cp36m-win32.whl", hash = "sha256:962c44070c281d86398aeb8f64e1bf37816a4dfc6f4c0f114756b14fc575621d"}, 465 | {file = "coverage-5.2.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b1ed2bdb27b4c9fc87058a1cb751c4df8752002143ed393899edb82b131e0546"}, 466 | {file = "coverage-5.2.1-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:c890728a93fffd0407d7d37c1e6083ff3f9f211c83b4316fae3778417eab9811"}, 467 | {file = "coverage-5.2.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:538f2fd5eb64366f37c97fdb3077d665fa946d2b6d95447622292f38407f9258"}, 468 | {file = "coverage-5.2.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:27ca5a2bc04d68f0776f2cdcb8bbd508bbe430a7bf9c02315cd05fb1d86d0034"}, 469 | {file = "coverage-5.2.1-cp37-cp37m-win32.whl", hash = "sha256:aab75d99f3f2874733946a7648ce87a50019eb90baef931698f96b76b6769a46"}, 470 | {file = "coverage-5.2.1-cp37-cp37m-win_amd64.whl", hash = "sha256:c2ff24df02a125b7b346c4c9078c8936da06964cc2d276292c357d64378158f8"}, 471 | {file = "coverage-5.2.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:304fbe451698373dc6653772c72c5d5e883a4aadaf20343592a7abb2e643dae0"}, 472 | {file = "coverage-5.2.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:c96472b8ca5dc135fb0aa62f79b033f02aa434fb03a8b190600a5ae4102df1fd"}, 473 | {file = "coverage-5.2.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:8505e614c983834239f865da2dd336dcf9d72776b951d5dfa5ac36b987726e1b"}, 474 | {file = "coverage-5.2.1-cp38-cp38-win32.whl", hash = "sha256:700997b77cfab016533b3e7dbc03b71d33ee4df1d79f2463a318ca0263fc29dd"}, 475 | {file = "coverage-5.2.1-cp38-cp38-win_amd64.whl", hash = "sha256:46794c815e56f1431c66d81943fa90721bb858375fb36e5903697d5eef88627d"}, 476 | {file = "coverage-5.2.1-cp39-cp39-macosx_10_13_x86_64.whl", hash = "sha256:16042dc7f8e632e0dcd5206a5095ebd18cb1d005f4c89694f7f8aafd96dd43a3"}, 477 | {file = "coverage-5.2.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:c1bbb628ed5192124889b51204de27c575b3ffc05a5a91307e7640eff1d48da4"}, 478 | {file = "coverage-5.2.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:4f6428b55d2916a69f8d6453e48a505c07b2245653b0aa9f0dee38785939f5e4"}, 479 | {file = "coverage-5.2.1-cp39-cp39-win32.whl", hash = "sha256:9e536783a5acee79a9b308be97d3952b662748c4037b6a24cbb339dc7ed8eb89"}, 480 | {file = "coverage-5.2.1-cp39-cp39-win_amd64.whl", hash = "sha256:b8f58c7db64d8f27078cbf2a4391af6aa4e4767cc08b37555c4ae064b8558d9b"}, 481 | {file = "coverage-5.2.1.tar.gz", hash = "sha256:a34cb28e0747ea15e82d13e14de606747e9e484fb28d63c999483f5d5188e89b"}, 482 | ] 483 | idna = [ 484 | {file = "idna-2.10-py2.py3-none-any.whl", hash = "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"}, 485 | {file = "idna-2.10.tar.gz", hash = "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6"}, 486 | ] 487 | iniconfig = [ 488 | {file = "iniconfig-1.0.1-py3-none-any.whl", hash = "sha256:80cf40c597eb564e86346103f609d74efce0f6b4d4f30ec8ce9e2c26411ba437"}, 489 | {file = "iniconfig-1.0.1.tar.gz", hash = "sha256:e5f92f89355a67de0595932a6c6c02ab4afddc6fcdc0bfc5becd0d60884d3f69"}, 490 | ] 491 | isort = [ 492 | {file = "isort-5.4.2-py3-none-any.whl", hash = "sha256:60a1b97e33f61243d12647aaaa3e6cc6778f5eb9f42997650f1cc975b6008750"}, 493 | {file = "isort-5.4.2.tar.gz", hash = "sha256:d488ba1c5a2db721669cc180180d5acf84ebdc5af7827f7aaeaa75f73cf0e2b8"}, 494 | ] 495 | joblib = [ 496 | {file = "joblib-0.16.0-py3-none-any.whl", hash = "sha256:d348c5d4ae31496b2aa060d6d9b787864dd204f9480baaa52d18850cb43e9f49"}, 497 | {file = "joblib-0.16.0.tar.gz", hash = "sha256:8f52bf24c64b608bf0b2563e0e47d6fcf516abc8cfafe10cfd98ad66d94f92d6"}, 498 | ] 499 | lazy-object-proxy = [ 500 | {file = "lazy-object-proxy-1.4.3.tar.gz", hash = "sha256:f3900e8a5de27447acbf900b4750b0ddfd7ec1ea7fbaf11dfa911141bc522af0"}, 501 | {file = "lazy_object_proxy-1.4.3-cp27-cp27m-macosx_10_13_x86_64.whl", hash = "sha256:a2238e9d1bb71a56cd710611a1614d1194dc10a175c1e08d75e1a7bcc250d442"}, 502 | {file = "lazy_object_proxy-1.4.3-cp27-cp27m-win32.whl", hash = "sha256:efa1909120ce98bbb3777e8b6f92237f5d5c8ea6758efea36a473e1d38f7d3e4"}, 503 | {file = "lazy_object_proxy-1.4.3-cp27-cp27m-win_amd64.whl", hash = "sha256:4677f594e474c91da97f489fea5b7daa17b5517190899cf213697e48d3902f5a"}, 504 | {file = "lazy_object_proxy-1.4.3-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:0c4b206227a8097f05c4dbdd323c50edf81f15db3b8dc064d08c62d37e1a504d"}, 505 | {file = "lazy_object_proxy-1.4.3-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:d945239a5639b3ff35b70a88c5f2f491913eb94871780ebfabb2568bd58afc5a"}, 506 | {file = "lazy_object_proxy-1.4.3-cp34-cp34m-win32.whl", hash = "sha256:9651375199045a358eb6741df3e02a651e0330be090b3bc79f6d0de31a80ec3e"}, 507 | {file = "lazy_object_proxy-1.4.3-cp34-cp34m-win_amd64.whl", hash = "sha256:eba7011090323c1dadf18b3b689845fd96a61ba0a1dfbd7f24b921398affc357"}, 508 | {file = "lazy_object_proxy-1.4.3-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:48dab84ebd4831077b150572aec802f303117c8cc5c871e182447281ebf3ac50"}, 509 | {file = "lazy_object_proxy-1.4.3-cp35-cp35m-win32.whl", hash = "sha256:ca0a928a3ddbc5725be2dd1cf895ec0a254798915fb3a36af0964a0a4149e3db"}, 510 | {file = "lazy_object_proxy-1.4.3-cp35-cp35m-win_amd64.whl", hash = "sha256:194d092e6f246b906e8f70884e620e459fc54db3259e60cf69a4d66c3fda3449"}, 511 | {file = "lazy_object_proxy-1.4.3-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:97bb5884f6f1cdce0099f86b907aa41c970c3c672ac8b9c8352789e103cf3156"}, 512 | {file = "lazy_object_proxy-1.4.3-cp36-cp36m-win32.whl", hash = "sha256:cb2c7c57005a6804ab66f106ceb8482da55f5314b7fcb06551db1edae4ad1531"}, 513 | {file = "lazy_object_proxy-1.4.3-cp36-cp36m-win_amd64.whl", hash = "sha256:8d859b89baf8ef7f8bc6b00aa20316483d67f0b1cbf422f5b4dc56701c8f2ffb"}, 514 | {file = "lazy_object_proxy-1.4.3-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:1be7e4c9f96948003609aa6c974ae59830a6baecc5376c25c92d7d697e684c08"}, 515 | {file = "lazy_object_proxy-1.4.3-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:d74bb8693bf9cf75ac3b47a54d716bbb1a92648d5f781fc799347cfc95952383"}, 516 | {file = "lazy_object_proxy-1.4.3-cp37-cp37m-win32.whl", hash = "sha256:9b15f3f4c0f35727d3a0fba4b770b3c4ebbb1fa907dbcc046a1d2799f3edd142"}, 517 | {file = "lazy_object_proxy-1.4.3-cp37-cp37m-win_amd64.whl", hash = "sha256:9254f4358b9b541e3441b007a0ea0764b9d056afdeafc1a5569eee1cc6c1b9ea"}, 518 | {file = "lazy_object_proxy-1.4.3-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:a6ae12d08c0bf9909ce12385803a543bfe99b95fe01e752536a60af2b7797c62"}, 519 | {file = "lazy_object_proxy-1.4.3-cp38-cp38-win32.whl", hash = "sha256:5541cada25cd173702dbd99f8e22434105456314462326f06dba3e180f203dfd"}, 520 | {file = "lazy_object_proxy-1.4.3-cp38-cp38-win_amd64.whl", hash = "sha256:59f79fef100b09564bc2df42ea2d8d21a64fdcda64979c0fa3db7bdaabaf6239"}, 521 | ] 522 | mccabe = [ 523 | {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, 524 | {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, 525 | ] 526 | more-itertools = [ 527 | {file = "more-itertools-8.5.0.tar.gz", hash = "sha256:6f83822ae94818eae2612063a5101a7311e68ae8002005b5e05f03fd74a86a20"}, 528 | {file = "more_itertools-8.5.0-py3-none-any.whl", hash = "sha256:9b30f12df9393f0d28af9210ff8efe48d10c94f73e5daf886f10c4b0b0b4f03c"}, 529 | ] 530 | mypy = [ 531 | {file = "mypy-0.782-cp35-cp35m-macosx_10_6_x86_64.whl", hash = "sha256:2c6cde8aa3426c1682d35190b59b71f661237d74b053822ea3d748e2c9578a7c"}, 532 | {file = "mypy-0.782-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:9c7a9a7ceb2871ba4bac1cf7217a7dd9ccd44c27c2950edbc6dc08530f32ad4e"}, 533 | {file = "mypy-0.782-cp35-cp35m-win_amd64.whl", hash = "sha256:c05b9e4fb1d8a41d41dec8786c94f3b95d3c5f528298d769eb8e73d293abc48d"}, 534 | {file = "mypy-0.782-cp36-cp36m-macosx_10_6_x86_64.whl", hash = "sha256:6731603dfe0ce4352c555c6284c6db0dc935b685e9ce2e4cf220abe1e14386fd"}, 535 | {file = "mypy-0.782-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:f05644db6779387ccdb468cc47a44b4356fc2ffa9287135d05b70a98dc83b89a"}, 536 | {file = "mypy-0.782-cp36-cp36m-win_amd64.whl", hash = "sha256:b7fbfabdbcc78c4f6fc4712544b9b0d6bf171069c6e0e3cb82440dd10ced3406"}, 537 | {file = "mypy-0.782-cp37-cp37m-macosx_10_6_x86_64.whl", hash = "sha256:3fdda71c067d3ddfb21da4b80e2686b71e9e5c72cca65fa216d207a358827f86"}, 538 | {file = "mypy-0.782-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:d7df6eddb6054d21ca4d3c6249cae5578cb4602951fd2b6ee2f5510ffb098707"}, 539 | {file = "mypy-0.782-cp37-cp37m-win_amd64.whl", hash = "sha256:a4a2cbcfc4cbf45cd126f531dedda8485671545b43107ded25ce952aac6fb308"}, 540 | {file = "mypy-0.782-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6bb93479caa6619d21d6e7160c552c1193f6952f0668cdda2f851156e85186fc"}, 541 | {file = "mypy-0.782-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:81c7908b94239c4010e16642c9102bfc958ab14e36048fa77d0be3289dda76ea"}, 542 | {file = "mypy-0.782-cp38-cp38-win_amd64.whl", hash = "sha256:5dd13ff1f2a97f94540fd37a49e5d255950ebcdf446fb597463a40d0df3fac8b"}, 543 | {file = "mypy-0.782-py3-none-any.whl", hash = "sha256:e0b61738ab504e656d1fe4ff0c0601387a5489ca122d55390ade31f9ca0e252d"}, 544 | {file = "mypy-0.782.tar.gz", hash = "sha256:eff7d4a85e9eea55afa34888dfeaccde99e7520b51f867ac28a48492c0b1130c"}, 545 | ] 546 | mypy-extensions = [ 547 | {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, 548 | {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, 549 | ] 550 | numpy = [ 551 | {file = "numpy-1.19.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b1cca51512299841bf69add3b75361779962f9cee7d9ee3bb446d5982e925b69"}, 552 | {file = "numpy-1.19.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:c9591886fc9cbe5532d5df85cb8e0cc3b44ba8ce4367bd4cf1b93dc19713da72"}, 553 | {file = "numpy-1.19.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:cf1347450c0b7644ea142712619533553f02ef23f92f781312f6a3553d031fc7"}, 554 | {file = "numpy-1.19.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:ed8a311493cf5480a2ebc597d1e177231984c818a86875126cfd004241a73c3e"}, 555 | {file = "numpy-1.19.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:3673c8b2b29077f1b7b3a848794f8e11f401ba0b71c49fbd26fb40b71788b132"}, 556 | {file = "numpy-1.19.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:56ef7f56470c24bb67fb43dae442e946a6ce172f97c69f8d067ff8550cf782ff"}, 557 | {file = "numpy-1.19.1-cp36-cp36m-win32.whl", hash = "sha256:aaf42a04b472d12515debc621c31cf16c215e332242e7a9f56403d814c744624"}, 558 | {file = "numpy-1.19.1-cp36-cp36m-win_amd64.whl", hash = "sha256:082f8d4dd69b6b688f64f509b91d482362124986d98dc7dc5f5e9f9b9c3bb983"}, 559 | {file = "numpy-1.19.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e4f6d3c53911a9d103d8ec9518190e52a8b945bab021745af4939cfc7c0d4a9e"}, 560 | {file = "numpy-1.19.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:5b6885c12784a27e957294b60f97e8b5b4174c7504665333c5e94fbf41ae5d6a"}, 561 | {file = "numpy-1.19.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:1bc0145999e8cb8aed9d4e65dd8b139adf1919e521177f198529687dbf613065"}, 562 | {file = "numpy-1.19.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:5a936fd51049541d86ccdeef2833cc89a18e4d3808fe58a8abeb802665c5af93"}, 563 | {file = "numpy-1.19.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:ef71a1d4fd4858596ae80ad1ec76404ad29701f8ca7cdcebc50300178db14dfc"}, 564 | {file = "numpy-1.19.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:b9792b0ac0130b277536ab8944e7b754c69560dac0415dd4b2dbd16b902c8954"}, 565 | {file = "numpy-1.19.1-cp37-cp37m-win32.whl", hash = "sha256:b12e639378c741add21fbffd16ba5ad25c0a1a17cf2b6fe4288feeb65144f35b"}, 566 | {file = "numpy-1.19.1-cp37-cp37m-win_amd64.whl", hash = "sha256:8343bf67c72e09cfabfab55ad4a43ce3f6bf6e6ced7acf70f45ded9ebb425055"}, 567 | {file = "numpy-1.19.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e45f8e981a0ab47103181773cc0a54e650b2aef8c7b6cd07405d0fa8d869444a"}, 568 | {file = "numpy-1.19.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:667c07063940e934287993366ad5f56766bc009017b4a0fe91dbd07960d0aba7"}, 569 | {file = "numpy-1.19.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:480fdd4dbda4dd6b638d3863da3be82873bba6d32d1fc12ea1b8486ac7b8d129"}, 570 | {file = "numpy-1.19.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:935c27ae2760c21cd7354402546f6be21d3d0c806fffe967f745d5f2de5005a7"}, 571 | {file = "numpy-1.19.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:309cbcfaa103fc9a33ec16d2d62569d541b79f828c382556ff072442226d1968"}, 572 | {file = "numpy-1.19.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:7ed448ff4eaffeb01094959b19cbaf998ecdee9ef9932381420d514e446601cd"}, 573 | {file = "numpy-1.19.1-cp38-cp38-win32.whl", hash = "sha256:de8b4a9b56255797cbddb93281ed92acbc510fb7b15df3f01bd28f46ebc4edae"}, 574 | {file = "numpy-1.19.1-cp38-cp38-win_amd64.whl", hash = "sha256:92feb989b47f83ebef246adabc7ff3b9a59ac30601c3f6819f8913458610bdcc"}, 575 | {file = "numpy-1.19.1-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:e1b1dc0372f530f26a03578ac75d5e51b3868b9b76cd2facba4c9ee0eb252ab1"}, 576 | {file = "numpy-1.19.1.zip", hash = "sha256:b8456987b637232602ceb4d663cb34106f7eb780e247d51a260b84760fd8f491"}, 577 | ] 578 | packaging = [ 579 | {file = "packaging-20.4-py2.py3-none-any.whl", hash = "sha256:998416ba6962ae7fbd6596850b80e17859a5753ba17c32284f67bfff33784181"}, 580 | {file = "packaging-20.4.tar.gz", hash = "sha256:4357f74f47b9c12db93624a82154e9b120fa8293699949152b22065d556079f8"}, 581 | ] 582 | pandas = [ 583 | {file = "pandas-1.1.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:8c9ec12c480c4d915e23ee9c8a2d8eba8509986f35f307771045c1294a2e5b73"}, 584 | {file = "pandas-1.1.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:e4b6c98f45695799990da328e6fd7d6187be32752ed64c2f22326ad66762d179"}, 585 | {file = "pandas-1.1.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:16ae070c47474008769fc443ac765ffd88c3506b4a82966e7a605592978896f9"}, 586 | {file = "pandas-1.1.1-cp36-cp36m-win32.whl", hash = "sha256:88930c74f69e97b17703600233c0eaf1f4f4dd10c14633d522724c5c1b963ec4"}, 587 | {file = "pandas-1.1.1-cp36-cp36m-win_amd64.whl", hash = "sha256:fe6f1623376b616e03d51f0dd95afd862cf9a33c18cf55ce0ed4bbe1c4444391"}, 588 | {file = "pandas-1.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a81c4bf9c59010aa3efddbb6b9fc84a9b76dc0b4da2c2c2d50f06a9ef6ac0004"}, 589 | {file = "pandas-1.1.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:1acc2bd7fc95e5408a4456897c2c2a1ae7c6acefe108d90479ab6d98d34fcc3d"}, 590 | {file = "pandas-1.1.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:84c101d0f7bbf0d9f1be9a2f29f6fcc12415442558d067164e50a56edfb732b4"}, 591 | {file = "pandas-1.1.1-cp37-cp37m-win32.whl", hash = "sha256:391db82ebeb886143b96b9c6c6166686c9a272d00020e4e39ad63b792542d9e2"}, 592 | {file = "pandas-1.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:0366150fe8ee37ef89a45d3093e05026b5f895e42bbce3902ce3b6427f1b8471"}, 593 | {file = "pandas-1.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d9644ac996149b2a51325d48d77e25c911e01aa6d39dc1b64be679cd71f683ec"}, 594 | {file = "pandas-1.1.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:41675323d4fcdd15abde068607cad150dfe17f7d32290ee128e5fea98442bd09"}, 595 | {file = "pandas-1.1.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:0246c67cbaaaac8d25fed8d4cf2d8897bd858f0e540e8528a75281cee9ac516d"}, 596 | {file = "pandas-1.1.1-cp38-cp38-win32.whl", hash = "sha256:01b1e536eb960822c5e6b58357cad8c4b492a336f4a5630bf0b598566462a578"}, 597 | {file = "pandas-1.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:57c5f6be49259cde8e6f71c2bf240a26b071569cabc04c751358495d09419e56"}, 598 | {file = "pandas-1.1.1.tar.gz", hash = "sha256:53328284a7bb046e2e885fd1b8c078bd896d7fc4575b915d4936f54984a2ba67"}, 599 | ] 600 | pluggy = [ 601 | {file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"}, 602 | {file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"}, 603 | ] 604 | py = [ 605 | {file = "py-1.10.0-py2.py3-none-any.whl", hash = "sha256:3b80836aa6d1feeaa108e046da6423ab8f6ceda6468545ae8d02d9d58d18818a"}, 606 | {file = "py-1.10.0.tar.gz", hash = "sha256:21b81bda15b66ef5e1a777a21c4dcd9c20ad3efd0b3f817e7a809035269e1bd3"}, 607 | ] 608 | pylint = [ 609 | {file = "pylint-2.6.0-py3-none-any.whl", hash = "sha256:bfe68f020f8a0fece830a22dd4d5dddb4ecc6137db04face4c3420a46a52239f"}, 610 | {file = "pylint-2.6.0.tar.gz", hash = "sha256:bb4a908c9dadbc3aac18860550e870f58e1a02c9f2c204fdf5693d73be061210"}, 611 | ] 612 | pyparsing = [ 613 | {file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"}, 614 | {file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"}, 615 | ] 616 | pytest = [ 617 | {file = "pytest-6.0.1-py3-none-any.whl", hash = "sha256:8b6007800c53fdacd5a5c192203f4e531eb2a1540ad9c752e052ec0f7143dbad"}, 618 | {file = "pytest-6.0.1.tar.gz", hash = "sha256:85228d75db9f45e06e57ef9bf4429267f81ac7c0d742cc9ed63d09886a9fe6f4"}, 619 | ] 620 | pytest-cov = [ 621 | {file = "pytest-cov-2.10.1.tar.gz", hash = "sha256:47bd0ce14056fdd79f93e1713f88fad7bdcc583dcd7783da86ef2f085a0bb88e"}, 622 | {file = "pytest_cov-2.10.1-py2.py3-none-any.whl", hash = "sha256:45ec2d5182f89a81fc3eb29e3d1ed3113b9e9a873bcddb2a71faaab066110191"}, 623 | ] 624 | python-dateutil = [ 625 | {file = "python-dateutil-2.8.1.tar.gz", hash = "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c"}, 626 | {file = "python_dateutil-2.8.1-py2.py3-none-any.whl", hash = "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a"}, 627 | ] 628 | pytz = [ 629 | {file = "pytz-2020.1-py2.py3-none-any.whl", hash = "sha256:a494d53b6d39c3c6e44c3bec237336e14305e4f29bbf800b599253057fbb79ed"}, 630 | {file = "pytz-2020.1.tar.gz", hash = "sha256:c35965d010ce31b23eeb663ed3cc8c906275d6be1a34393a1d73a41febf4a048"}, 631 | ] 632 | requests = [ 633 | {file = "requests-2.28.1-py3-none-any.whl", hash = "sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349"}, 634 | {file = "requests-2.28.1.tar.gz", hash = "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983"}, 635 | ] 636 | scikit-learn = [ 637 | {file = "scikit-learn-0.23.2.tar.gz", hash = "sha256:20766f515e6cd6f954554387dfae705d93c7b544ec0e6c6a5d8e006f6f7ef480"}, 638 | {file = "scikit_learn-0.23.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:98508723f44c61896a4e15894b2016762a55555fbf09365a0bb1870ecbd442de"}, 639 | {file = "scikit_learn-0.23.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:a64817b050efd50f9abcfd311870073e500ae11b299683a519fbb52d85e08d25"}, 640 | {file = "scikit_learn-0.23.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:daf276c465c38ef736a79bd79fc80a249f746bcbcae50c40945428f7ece074f8"}, 641 | {file = "scikit_learn-0.23.2-cp36-cp36m-win32.whl", hash = "sha256:cb3e76380312e1f86abd20340ab1d5b3cc46a26f6593d3c33c9ea3e4c7134028"}, 642 | {file = "scikit_learn-0.23.2-cp36-cp36m-win_amd64.whl", hash = "sha256:0a127cc70990d4c15b1019680bfedc7fec6c23d14d3719fdf9b64b22d37cdeca"}, 643 | {file = "scikit_learn-0.23.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2aa95c2f17d2f80534156215c87bee72b6aa314a7f8b8fe92a2d71f47280570d"}, 644 | {file = "scikit_learn-0.23.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:6c28a1d00aae7c3c9568f61aafeaad813f0f01c729bee4fd9479e2132b215c1d"}, 645 | {file = "scikit_learn-0.23.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:da8e7c302003dd765d92a5616678e591f347460ac7b53e53d667be7dfe6d1b10"}, 646 | {file = "scikit_learn-0.23.2-cp37-cp37m-win32.whl", hash = "sha256:d9a1ce5f099f29c7c33181cc4386660e0ba891b21a60dc036bf369e3a3ee3aec"}, 647 | {file = "scikit_learn-0.23.2-cp37-cp37m-win_amd64.whl", hash = "sha256:914ac2b45a058d3f1338d7736200f7f3b094857758895f8667be8a81ff443b5b"}, 648 | {file = "scikit_learn-0.23.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7671bbeddd7f4f9a6968f3b5442dac5f22bf1ba06709ef888cc9132ad354a9ab"}, 649 | {file = "scikit_learn-0.23.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:d0dcaa54263307075cb93d0bee3ceb02821093b1b3d25f66021987d305d01dce"}, 650 | {file = "scikit_learn-0.23.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:5ce7a8021c9defc2b75620571b350acc4a7d9763c25b7593621ef50f3bd019a2"}, 651 | {file = "scikit_learn-0.23.2-cp38-cp38-win32.whl", hash = "sha256:0d39748e7c9669ba648acf40fb3ce96b8a07b240db6888563a7cb76e05e0d9cc"}, 652 | {file = "scikit_learn-0.23.2-cp38-cp38-win_amd64.whl", hash = "sha256:1b8a391de95f6285a2f9adffb7db0892718950954b7149a70c783dc848f104ea"}, 653 | ] 654 | scipy = [ 655 | {file = "scipy-1.5.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:cca9fce15109a36a0a9f9cfc64f870f1c140cb235ddf27fe0328e6afb44dfed0"}, 656 | {file = "scipy-1.5.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:1c7564a4810c1cd77fcdee7fa726d7d39d4e2695ad252d7c86c3ea9d85b7fb8f"}, 657 | {file = "scipy-1.5.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:07e52b316b40a4f001667d1ad4eb5f2318738de34597bd91537851365b6c61f1"}, 658 | {file = "scipy-1.5.2-cp36-cp36m-win32.whl", hash = "sha256:d56b10d8ed72ec1be76bf10508446df60954f08a41c2d40778bc29a3a9ad9bce"}, 659 | {file = "scipy-1.5.2-cp36-cp36m-win_amd64.whl", hash = "sha256:8e28e74b97fc8d6aa0454989db3b5d36fc27e69cef39a7ee5eaf8174ca1123cb"}, 660 | {file = "scipy-1.5.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:6e86c873fe1335d88b7a4bfa09d021f27a9e753758fd75f3f92d714aa4093768"}, 661 | {file = "scipy-1.5.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:a0afbb967fd2c98efad5f4c24439a640d39463282040a88e8e928db647d8ac3d"}, 662 | {file = "scipy-1.5.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:eecf40fa87eeda53e8e11d265ff2254729d04000cd40bae648e76ff268885d66"}, 663 | {file = "scipy-1.5.2-cp37-cp37m-win32.whl", hash = "sha256:315aa2165aca31375f4e26c230188db192ed901761390be908c9b21d8b07df62"}, 664 | {file = "scipy-1.5.2-cp37-cp37m-win_amd64.whl", hash = "sha256:ec5fe57e46828d034775b00cd625c4a7b5c7d2e354c3b258d820c6c72212a6ec"}, 665 | {file = "scipy-1.5.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:fc98f3eac993b9bfdd392e675dfe19850cc8c7246a8fd2b42443e506344be7d9"}, 666 | {file = "scipy-1.5.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:a785409c0fa51764766840185a34f96a0a93527a0ff0230484d33a8ed085c8f8"}, 667 | {file = "scipy-1.5.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:0a0e9a4e58a4734c2eba917f834b25b7e3b6dc333901ce7784fd31aefbd37b2f"}, 668 | {file = "scipy-1.5.2-cp38-cp38-win32.whl", hash = "sha256:dac09281a0eacd59974e24525a3bc90fa39b4e95177e638a31b14db60d3fa806"}, 669 | {file = "scipy-1.5.2-cp38-cp38-win_amd64.whl", hash = "sha256:92eb04041d371fea828858e4fff182453c25ae3eaa8782d9b6c32b25857d23bc"}, 670 | {file = "scipy-1.5.2.tar.gz", hash = "sha256:066c513d90eb3fd7567a9e150828d39111ebd88d3e924cdfc9f8ce19ab6f90c9"}, 671 | ] 672 | six = [ 673 | {file = "six-1.15.0-py2.py3-none-any.whl", hash = "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"}, 674 | {file = "six-1.15.0.tar.gz", hash = "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259"}, 675 | ] 676 | threadpoolctl = [ 677 | {file = "threadpoolctl-2.1.0-py3-none-any.whl", hash = "sha256:38b74ca20ff3bb42caca8b00055111d74159ee95c4370882bbff2b93d24da725"}, 678 | {file = "threadpoolctl-2.1.0.tar.gz", hash = "sha256:ddc57c96a38beb63db45d6c159b5ab07b6bced12c45a1f07b2b92f272aebfa6b"}, 679 | ] 680 | toml = [ 681 | {file = "toml-0.10.1-py2.py3-none-any.whl", hash = "sha256:bda89d5935c2eac546d648028b9901107a595863cb36bae0c73ac804a9b4ce88"}, 682 | {file = "toml-0.10.1.tar.gz", hash = "sha256:926b612be1e5ce0634a2ca03470f95169cf16f939018233a670519cb4ac58b0f"}, 683 | ] 684 | typed-ast = [ 685 | {file = "typed_ast-1.4.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3"}, 686 | {file = "typed_ast-1.4.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:aaee9905aee35ba5905cfb3c62f3e83b3bec7b39413f0a7f19be4e547ea01ebb"}, 687 | {file = "typed_ast-1.4.1-cp35-cp35m-win32.whl", hash = "sha256:0c2c07682d61a629b68433afb159376e24e5b2fd4641d35424e462169c0a7919"}, 688 | {file = "typed_ast-1.4.1-cp35-cp35m-win_amd64.whl", hash = "sha256:4083861b0aa07990b619bd7ddc365eb7fa4b817e99cf5f8d9cf21a42780f6e01"}, 689 | {file = "typed_ast-1.4.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:269151951236b0f9a6f04015a9004084a5ab0d5f19b57de779f908621e7d8b75"}, 690 | {file = "typed_ast-1.4.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:24995c843eb0ad11a4527b026b4dde3da70e1f2d8806c99b7b4a7cf491612652"}, 691 | {file = "typed_ast-1.4.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:fe460b922ec15dd205595c9b5b99e2f056fd98ae8f9f56b888e7a17dc2b757e7"}, 692 | {file = "typed_ast-1.4.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:fcf135e17cc74dbfbc05894ebca928ffeb23d9790b3167a674921db19082401f"}, 693 | {file = "typed_ast-1.4.1-cp36-cp36m-win32.whl", hash = "sha256:4e3e5da80ccbebfff202a67bf900d081906c358ccc3d5e3c8aea42fdfdfd51c1"}, 694 | {file = "typed_ast-1.4.1-cp36-cp36m-win_amd64.whl", hash = "sha256:249862707802d40f7f29f6e1aad8d84b5aa9e44552d2cc17384b209f091276aa"}, 695 | {file = "typed_ast-1.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8ce678dbaf790dbdb3eba24056d5364fb45944f33553dd5869b7580cdbb83614"}, 696 | {file = "typed_ast-1.4.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:c9e348e02e4d2b4a8b2eedb48210430658df6951fa484e59de33ff773fbd4b41"}, 697 | {file = "typed_ast-1.4.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:bcd3b13b56ea479b3650b82cabd6b5343a625b0ced5429e4ccad28a8973f301b"}, 698 | {file = "typed_ast-1.4.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:f208eb7aff048f6bea9586e61af041ddf7f9ade7caed625742af423f6bae3298"}, 699 | {file = "typed_ast-1.4.1-cp37-cp37m-win32.whl", hash = "sha256:d5d33e9e7af3b34a40dc05f498939f0ebf187f07c385fd58d591c533ad8562fe"}, 700 | {file = "typed_ast-1.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:0666aa36131496aed8f7be0410ff974562ab7eeac11ef351def9ea6fa28f6355"}, 701 | {file = "typed_ast-1.4.1-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:d205b1b46085271b4e15f670058ce182bd1199e56b317bf2ec004b6a44f911f6"}, 702 | {file = "typed_ast-1.4.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:6daac9731f172c2a22ade6ed0c00197ee7cc1221aa84cfdf9c31defeb059a907"}, 703 | {file = "typed_ast-1.4.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:498b0f36cc7054c1fead3d7fc59d2150f4d5c6c56ba7fb150c013fbc683a8d2d"}, 704 | {file = "typed_ast-1.4.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:7e4c9d7658aaa1fc80018593abdf8598bf91325af6af5cce4ce7c73bc45ea53d"}, 705 | {file = "typed_ast-1.4.1-cp38-cp38-win32.whl", hash = "sha256:715ff2f2df46121071622063fc7543d9b1fd19ebfc4f5c8895af64a77a8c852c"}, 706 | {file = "typed_ast-1.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:fc0fea399acb12edbf8a628ba8d2312f583bdbdb3335635db062fa98cf71fca4"}, 707 | {file = "typed_ast-1.4.1-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34"}, 708 | {file = "typed_ast-1.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:92c325624e304ebf0e025d1224b77dd4e6393f18aab8d829b5b7e04afe9b7a2c"}, 709 | {file = "typed_ast-1.4.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:d648b8e3bf2fe648745c8ffcee3db3ff903d0817a01a12dd6a6ea7a8f4889072"}, 710 | {file = "typed_ast-1.4.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:fac11badff8313e23717f3dada86a15389d0708275bddf766cca67a84ead3e91"}, 711 | {file = "typed_ast-1.4.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:0d8110d78a5736e16e26213114a38ca35cb15b6515d535413b090bd50951556d"}, 712 | {file = "typed_ast-1.4.1-cp39-cp39-win32.whl", hash = "sha256:b52ccf7cfe4ce2a1064b18594381bccf4179c2ecf7f513134ec2f993dd4ab395"}, 713 | {file = "typed_ast-1.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:3742b32cf1c6ef124d57f95be609c473d7ec4c14d0090e5a5e05a15269fb4d0c"}, 714 | {file = "typed_ast-1.4.1.tar.gz", hash = "sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b"}, 715 | ] 716 | typing-extensions = [ 717 | {file = "typing_extensions-3.7.4.3-py2-none-any.whl", hash = "sha256:dafc7639cde7f1b6e1acc0f457842a83e722ccca8eef5270af2d74792619a89f"}, 718 | {file = "typing_extensions-3.7.4.3-py3-none-any.whl", hash = "sha256:7cb407020f00f7bfc3cb3e7881628838e69d8f3fcab2f64742a5e76b2f841918"}, 719 | {file = "typing_extensions-3.7.4.3.tar.gz", hash = "sha256:99d4073b617d30288f569d3f13d2bd7548c3a7e4c8de87db09a9d29bb3a4a60c"}, 720 | ] 721 | urllib3 = [ 722 | {file = "urllib3-1.26.5-py2.py3-none-any.whl", hash = "sha256:753a0374df26658f99d826cfe40394a686d05985786d946fbe4165b5148f5a7c"}, 723 | {file = "urllib3-1.26.5.tar.gz", hash = "sha256:a7acd0977125325f516bda9735fa7142b909a8d01e8b2e4c8108d0984e6e0098"}, 724 | ] 725 | wrapt = [ 726 | {file = "wrapt-1.12.1.tar.gz", hash = "sha256:b62ffa81fb85f4332a4f609cab4ac40709470da05643a082ec1eb88e6d9b97d7"}, 727 | ] 728 | -------------------------------------------------------------------------------- /pylintrc: -------------------------------------------------------------------------------- 1 | [BASIC] 2 | good-names=df 3 | max-line-length=120 4 | max-locals=25 5 | max-args=8 6 | 7 | # C0103: invalid-name, W1202: logging-format-interpolation, R1705: no-else-return 8 | disable=C0103, W1202, R1705 -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "testing-ml" 3 | version = "0.1.0" 4 | description = "" 5 | authors = ["eugeneyan "] 6 | 7 | [tool.poetry.dependencies] 8 | python = "^3.8" 9 | numpy = "^1.19.1" 10 | pandas = "^1.1.1" 11 | scikit-learn = "^0.23.2" 12 | pytest = "^6.0.1" 13 | mypy = "^0.782" 14 | pylint = "^2.6.0" 15 | pytest-cov = "^2.10.1" 16 | codecov = "^2.1.9" 17 | 18 | [tool.poetry.dev-dependencies] 19 | 20 | [build-system] 21 | requires = ["poetry>=0.12"] 22 | build-backend = "poetry.masonry.api" 23 | -------------------------------------------------------------------------------- /src/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eugeneyan/testing-ml/90d18f0977e38dd37fd098f930cfd816d683cc01/src/__init__.py -------------------------------------------------------------------------------- /src/data_prep/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eugeneyan/testing-ml/90d18f0977e38dd37fd098f930cfd816d683cc01/src/data_prep/__init__.py -------------------------------------------------------------------------------- /src/data_prep/categorical.py: -------------------------------------------------------------------------------- 1 | """ 2 | Data preparation methods for categorical variables. 3 | """ 4 | import numpy as np 5 | import pandas as pd 6 | 7 | 8 | def lowercase_string(string: str) -> str: 9 | """Returns a lowercased string 10 | 11 | Args: 12 | string: String to lowercase 13 | 14 | Returns: 15 | String in lowercase 16 | """ 17 | if isinstance(string, str): 18 | return string.lower() 19 | return None 20 | 21 | 22 | def lowercase_column(df: pd.DataFrame, col: str) -> pd.DataFrame: 23 | """Lowercases a column in a dataframe 24 | 25 | Args: 26 | df: DataFrame to lowercase 27 | col: Column in DataFrame to lowercase 28 | 29 | Returns: 30 | A DataFrame with column lowercased 31 | """ 32 | df[col] = df[col].apply(lowercase_string) 33 | return df 34 | 35 | 36 | def extract_title(df: pd.DataFrame, col: str, replace_dict: dict = None, 37 | title_col: str = 'title') -> pd.DataFrame: 38 | """Extracts titles into a new title column 39 | 40 | Args: 41 | df: DataFrame to extract titles from 42 | col: Column in DataFrame to extract titles from 43 | replace_dict (Optional): Optional dictionary to map titles 44 | title_col: Name of new column containing extracted titles 45 | 46 | Returns: 47 | A DataFrame with an additional column of extracted titles 48 | """ 49 | df[title_col] = df[col].str.extract(r' ([A-Za-z]+)\.', expand=False) 50 | 51 | if replace_dict: 52 | df[title_col] = np.where(df[title_col].isin(replace_dict.keys()), 53 | df[title_col].map(replace_dict), 54 | df[title_col]) 55 | 56 | return df 57 | -------------------------------------------------------------------------------- /src/data_prep/continuous.py: -------------------------------------------------------------------------------- 1 | """ 2 | Data preparation methods for continuous variables. 3 | """ 4 | import pandas as pd 5 | 6 | 7 | def fill_numeric(df: pd.DataFrame, col: str, fill_type: str = 'median') -> pd.DataFrame: 8 | """Fills missing values in numeric column specified. 9 | 10 | Args: 11 | df: DataFrame to fill 12 | col: Column in DataFrame to fill 13 | fill_type: How to fill the data. Supported types: "mean", "median", "-1" 14 | 15 | Returns: 16 | A DataFrame with numeric_col filled. 17 | """ 18 | if fill_type == 'median': 19 | fill_value = df[col].median() # type: float 20 | elif fill_type == 'mean': 21 | fill_value = df[col].mean() 22 | elif fill_type == '-1': 23 | fill_value = -1 24 | else: 25 | raise NotImplementedError('Valid fill_type options are "mean", "median", "-1') 26 | 27 | df.loc[df[col].isnull(), col] = fill_value 28 | return df 29 | -------------------------------------------------------------------------------- /src/data_prep/prep_titanic.py: -------------------------------------------------------------------------------- 1 | """ 2 | Data preparation for Titanic data. Includes train-test split and creating of features and labels. 3 | """ 4 | from typing import Tuple 5 | 6 | import pandas as pd 7 | from numpy import array 8 | from sklearn.model_selection import train_test_split 9 | 10 | from src.data_prep.categorical import lowercase_column, extract_title 11 | from src.data_prep.continuous import fill_numeric 12 | 13 | title_mapping = {'mme': 'mrs', 14 | 'ms': 'miss', 15 | 'mlle': 'miss', 16 | 'lady': 'rare', 17 | 'countess': 'rare', 18 | 'capt': 'rare', 19 | 'col': 'rare', 20 | 'don': 'rare', 21 | 'dr': 'rare', 22 | 'major': 'rare', 23 | 'rev': 'rare', 24 | 'sir': 'rare', 25 | 'jonkheer': 'rare', 26 | 'dona': 'rare'} 27 | title_to_int = {'mr': 1, 'mrs': 2, 'miss': 3, 'master': 4, 'rare': 5, 'NA': -1} 28 | sex_to_int = {'female': 1, 'male': 0, 'NA': -1} 29 | port_to_int = {'s': 0, 'c': 1, 'q': 2, 'NA': -1} 30 | 31 | 32 | def load_df() -> pd.DataFrame: 33 | """Return raw Titanic Data 34 | 35 | Returns: 36 | Titanic data loaded from data/titanic.csv 37 | """ 38 | return pd.read_csv('data/titanic.csv') 39 | 40 | 41 | def prep_df(df: pd.DataFrame) -> pd.DataFrame: 42 | """Returns prepared Titanic data. 43 | 44 | Args: 45 | df: Dataframe of raw Titanic data 46 | 47 | Returns: 48 | Prepared Titanic data. 49 | """ 50 | # Lowercase columns 51 | df.columns = [col.lower() for col in df.columns] 52 | 53 | # Drop ticket and cabin col 54 | df.drop(columns=['passengerid', 'ticket', 'cabin'], inplace=True) 55 | 56 | # Create title column 57 | df = lowercase_column(df, 'name') 58 | df = extract_title(df, 'name', title_mapping) 59 | df.drop(columns=['name'], inplace=True) 60 | 61 | # Fill lowercase embarked column 62 | df = lowercase_column(df, 'embarked') 63 | df = lowercase_column(df, 'sex') 64 | 65 | # Fill nulls for numeric cols 66 | for col in ['pclass', 'age', 'sibsp', 'parch', 'fare']: 67 | df = fill_numeric(df, col, '-1') 68 | 69 | # Fill null values and categorical encoding 70 | df['title'].fillna('NA', inplace=True) 71 | df['sex'].fillna('NA', inplace=True) 72 | df['embarked'].fillna('NA', inplace=True) 73 | 74 | df['title'] = df['title'].map(title_to_int) 75 | df['sex'] = df['sex'].map(sex_to_int) 76 | df['embarked'] = df['embarked'].map(port_to_int) 77 | 78 | return df 79 | 80 | 81 | def split_df(df: pd.DataFrame) -> Tuple[pd.DataFrame, pd.DataFrame]: 82 | """Splits processed Titanic data into train and test dataframes. 83 | 84 | Args: 85 | df: Processed Titanic data 86 | 87 | Returns: 88 | Two dataframes, one for train and one for test. 89 | """ 90 | train, test = train_test_split(df, test_size=0.2, random_state=1368, stratify=df['survived']) 91 | 92 | return train, test 93 | 94 | 95 | def get_feats_and_labels(df: pd.DataFrame) -> Tuple[array, array]: 96 | """Returns a tuple of feature array and label vector 97 | 98 | Args: 99 | df: Processed Titanic data 100 | 101 | Returns: 102 | A tuple of feature array and label vector 103 | """ 104 | # Get labels and features 105 | X = df.iloc[:, 1:].values 106 | y = df['survived'].values 107 | 108 | return X, y 109 | -------------------------------------------------------------------------------- /src/tree/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eugeneyan/testing-ml/90d18f0977e38dd37fd098f930cfd816d683cc01/src/tree/__init__.py -------------------------------------------------------------------------------- /src/tree/decision_tree.py: -------------------------------------------------------------------------------- 1 | """ 2 | DecisionTree class 3 | """ 4 | from __future__ import annotations 5 | 6 | from typing import Callable 7 | 8 | import numpy as np 9 | 10 | from src.utils.logger import logger 11 | 12 | 13 | class Node: 14 | """Class for decision tree node.""" 15 | 16 | def __init__(self, left: Node, right: Node, split_function: Callable, leaf_label: int = None): 17 | """Initializes a node that splits data into left and right nodes based on split_function. 18 | 19 | Args: 20 | left: Left child node 21 | right: Right child node 22 | split_function: Callable to decide left or right node 23 | leaf_label: Label for leaf node 24 | """ 25 | self.left = left 26 | self.right = right 27 | self.split_function = split_function 28 | self.leaf_label = leaf_label 29 | 30 | def __str__(self): # pragma: no cover 31 | return self.__class__.__name__ 32 | 33 | def split(self, feature: np.array) -> Node: 34 | """Returns a child node based on split function 35 | 36 | Args: 37 | feature: Feature vector 38 | 39 | Returns: 40 | If leaf node, returns a leaf label. Else, a child node. 41 | """ 42 | if self.leaf_label is not None: 43 | return self.leaf_label # type: ignore 44 | 45 | else: 46 | if self.split_function(feature): 47 | return self.left.split(feature) 48 | else: 49 | return self.right.split(feature) 50 | 51 | 52 | def gini_impurity(labels: np.array) -> float: 53 | """Returns the gini impurity for a lits of labels 54 | 55 | https://en.wikipedia.org/wiki/Decision_tree_learning#Gini_impurity 56 | 57 | Args: 58 | labels: Array of binary labels (1 or 0) 59 | 60 | Returns: 61 | Gini impurity 62 | """ 63 | label_array = np.array(labels) 64 | 65 | prob_pos = len(np.where(label_array == 1)[0]) / len(label_array) 66 | prob_neg = len(np.where(label_array == 0)[0]) / len(label_array) 67 | 68 | return 1 - (prob_pos ** 2 + prob_neg ** 2) 69 | 70 | 71 | def gini_gain(prev_labels: np.array, labels: np.array) -> float: 72 | """Returns the information gain between the previous and current set of labels 73 | 74 | https://en.wikipedia.org/wiki/Decision_tree_learning#Information_gain 75 | 76 | Args: 77 | prev_labels: List of binary labels (1 or 0) 78 | labels: List of List of binary labels (1 or 0) 79 | 80 | Returns: 81 | Information gain 82 | """ 83 | gini_prev = gini_impurity(prev_labels) 84 | len_prev = len(prev_labels) 85 | 86 | gini_current = [gini_impurity(vec) for vec in labels if len(vec) > 0] 87 | weights = [len(vec) / len_prev for vec in labels if len(vec) > 0] 88 | 89 | return gini_prev - sum([weight * gini for weight, gini in zip(weights, gini_current)]) 90 | 91 | 92 | class DecisionTree: 93 | """Class for decision tree.""" 94 | 95 | def __init__(self, depth_limit: int = 99): 96 | """Initializes a decision tree with depth limit 97 | 98 | Args: 99 | depth_limit: Maximum depth to build the tree 100 | """ 101 | self.root = None 102 | self.depth_limit = depth_limit 103 | logger.info('{} initialized with depth limit: {}'.format(self.__class__.__name__, depth_limit)) 104 | 105 | def check_stopping_condition(self, labels: np.array, depth: int) -> bool: 106 | """Checks if stopping conditions (i.e., labels are all same, depth limit reached) has been met 107 | 108 | Args: 109 | labels: Vector of labels 110 | depth: Current depth of tree 111 | 112 | Returns: 113 | True if stopping condition has been met, False otherwise. 114 | """ 115 | if depth == self.depth_limit: # Depth has been reached 116 | return True 117 | elif len(set(labels)) == 1: # All labels are the same 118 | return True 119 | else: 120 | return False 121 | 122 | @staticmethod 123 | def get_percentile_list(n_percentiles: int = 100) -> np.array: 124 | """Returns an array of percentiles. Note: This is used in np.percentile, which requires the sequence of 125 | percentiles to be between 0 to 100 inclusive. 126 | 127 | Args: 128 | n_percentiles: Number of percentiles to split on 129 | 130 | Returns: 131 | Array of percentiles 132 | """ 133 | return np.arange(1, 100, 100 / n_percentiles)[1:] 134 | 135 | @staticmethod 136 | def get_probability(labels: np.array) -> float: 137 | """Returns the majority label 138 | 139 | Args: 140 | labels: 141 | 142 | Returns: 143 | 144 | """ 145 | if len(labels) > 0: 146 | return labels.mean() 147 | return None # type: ignore # pragma: no cover 148 | 149 | def __build_tree__(self, features: np.array, labels: np.array, depth: int = 0) -> Node: 150 | """Build decision tree that learns split functions. 151 | 152 | Args: 153 | features: 154 | labels: 155 | depth: 156 | 157 | Returns: 158 | Decision tree root node 159 | """ 160 | n_percentiles = max(2, int(len(labels) / 10)) 161 | 162 | if self.check_stopping_condition(labels, depth): 163 | prob = self.get_probability(labels) 164 | return Node(None, None, None, prob) # type: ignore 165 | 166 | else: 167 | logger.debug('Features: {}'.format(features)) 168 | logger.debug('Labels: {}'.format(labels)) 169 | splits = np.percentile(features, self.get_percentile_list(n_percentiles), axis=0) 170 | 171 | best_split = None 172 | best_split_feat_idx = None 173 | best_split_gini_gain = float('-inf') 174 | 175 | for feat_idx, feat_col in enumerate(features.T): # Transpose to loop through columns 176 | logger.debug('Col index: {}'.format(feat_idx)) 177 | 178 | for split in splits[:, feat_idx]: 179 | labels_left = labels[np.where(feat_col < split)] 180 | labels_right = labels[np.where(feat_col >= split)] 181 | 182 | gain = gini_gain(labels, [labels_left, labels_right]) 183 | 184 | if gain > best_split_gini_gain: 185 | best_split_gini_gain, best_split, best_split_feat_idx = gain, split, feat_idx 186 | 187 | split_left = np.where(features[:, best_split_feat_idx] < best_split) 188 | split_right = np.where(features[:, best_split_feat_idx] >= best_split) 189 | logger.debug('Split left: {} | right: {}'.format(split_left, split_right)) 190 | 191 | features_left, features_right = features[split_left], features[split_right] 192 | labels_left, labels_right = labels[split_left], labels[split_right] 193 | 194 | # If either node is empty after splitting 195 | if len(labels_left) == 0: 196 | node_left = Node(None, None, None, self.get_probability(labels)) # type: ignore 197 | node_right = self.__build_tree__(features_right, labels_right, depth + 1) 198 | elif len(labels_right) == 0: # pragma: no cover 199 | node_left = self.__build_tree__(features_left, labels_left, depth + 1) 200 | node_right = Node(None, None, None, self.get_probability(labels)) # type: ignore 201 | else: 202 | node_left = self.__build_tree__(features_left, labels_left, depth + 1) 203 | node_right = self.__build_tree__(features_right, labels_right, depth + 1) 204 | 205 | return Node(node_left, node_right, lambda feature: feature[best_split_feat_idx] < best_split) 206 | 207 | def fit(self, features: np.array, labels: np.array): 208 | """Build decision tree 209 | 210 | Args: 211 | features: 212 | labels: 213 | 214 | Returns: 215 | None 216 | """ 217 | self.root = self.__build_tree__(features, labels) # type: ignore 218 | 219 | def predict(self, features: np.array) -> np.array: 220 | """Returns labels given a set of features. 221 | 222 | Args: 223 | features: Numpy array of features with shape (row x col) 224 | 225 | Returns: 226 | Predicted labels 227 | """ 228 | labels = np.array([self.root.split(row) for row in features]) # type: ignore 229 | 230 | return labels 231 | -------------------------------------------------------------------------------- /src/tree/random_forest.py: -------------------------------------------------------------------------------- 1 | """ 2 | RandomForest class 3 | """ 4 | from typing import List 5 | 6 | import numpy as np 7 | 8 | from src.tree.decision_tree import DecisionTree, Node 9 | from src.utils.logger import logger 10 | 11 | 12 | class RandomForest(DecisionTree): 13 | """Class for RandomForest (of DecisionTrees).""" 14 | 15 | def __init__(self, num_trees: int, row_subsampling: float, col_subsampling: float, 16 | depth_limit: int = 99, seed: int = 1368): 17 | """Initializes a decision tree with depth limit 18 | 19 | Args: 20 | num_trees: 21 | row_subsampling: 22 | col_subsampling: 23 | depth_limit: Maximum depth to build the tree 24 | """ 25 | super().__init__(depth_limit) 26 | self.trees: List[Node] = [] 27 | self.num_trees = num_trees 28 | self.row_subsampling = row_subsampling 29 | self.col_subsampling = col_subsampling 30 | self.col_idxs: List[np.array] = [] 31 | np.random.seed(seed) 32 | 33 | def fit(self, features: np.array, labels: np.array) -> None: 34 | """Builds a random forest of decision trees. 35 | 36 | Args: 37 | features: 38 | labels: 39 | 40 | Returns: 41 | None 42 | """ 43 | n_rows, n_cols = features.shape 44 | 45 | for i in range(self.num_trees): 46 | logger.debug('{} training tree: {}'.format(self.__class__.__name__, i + 1)) 47 | shuffled_row_idx = np.random.permutation(n_rows) 48 | shuffled_col_idx = np.random.permutation(n_cols) 49 | 50 | row_idx = np.random.choice(shuffled_row_idx, int(self.row_subsampling * n_rows), replace=False) 51 | col_idx = np.random.choice(shuffled_col_idx, int(self.col_subsampling * n_cols), replace=False) 52 | self.col_idxs.append(col_idx) 53 | 54 | features_subsampled = features[np.ix_(row_idx, col_idx)] 55 | labels_subsampled = labels[row_idx] 56 | 57 | self.trees.append(self.__build_tree__(features_subsampled, labels_subsampled)) 58 | 59 | def predict(self, features: np.array) -> np.array: 60 | """Returns labels given a set of features. 61 | 62 | Args: 63 | features: Numpy array of features with shape (row x col) 64 | 65 | Returns: 66 | Predicted labels 67 | """ 68 | labels_list = [] 69 | 70 | for tree, col_idx in zip(self.trees, self.col_idxs): 71 | logger.debug('Col index: {}'.format(col_idx)) 72 | features_subsampled = features[:, col_idx] 73 | labels_list.append([tree.split(row) for row in features_subsampled]) 74 | 75 | labels = np.array(labels_list).mean(axis=0) 76 | 77 | return labels 78 | -------------------------------------------------------------------------------- /src/utils/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eugeneyan/testing-ml/90d18f0977e38dd37fd098f930cfd816d683cc01/src/utils/__init__.py -------------------------------------------------------------------------------- /src/utils/logger.py: -------------------------------------------------------------------------------- 1 | """ 2 | Logger utility 3 | """ 4 | import datetime 5 | import logging 6 | import os 7 | 8 | 9 | def get_file_handler(job: str, log_path: str, log_variables=None): 10 | """ 11 | Get a file handler to write logs to 12 | 13 | Args: 14 | job: Name of job 15 | log_path: Dir path to write log to 16 | log_variables: Variables to be in the log name 17 | 18 | Returns: 19 | File handler 20 | 21 | Examples: 22 | fh = get_file_handler('ar-poc', '../') 23 | logger.addHandler(fh) 24 | """ 25 | if log_variables is None: 26 | log_variables = [] 27 | log_path = os.path.join(os.getcwd(), log_path, job) 28 | current_datetime = datetime.datetime.now().strftime('%Y-%m-%d-%H%M') 29 | log_name = log_path + '_'.join([''] + log_variables) + '_' + current_datetime + '.log' 30 | fh = logging.FileHandler(os.path.join(os.getcwd(), log_path, log_name), encoding='utf8') 31 | fh.setFormatter(logging.Formatter('%(asctime)s - %(message)s')) 32 | fh.setLevel(logging.DEBUG) 33 | return fh 34 | 35 | 36 | logger = logging.getLogger(__name__) 37 | logger.setLevel(logging.INFO) 38 | formatter = logging.Formatter('%(asctime)s - %(message)s') 39 | 40 | # create console handler and set level to info 41 | ch = logging.StreamHandler() 42 | ch.setFormatter(formatter) 43 | ch.setLevel(logging.INFO) 44 | 45 | # add ch to logger 46 | logger.addHandler(ch) 47 | -------------------------------------------------------------------------------- /src/utils/timer.py: -------------------------------------------------------------------------------- 1 | """ 2 | Logger utility 3 | """ 4 | from functools import wraps 5 | from time import perf_counter 6 | from typing import Callable 7 | from typing import Tuple 8 | 9 | import numpy as np 10 | 11 | 12 | def timer(func: Callable) -> Callable: 13 | """Decorator to time a function. 14 | 15 | Args: 16 | func: Function to time 17 | 18 | Returns: 19 | Function results and time (in seconds) 20 | """ 21 | 22 | @wraps(func) 23 | def wrapper(*args, **kwargs): 24 | start = perf_counter() 25 | results = func(*args, **kwargs) 26 | end = perf_counter() 27 | run_time = end - start 28 | return results, run_time 29 | 30 | return wrapper 31 | 32 | 33 | @timer 34 | def fit_with_time(model, X_train: np.array, y_train: np.array) -> Tuple: 35 | """Returns trained model with the time 36 | 37 | Args: 38 | model: Model to test latency on 39 | X_test: Input data 40 | 41 | Returns: 42 | Predicted values and time taken to predict it 43 | """ 44 | return model.fit(X_train, y_train) 45 | 46 | 47 | @timer 48 | def predict_with_time(model, X_test: np.array) -> Tuple[np.array]: 49 | """Returns model output with the time 50 | 51 | Args: 52 | model: Model to test latency on 53 | X_test: Input data 54 | 55 | Returns: 56 | Predicted values and time taken to predict it 57 | """ 58 | return model.predict(X_test) 59 | -------------------------------------------------------------------------------- /testing-ml-flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eugeneyan/testing-ml/90d18f0977e38dd37fd098f930cfd816d683cc01/testing-ml-flow.png -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eugeneyan/testing-ml/90d18f0977e38dd37fd098f930cfd816d683cc01/tests/__init__.py -------------------------------------------------------------------------------- /tests/data_prep/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eugeneyan/testing-ml/90d18f0977e38dd37fd098f930cfd816d683cc01/tests/data_prep/__init__.py -------------------------------------------------------------------------------- /tests/data_prep/test_categorical.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import pytest 3 | 4 | from src.data_prep.categorical import lowercase_string, lowercase_column, extract_title 5 | 6 | 7 | @pytest.fixture 8 | def dummy_df(): 9 | string_col = ['Futrelle, Mme. Jacques Heath (Lily May Peel)', 10 | 'Johnston, Ms. Catherine Helen "Carrie"', 11 | 'Sloper, Mr. William Thompson', 12 | 'Ostby, Lady. Engelhart Cornelius', 13 | 'Backstrom, Major. Karl Alfred (Maria Mathilda Gustafsson)'] 14 | df_dict = {'string': string_col} 15 | df = pd.DataFrame(df_dict) 16 | return df 17 | 18 | 19 | @pytest.fixture 20 | def lowercased_df(): 21 | string_col = ['futrelle, mme. jacques heath (lily may peel)', 22 | 'johnston, ms. catherine helen "carrie"', 23 | 'sloper, mr. william thompson', 24 | 'ostby, lady. engelhart cornelius', 25 | 'backstrom, major. karl alfred (maria mathilda gustafsson)'] 26 | df_dict = {'string': string_col} 27 | df = pd.DataFrame(df_dict) 28 | return df 29 | 30 | 31 | def test_lowercase_string(): 32 | assert lowercase_string('abc') == 'abc' 33 | assert lowercase_string('ABC') == 'abc' 34 | assert lowercase_string('Abc123') == 'abc123' 35 | assert lowercase_string(1) is None 36 | 37 | 38 | def test_lowercase_column(dummy_df, lowercased_df): 39 | actual_df = lowercase_column(dummy_df, col='string') 40 | assert actual_df.equals(lowercased_df) 41 | 42 | 43 | def test_extract_title(lowercased_df): 44 | result = extract_title(lowercased_df, col='string') 45 | assert result['title'].tolist() == ['mme', 'ms', 'mr', 'lady', 'major'] 46 | 47 | title_replacement = {'mme': 'mrs', 'ms': 'miss', 'lady': 'rare', 'major': 'rare'} 48 | result = extract_title(lowercased_df, col='string', replace_dict=title_replacement) 49 | assert result['title'].tolist() == ['mrs', 'miss', 'mr', 'rare', 'rare'] 50 | -------------------------------------------------------------------------------- /tests/data_prep/test_continuous.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import pytest 3 | 4 | from src.data_prep.continuous import fill_numeric 5 | 6 | 7 | @pytest.fixture 8 | def dummy_df(): 9 | int_col = [1, None, 4, 2, 100] 10 | float_col = [100.234, 0.0, None, None, 9.19] 11 | df_dict = {'int': int_col, 'float': float_col} 12 | df = pd.DataFrame(df_dict) 13 | return df 14 | 15 | 16 | def test_fill_numeric_default(dummy_df): 17 | result_int = fill_numeric(dummy_df, col='int') 18 | result_float = fill_numeric(dummy_df, col='float') 19 | assert result_int['int'].tolist() == [1.0, 3.0, 4.0, 2.0, 100.0] 20 | assert result_float['float'].tolist() == [100.234, 0.0, 9.19, 9.19, 9.19] 21 | 22 | 23 | def test_fill_numeric_median(dummy_df): 24 | result_int = fill_numeric(dummy_df, col='int', fill_type='median') 25 | result_float = fill_numeric(dummy_df, col='float', fill_type='median') 26 | assert result_int['int'].tolist() == [1.0, 3.0, 4.0, 2.0, 100.0] 27 | assert result_float['float'].tolist() == [100.234, 0.0, 9.19, 9.19, 9.19] 28 | 29 | 30 | def test_fill_numeric_mean(dummy_df): 31 | result_int = fill_numeric(dummy_df, col='int', fill_type='mean') 32 | result_float = fill_numeric(dummy_df, col='float', fill_type='mean') 33 | assert result_int['int'].tolist() == [1.0, 26.75, 4.0, 2.0, 100.0] 34 | assert result_float['float'].tolist() == [100.234, 0.0, 36.474666666666664, 36.474666666666664, 9.19] 35 | 36 | 37 | def test_fill_numeric_minus1(dummy_df): 38 | result_int = fill_numeric(dummy_df, col='int', fill_type='-1') 39 | result_float = fill_numeric(dummy_df, col='float', fill_type='-1') 40 | assert result_int['int'].tolist() == [1.0, -1, 4.0, 2.0, 100.0] 41 | assert result_float['float'].tolist() == [100.234, 0.0, -1.0, -1.0, 9.19] 42 | 43 | 44 | def test_fill_numeric_not_implemented(dummy_df): 45 | with pytest.raises(NotImplementedError): 46 | fill_numeric(dummy_df, col='int', fill_type='random') 47 | -------------------------------------------------------------------------------- /tests/data_prep/test_prep_titanic.py: -------------------------------------------------------------------------------- 1 | from src.data_prep.prep_titanic import load_df, prep_df, split_df, get_feats_and_labels 2 | 3 | 4 | # Assert data set shape 5 | def test_prep_steps(): 6 | df = load_df() 7 | df = prep_df(df) 8 | 9 | train, test = split_df(df) 10 | X_train, y_train = get_feats_and_labels(train) 11 | X_test, y_test = get_feats_and_labels(test) 12 | 13 | assert X_train.shape == (712, 8) 14 | assert y_train.shape == (712,) 15 | assert X_test.shape == (179, 8) 16 | assert y_test.shape == (179,) 17 | -------------------------------------------------------------------------------- /tests/tree/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eugeneyan/testing-ml/90d18f0977e38dd37fd098f930cfd816d683cc01/tests/tree/__init__.py -------------------------------------------------------------------------------- /tests/tree/fixtures.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | import numpy as np 3 | 4 | from src.data_prep.prep_titanic import load_df, prep_df, split_df, get_feats_and_labels 5 | from src.tree.decision_tree import DecisionTree 6 | from src.tree.random_forest import RandomForest 7 | 8 | 9 | @pytest.fixture 10 | def dummy_feats_and_labels(): 11 | feats = np.array([[0.7057, -5.4981, 8.3368, -2.8715], 12 | [2.4391, 6.4417, -0.80743, -0.69139], 13 | [-0.2062, 9.2207, -3.7044, -6.8103], 14 | [4.2586, 11.2962, -4.0943, -4.3457], 15 | [-2.343, 12.9516, 3.3285, -5.9426], 16 | [-2.0545, -10.8679, 9.4926, -1.4116], 17 | [2.2279, 4.0951, -4.8037, -2.1112], 18 | [-6.1632, 8.7096, -0.21621, -3.6345], 19 | [0.52374, 3.644, -4.0746, -1.9909], 20 | [1.5077, 1.9596, -3.0584, -0.12243] 21 | ]) 22 | labels = np.array([1, 1, 1, 1, 1, 0, 0, 0, 0, 0]) 23 | return feats, labels 24 | 25 | 26 | @pytest.fixture 27 | def dummy_titanic(): 28 | df = load_df() 29 | df = prep_df(df) 30 | 31 | train, test = split_df(df) 32 | X_train, y_train = get_feats_and_labels(train) 33 | X_test, y_test = get_feats_and_labels(test) 34 | return X_train, y_train, X_test, y_test 35 | 36 | 37 | @pytest.fixture 38 | def dummy_titanic_df(): 39 | df = load_df() 40 | df.columns = [col.lower() for col in df.columns] 41 | 42 | train, test = split_df(df) 43 | return train, test 44 | 45 | 46 | @pytest.fixture 47 | def dummy_passengers(): 48 | # Based on passenger 1 (low passenger class male) 49 | passenger1 = {'PassengerId': 1, 50 | 'Survived': None, 51 | 'Pclass': 3, 52 | 'Name': ' Mr. Owen', 53 | 'Sex': 'male', 54 | 'Age': 22.0, 55 | 'SibSp': 1, 56 | 'Parch': 0, 57 | 'Ticket': 'A/5 21171', 58 | 'Fare': 7.25, 59 | 'Cabin': None, 60 | 'Embarked': 'S'} 61 | 62 | # Based on passenger 2 (high passenger class female) 63 | passenger2 = {'PassengerId': 2, 64 | 'Survived': None, 65 | 'Pclass': 1, 66 | 'Name': ' Mrs. John', 67 | 'Sex': 'female', 68 | 'Age': 38.0, 69 | 'SibSp': 1, 70 | 'Parch': 0, 71 | 'Ticket': 'PC 17599', 72 | 'Fare': 71.2833, 73 | 'Cabin': 'C85', 74 | 'Embarked': 'C'} 75 | 76 | return passenger1, passenger2 77 | 78 | 79 | @pytest.fixture 80 | def dummy_titanic_dt(dummy_titanic): 81 | X_train, y_train, _, _ = dummy_titanic 82 | dt = DecisionTree(depth_limit=5) 83 | dt.fit(X_train, y_train) 84 | return dt 85 | 86 | 87 | @pytest.fixture 88 | def dummy_titanic_rf(dummy_titanic): 89 | X_train, y_train, _, _ = dummy_titanic 90 | rf = RandomForest(num_trees=8, depth_limit=5, col_subsampling=0.8, row_subsampling=0.8) 91 | rf.fit(X_train, y_train) 92 | return rf 93 | -------------------------------------------------------------------------------- /tests/tree/test_decision_tree_1pre.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pandas as pd 3 | from sklearn.metrics import accuracy_score, roc_auc_score 4 | 5 | from src.tree.decision_tree import gini_gain, gini_impurity, DecisionTree 6 | from tests.tree.fixtures import dummy_feats_and_labels, dummy_titanic, dummy_titanic_df 7 | 8 | 9 | def test_gini_impurity(): 10 | assert round(gini_impurity([1, 1, 1, 1, 1, 1, 1, 1]), 3) == 0 11 | assert round(gini_impurity([1, 1, 1, 1, 1, 1, 1, 0]), 3) == 0.219 12 | assert round(gini_impurity([1, 1, 1, 1, 1, 1, 0, 0]), 3) == 0.375 13 | assert round(gini_impurity([1, 1, 1, 1, 1, 0, 0, 0]), 3) == 0.469 14 | assert round(gini_impurity([1, 1, 1, 1, 0, 0, 0, 0]), 3) == 0.500 15 | assert round(gini_impurity([1, 1, 0, 0, 0, 0, 0, 0]), 3) == 0.375 16 | 17 | 18 | def test_gini_gain(): 19 | assert round(gini_gain([1, 1, 1, 1, 0, 0, 0, 0], [[1, 1, 1, 1], [0, 0, 0, 0]]), 3) == 0.5 20 | assert round(gini_gain([1, 1, 1, 1, 0, 0, 0, 0], [[1, 1, 1, 0], [0, 0, 0, 1]]), 3) == 0.125 21 | assert round(gini_gain([1, 1, 1, 1, 0, 0, 0, 0], [[1, 0, 0, 0], [0, 1, 1, 1]]), 3) == 0.125 22 | assert round(gini_gain([1, 1, 1, 1, 0, 0, 0, 0], [[1, 1, 0, 0], [0, 0, 1, 1]]), 3) == 0.0 23 | 24 | 25 | # Check model prediction to ensure same shape as labels 26 | def test_dt_output_shape(dummy_feats_and_labels, dummy_titanic): 27 | feats, labels = dummy_feats_and_labels 28 | dt = DecisionTree() 29 | dt.fit(feats, labels) 30 | pred = dt.predict(feats) 31 | 32 | assert pred.shape == (feats.shape[0],), 'DecisionTree output should be same as training labels.' 33 | 34 | X_train, y_train, X_test, y_test = dummy_titanic 35 | dt = DecisionTree() 36 | dt.fit(X_train, y_train) 37 | pred_train = dt.predict(X_train) 38 | pred_test = dt.predict(X_test) 39 | 40 | assert pred_train.shape == (X_train.shape[0],), 'DecisionTree output should be same as training labels.' 41 | assert pred_test.shape == (X_test.shape[0],), 'DecisionTree output should be same as testing labels.' 42 | 43 | 44 | # Check model prediction to ensure output ranges from 0 to 1 inclusive 45 | def test_dt_output_range(dummy_feats_and_labels, dummy_titanic): 46 | feats, labels = dummy_feats_and_labels 47 | dt = DecisionTree() 48 | dt.fit(feats, labels) 49 | pred = dt.predict(feats) 50 | 51 | assert (pred <= 1).all() & (pred >= 0).all(), 'Decision tree output should range from 0 to 1 inclusive' 52 | 53 | X_train, y_train, X_test, y_test = dummy_titanic 54 | dt = DecisionTree() 55 | dt.fit(X_train, y_train) 56 | pred_train = dt.predict(X_train) 57 | pred_test = dt.predict(X_test) 58 | 59 | assert (pred_train <= 1).all() & (pred_train >= 0).all(), 'Decision tree output should range from 0 to 1 inclusive' 60 | assert (pred_test <= 1).all() & (pred_test >= 0).all(), 'Decision tree output should range from 0 to 1 inclusive' 61 | 62 | 63 | # Check if model can overfit perfectly 64 | def test_dt_overfit(dummy_feats_and_labels, dummy_titanic): 65 | feats, labels = dummy_feats_and_labels 66 | dt = DecisionTree() 67 | dt.fit(feats, labels) 68 | pred = np.round(dt.predict(feats)) 69 | 70 | assert np.array_equal(labels, pred), 'DecisionTree should fit data perfectly and prediction should == labels.' 71 | 72 | X_train, y_train, X_test, y_test = dummy_titanic 73 | dt = DecisionTree() 74 | dt.fit(X_train, y_train) 75 | 76 | pred_train = dt.predict(X_train) 77 | pred_train_binary = np.round(pred_train) 78 | acc_train = accuracy_score(y_train, pred_train_binary) 79 | auc_train = roc_auc_score(y_train, pred_train) 80 | 81 | assert acc_train > 0.97, 'Accuracy on train should be > 0.97' 82 | assert auc_train > 0.99, 'AUC ROC on train should be > 0.99' 83 | 84 | 85 | # Check if additional tree depth increases accuracy and AUC ROC 86 | def test_dt_increase_acc(dummy_titanic): 87 | X_train, y_train, _, _ = dummy_titanic 88 | 89 | acc_list, auc_list = [], [] 90 | for depth in range(1, 10): 91 | dt = DecisionTree(depth_limit=depth) 92 | dt.fit(X_train, y_train) 93 | pred = dt.predict(X_train) 94 | pred_binary = np.round(pred) 95 | acc_list.append(accuracy_score(y_train, pred_binary)) 96 | auc_list.append(roc_auc_score(y_train, pred)) 97 | 98 | assert sorted(acc_list) == acc_list, 'Accuracy should increase as tree depth increases.' 99 | assert sorted(auc_list) == auc_list, 'AUC ROC should increase as tree depth increases.' 100 | 101 | 102 | # Check if any records in our test set are also in our train set 103 | def test_data_leak_in_test_data(dummy_titanic_df): 104 | train, test = dummy_titanic_df 105 | 106 | concat_df = pd.concat([train, test]) 107 | concat_df.drop_duplicates(inplace=True) 108 | 109 | assert concat_df.shape[0] == train.shape[0] + test.shape[0] 110 | -------------------------------------------------------------------------------- /tests/tree/test_decision_tree_2post.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | 3 | from src.data_prep.prep_titanic import prep_df, get_feats_and_labels 4 | from tests.tree.fixtures import dummy_titanic_dt, dummy_passengers, dummy_titanic 5 | 6 | 7 | # Check if changing certain inputs will keep outputs constant 8 | def test_dt_invariance(dummy_titanic_dt, dummy_passengers): 9 | model = dummy_titanic_dt 10 | p1, p2 = dummy_passengers 11 | 12 | # Get original survival probability of passenger 1 13 | test_df = pd.DataFrame.from_dict([p1], orient='columns') 14 | X, y = get_feats_and_labels(prep_df(test_df)) 15 | p1_prob = model.predict(X)[0] # 0.09 16 | 17 | # Change name from Owen to Mary (without changing gender or title) 18 | p1_name = p1.copy() 19 | p1_name['Name'] = ' Mr. Mary' 20 | test_df = pd.DataFrame.from_dict([p1_name], orient='columns') 21 | X, y = get_feats_and_labels(prep_df(test_df)) 22 | p1_name_prob = model.predict(X)[0] # 0.09 23 | 24 | # Change ticket number from 'A/5 21171' to 'PC 17599' 25 | p1_ticket = p1.copy() 26 | p1_ticket['ticket'] = 'PC 17599' 27 | test_df = pd.DataFrame.from_dict([p1_ticket], orient='columns') 28 | X, y = get_feats_and_labels(prep_df(test_df)) 29 | p1_ticket_prob = model.predict(X)[0] # 0.09 30 | 31 | # Change embarked port from 'S' to 'C' 32 | p1_port = p1.copy() 33 | p1_port['Embarked'] = 'C' 34 | test_df = pd.DataFrame.from_dict([p1_port], orient='columns') 35 | X, y = get_feats_and_labels(prep_df(test_df)) 36 | p1_port_prob = model.predict(X)[0] # 0.09 37 | 38 | # Get original survival probability of passenger 2 39 | test_df = pd.DataFrame.from_dict([p2], orient='columns') 40 | X, y = get_feats_and_labels(prep_df(test_df)) 41 | p2_prob = model.predict(X)[0] # 1.0 42 | 43 | # Change name from John to Berns (without changing gender or title) 44 | p2_name = p2.copy() 45 | p2_name['Name'] = ' Mrs. Berns' 46 | test_df = pd.DataFrame.from_dict([p2_name], orient='columns') 47 | X, y = get_feats_and_labels(prep_df(test_df)) 48 | p2_name_prob = model.predict(X)[0] # 1.0 49 | 50 | # Change ticket number from 'PC 17599' to 'A/5 21171' 51 | p2_ticket = p2.copy() 52 | p2_ticket['ticket'] = 'A/5 21171' 53 | test_df = pd.DataFrame.from_dict([p2_ticket], orient='columns') 54 | X, y = get_feats_and_labels(prep_df(test_df)) 55 | p2_ticket_prob = model.predict(X)[0] # 1.0 56 | 57 | # Change embarked port from 'C' to 'Q' 58 | p2_port = p2.copy() 59 | p2_port['Embarked'] = 'Q' 60 | test_df = pd.DataFrame.from_dict([p2_port], orient='columns') 61 | X, y = get_feats_and_labels(prep_df(test_df)) 62 | p2_port_prob = model.predict(X)[0] # 1.0 63 | 64 | assert p1_prob == p1_name_prob == p1_ticket_prob == p1_port_prob 65 | assert p2_prob == p2_name_prob == p2_ticket_prob == p2_port_prob 66 | 67 | 68 | # Check if changing input (e.g., gender, passenger class) will affect survival probability in expected direction 69 | def test_dt_directional_expectation(dummy_titanic_dt, dummy_passengers): 70 | model = dummy_titanic_dt 71 | p1, p2 = dummy_passengers 72 | 73 | # Get original survival probability of passenger 1 74 | test_df = pd.DataFrame.from_dict([p1], orient='columns') 75 | X, y = get_feats_and_labels(prep_df(test_df)) 76 | p1_prob = model.predict(X)[0] # 0.09 77 | 78 | # Change gender from male to female 79 | p1_female = p1.copy() 80 | p1_female['Name'] = ' Mrs. Owen' 81 | p1_female['Sex'] = 'female' 82 | test_df = pd.DataFrame.from_dict([p1_female], orient='columns') 83 | X, y = get_feats_and_labels(prep_df(test_df)) 84 | p1_female_prob = model.predict(X)[0] # 0.65 85 | 86 | # Change passenger class from 3 to 1 87 | p1_class = p1.copy() 88 | p1_class['Pclass'] = 1 89 | test_df = pd.DataFrame.from_dict([p1_class], orient='columns') 90 | X, y = get_feats_and_labels(prep_df(test_df)) 91 | p1_class_prob = model.predict(X)[0] # 0.36 92 | 93 | assert p1_prob < p1_female_prob, 'Changing gender from male to female should increase survival probability.' 94 | assert p1_prob < p1_class_prob, 'Changing class from 3 to 1 should increase survival probability.' 95 | 96 | # Get original survival probability of passenger 2 97 | test_df = pd.DataFrame.from_dict([p2], orient='columns') 98 | X, y = get_feats_and_labels(prep_df(test_df)) 99 | p2_prob = model.predict(X)[0] # 1.0 100 | 101 | # Change gender from female to male 102 | p2_male = p2.copy() 103 | p2_male['Name'] = ' Mr. John' 104 | p2_male['Sex'] = 'male' 105 | test_df = pd.DataFrame.from_dict([p2_male], orient='columns') 106 | X, y = get_feats_and_labels(prep_df(test_df)) 107 | p2_male_prob = model.predict(X)[0] # 0.56 108 | 109 | # Change class from 1 to 3 110 | p2_class = p2.copy() 111 | p2_class['Pclass'] = 3 112 | test_df = pd.DataFrame.from_dict([p2_class], orient='columns') 113 | X, y = get_feats_and_labels(prep_df(test_df)) 114 | p2_class_prob = model.predict(X)[0] # 0.0 115 | 116 | # Lower fare from 71.2833 to 5 117 | p2_fare = p2.copy() 118 | p2_fare['Fare'] = 5 119 | test_df = pd.DataFrame.from_dict([p2_fare], orient='columns') 120 | X, y = get_feats_and_labels(prep_df(test_df)) 121 | p2_fare_prob = model.predict(X)[0] # 0.85 122 | 123 | assert p2_prob > p2_male_prob, 'Changing gender from female to male should decrease survival probability.' 124 | assert p2_prob > p2_class_prob, 'Changing class from 1 to 3 should decrease survival probability.' 125 | assert p2_prob > p2_fare_prob, 'Changing fare from 72 to 5 should decrease survival probability.' 126 | -------------------------------------------------------------------------------- /tests/tree/test_decision_tree_3eval.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from sklearn.metrics import accuracy_score, roc_auc_score 3 | 4 | from src.tree.decision_tree import DecisionTree 5 | from src.utils.timer import fit_with_time, predict_with_time 6 | from tests.tree.fixtures import dummy_titanic_dt, dummy_titanic 7 | 8 | 9 | # DecisionTree evaluation 10 | def test_dt_evaluation(dummy_titanic_dt, dummy_titanic): 11 | model = dummy_titanic_dt 12 | X_train, y_train, X_test, y_test = dummy_titanic 13 | 14 | pred_train = model.predict(X_train) 15 | pred_train_binary = np.round(pred_train) 16 | acc_train = accuracy_score(y_train, pred_train_binary) 17 | auc_train = roc_auc_score(y_train, pred_train) 18 | 19 | assert acc_train > 0.85, 'Accuracy on train should be > 0.85' 20 | assert auc_train > 0.90, 'AUC ROC on train should be > 0.90' 21 | 22 | pred_test = model.predict(X_test) 23 | pred_test_binary = np.round(pred_test) 24 | acc_test = accuracy_score(y_test, pred_test_binary) 25 | auc_test = roc_auc_score(y_test, pred_test) 26 | 27 | assert acc_test > 0.82, 'Accuracy on test should be > 0.82' 28 | assert auc_test > 0.84, 'AUC ROC on test should be > 0.84' 29 | 30 | 31 | def test_dt_training_time(dummy_titanic): 32 | X_train, y_train, X_test, y_test = dummy_titanic 33 | 34 | # Standardize to use depth = 10 35 | dt = DecisionTree(depth_limit=10) 36 | latency_array = np.array([fit_with_time(dt, X_train, y_train)[1] for i in range(50)]) 37 | time_p95 = np.quantile(latency_array, 0.95) 38 | assert time_p95 < 1.0, 'Training time at 95th percentile should be < 1.0 sec' 39 | 40 | 41 | def test_dt_serving_latency(dummy_titanic): 42 | X_train, y_train, X_test, y_test = dummy_titanic 43 | 44 | # Standardize to use depth = 10 45 | dt = DecisionTree(depth_limit=10) 46 | dt.fit(X_train, y_train) 47 | 48 | latency_array = np.array([predict_with_time(dt, X_test)[1] for i in range(200)]) 49 | latency_p99 = np.quantile(latency_array, 0.99) 50 | assert latency_p99 < 0.004, 'Serving latency at 99th percentile should be < 0.004 sec' 51 | -------------------------------------------------------------------------------- /tests/tree/test_random_forest_1pre.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from sklearn.metrics import accuracy_score, roc_auc_score 3 | 4 | from src.tree.random_forest import RandomForest, DecisionTree 5 | from tests.tree.fixtures import dummy_feats_and_labels, dummy_titanic 6 | 7 | 8 | # Check if model can overfit perfectly 9 | def test_rf_overfit(dummy_feats_and_labels): 10 | feats, labels = dummy_feats_and_labels 11 | dt = RandomForest(1, 1, 1) 12 | dt.fit(feats, labels) 13 | pred = np.round(dt.predict(feats)) 14 | assert np.array_equal(labels, pred), 'RandomForest should fit data perfectly with single tree and no subsampling.' 15 | 16 | 17 | # Check if additional bagged trees increases accuracy and AUC ROC 18 | def test_rf_increase_acc(dummy_titanic): 19 | X_train, y_train, X_test, y_test = dummy_titanic 20 | 21 | acc_list, acc_list = [], [] 22 | auc_list = [] 23 | for num_trees in [1, 3, 7, 15]: 24 | rf = RandomForest(num_trees=num_trees, depth_limit=7, col_subsampling=0.7, row_subsampling=0.7) 25 | rf.fit(X_train, y_train) 26 | pred = rf.predict(X_test) 27 | pred_binary = np.round(pred) 28 | acc_list.append(accuracy_score(y_test, pred_binary)) 29 | auc_list.append(roc_auc_score(y_test, pred)) 30 | 31 | assert sorted(acc_list) == acc_list, 'Accuracy should increase as number of trees increases.' 32 | assert sorted(auc_list) == auc_list, 'AUC ROC should increase as number of trees increases.' 33 | 34 | 35 | # Check if RandomForest is an improvement over DecisionTree on test set 36 | def test_rf_better_than_dt(dummy_titanic): 37 | X_train, y_train, X_test, y_test = dummy_titanic 38 | 39 | dt = DecisionTree(depth_limit=10) 40 | dt.fit(X_train, y_train) 41 | 42 | rf = RandomForest(depth_limit=10, num_trees=7, col_subsampling=0.8, row_subsampling=0.8) 43 | rf.fit(X_train, y_train) 44 | 45 | pred_test_dt = dt.predict(X_test) 46 | pred_test_binary_dt = np.round(pred_test_dt) 47 | acc_test_dt = accuracy_score(y_test, pred_test_binary_dt) 48 | auc_test_dt = roc_auc_score(y_test, pred_test_dt) 49 | 50 | pred_test_rf = rf.predict(X_test) 51 | pred_test_binary_rf = np.round(pred_test_rf) 52 | acc_test_rf = accuracy_score(y_test, pred_test_binary_rf) 53 | auc_test_rf = roc_auc_score(y_test, pred_test_rf) 54 | 55 | assert acc_test_rf > acc_test_dt, 'RandomForest should have higher accuracy than DecisionTree on test set.' 56 | assert auc_test_rf > auc_test_dt, 'RandomForest should have higher AUC ROC than DecisionTree on test set.' 57 | -------------------------------------------------------------------------------- /tests/tree/test_random_forest_2post.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | 3 | from src.data_prep.prep_titanic import prep_df, get_feats_and_labels 4 | from tests.tree.fixtures import dummy_titanic_rf, dummy_passengers, dummy_titanic 5 | 6 | 7 | # Check if changing certain inputs will keep outputs constant 8 | def test_rf_invariance(dummy_titanic_rf, dummy_passengers): 9 | model = dummy_titanic_rf 10 | p1, p2 = dummy_passengers 11 | 12 | # Get original survival probability of passenger 1 13 | test_df = pd.DataFrame.from_dict([p1], orient='columns') 14 | X, y = get_feats_and_labels(prep_df(test_df)) 15 | p1_prob = model.predict(X)[0] # 0.09 16 | 17 | # Change name from Owen to Mary (without changing gender or title) 18 | p1_name = p1.copy() 19 | p1_name['Name'] = ' Mr. Mary' 20 | test_df = pd.DataFrame.from_dict([p1_name], orient='columns') 21 | X, y = get_feats_and_labels(prep_df(test_df)) 22 | p1_name_prob = model.predict(X)[0] # 0.09 23 | 24 | # Change ticket number from 'A/5 21171' to 'PC 17599' 25 | p1_ticket = p1.copy() 26 | p1_ticket['ticket'] = 'PC 17599' 27 | test_df = pd.DataFrame.from_dict([p1_ticket], orient='columns') 28 | X, y = get_feats_and_labels(prep_df(test_df)) 29 | p1_ticket_prob = model.predict(X)[0] # 0.09 30 | 31 | # Change embarked port from 'S' to 'C' 32 | p1_port = p1.copy() 33 | p1_port['Embarked'] = 'C' 34 | test_df = pd.DataFrame.from_dict([p1_port], orient='columns') 35 | X, y = get_feats_and_labels(prep_df(test_df)) 36 | p1_port_prob = model.predict(X)[0] # 0.09 37 | 38 | # Get original survival probability of passenger 2 39 | test_df = pd.DataFrame.from_dict([p2], orient='columns') 40 | X, y = get_feats_and_labels(prep_df(test_df)) 41 | p2_prob = model.predict(X)[0] # 1.0 42 | 43 | # Change name from John to Berns (without changing gender or title) 44 | p2_name = p2.copy() 45 | p2_name['Name'] = ' Mrs. Berns' 46 | test_df = pd.DataFrame.from_dict([p2_name], orient='columns') 47 | X, y = get_feats_and_labels(prep_df(test_df)) 48 | p2_name_prob = model.predict(X)[0] # 1.0 49 | 50 | # Change ticket number from 'PC 17599' to 'A/5 21171' 51 | p2_ticket = p2.copy() 52 | p2_ticket['ticket'] = 'A/5 21171' 53 | test_df = pd.DataFrame.from_dict([p2_ticket], orient='columns') 54 | X, y = get_feats_and_labels(prep_df(test_df)) 55 | p2_ticket_prob = model.predict(X)[0] # 1.0 56 | 57 | # Change embarked port from 'C' to 'Q' 58 | p2_port = p2.copy() 59 | p2_port['Embarked'] = 'Q' 60 | test_df = pd.DataFrame.from_dict([p2_port], orient='columns') 61 | X, y = get_feats_and_labels(prep_df(test_df)) 62 | p2_port_prob = model.predict(X)[0] # 1.0 63 | 64 | assert p1_prob == p1_name_prob == p1_ticket_prob == p1_port_prob 65 | assert p2_prob == p2_name_prob == p2_ticket_prob == p2_port_prob 66 | 67 | 68 | # Check if changing input (e.g., gender, passenger class) will affect survival probability in expected direction 69 | def test_rf_directional_expectation(dummy_titanic_rf, dummy_passengers): 70 | model = dummy_titanic_rf 71 | p1, p2 = dummy_passengers 72 | 73 | # Get original survival probability of passenger 1 74 | test_df = pd.DataFrame.from_dict([p1], orient='columns') 75 | X, y = get_feats_and_labels(prep_df(test_df)) 76 | p1_prob = model.predict(X)[0] # 0.09 77 | 78 | # Change gender from male to female 79 | p1_female = p1.copy() 80 | p1_female['Name'] = ' Mrs. Owen' 81 | p1_female['Sex'] = 'female' 82 | test_df = pd.DataFrame.from_dict([p1_female], orient='columns') 83 | X, y = get_feats_and_labels(prep_df(test_df)) 84 | p1_female_prob = model.predict(X)[0] # 0.65 85 | 86 | # Change passenger class from 3 to 1 87 | p1_class = p1.copy() 88 | p1_class['Pclass'] = 1 89 | test_df = pd.DataFrame.from_dict([p1_class], orient='columns') 90 | X, y = get_feats_and_labels(prep_df(test_df)) 91 | p1_class_prob = model.predict(X)[0] # 0.36 92 | 93 | assert p1_prob < p1_female_prob, 'Changing gender from male to female should increase survival probability.' 94 | assert p1_prob < p1_class_prob, 'Changing class from 3 to 1 should increase survival probability.' 95 | 96 | # Get original survival probability of passenger 2 97 | test_df = pd.DataFrame.from_dict([p2], orient='columns') 98 | X, y = get_feats_and_labels(prep_df(test_df)) 99 | p2_prob = model.predict(X)[0] # 1.0 100 | 101 | # Change gender from female to male 102 | p2_male = p2.copy() 103 | p2_male['Name'] = ' Mr. John' 104 | p2_male['Sex'] = 'male' 105 | test_df = pd.DataFrame.from_dict([p2_male], orient='columns') 106 | X, y = get_feats_and_labels(prep_df(test_df)) 107 | p2_male_prob = model.predict(X)[0] # 0.56 108 | 109 | # Change class from 1 to 3 110 | p2_class = p2.copy() 111 | p2_class['Pclass'] = 3 112 | test_df = pd.DataFrame.from_dict([p2_class], orient='columns') 113 | X, y = get_feats_and_labels(prep_df(test_df)) 114 | p2_class_prob = model.predict(X)[0] # 0.0 115 | 116 | # Lower fare from 71.2833 to 5 117 | p2_fare = p2.copy() 118 | p2_fare['Fare'] = 5 119 | test_df = pd.DataFrame.from_dict([p2_fare], orient='columns') 120 | X, y = get_feats_and_labels(prep_df(test_df)) 121 | p2_fare_prob = model.predict(X)[0] # 0.85 122 | 123 | assert p2_prob > p2_male_prob, 'Changing gender from female to male should decrease survival probability.' 124 | assert p2_prob > p2_class_prob, 'Changing class from 1 to 3 should decrease survival probability.' 125 | assert p2_prob > p2_fare_prob, 'Changing fare from 72 to 5 should decrease survival probability.' 126 | -------------------------------------------------------------------------------- /tests/tree/test_random_forest_3eval.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from sklearn.metrics import accuracy_score, roc_auc_score 3 | 4 | from src.tree.random_forest import RandomForest 5 | from src.utils.timer import predict_with_time, fit_with_time 6 | from tests.tree.fixtures import dummy_titanic_rf, dummy_titanic 7 | 8 | 9 | # RandomForest evaluation 10 | def test_rf_evaluation(dummy_titanic_rf, dummy_titanic): 11 | model = dummy_titanic_rf 12 | X_train, y_train, X_test, y_test = dummy_titanic 13 | 14 | pred_train = model.predict(X_train) 15 | pred_train_binary = np.round(pred_train) 16 | acc_train = accuracy_score(y_train, pred_train_binary) 17 | auc_train = roc_auc_score(y_train, pred_train) 18 | 19 | assert acc_train > 0.84, 'Accuracy on train should be > 0.84' 20 | assert auc_train > 0.91, 'AUC ROC on train should be > 0.90' 21 | 22 | pred_test = model.predict(X_test) 23 | pred_test_binary = np.round(pred_test) 24 | acc_test = accuracy_score(y_test, pred_test_binary) 25 | auc_test = roc_auc_score(y_test, pred_test) 26 | 27 | assert acc_test > 0.84, 'Accuracy on test should be > 0.84' 28 | assert auc_test > 0.86, 'AUC ROC on test should be > 0.86' 29 | 30 | 31 | def test_rf_training_time(dummy_titanic): 32 | X_train, y_train, X_test, y_test = dummy_titanic 33 | 34 | # Standardize to use depth = 10 35 | rf = RandomForest(depth_limit=10, num_trees=5, col_subsampling=0.8, row_subsampling=0.8) 36 | latency_array = np.array([fit_with_time(rf, X_train, y_train)[1] for i in range(20)]) 37 | time_p95 = np.quantile(latency_array, 0.95) 38 | assert time_p95 < 3, 'Training time at 95th percentile should be < 3.0 sec' 39 | 40 | 41 | def test_rf_serving_latency(dummy_titanic): 42 | X_train, y_train, X_test, y_test = dummy_titanic 43 | 44 | # Standardize to use depth = 10 45 | rf = RandomForest(depth_limit=10, num_trees=5, col_subsampling=0.8, row_subsampling=0.8) 46 | rf.fit(X_train, y_train) 47 | 48 | latency_array = np.array([predict_with_time(rf, X_test)[1] for i in range(200)]) 49 | latency_p99 = np.quantile(latency_array, 0.99) 50 | assert latency_p99 < 0.018, 'Serving latency at 99th percentile should be < 0.018 sec' 51 | --------------------------------------------------------------------------------