├── .gitignore
├── .tmux.conf
├── LICENSE
├── README.md
├── dataset
├── PreprocessData.csv
└── data.csv
├── images
├── 1.png
├── 2.png
├── 3.png
└── 4.png
├── notebooks
├── VisualizePreprocess.ipynb
└── training_models.ipynb
└── scripts
├── bash
├── git_star_pred_DO_conf cmds
└── settingUpDOServer.sh
├── nodejs
├── getting_repos_v2.js
├── githubGraphQLApiCallsDO_V2.js
├── githubGraphQLApiCallsDO_V3.js
├── graphql queries
├── package.json
├── test.js
└── test3.js
└── python
├── json_to_csv.py
└── merge.py
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 |
6 | # Runtime data
7 | pids
8 | *.pid
9 | *.seed
10 |
11 | # Directory for instrumented libs generated by jscoverage/JSCover
12 | lib-cov
13 |
14 | # Coverage directory used by tools like istanbul
15 | coverage
16 |
17 | # nyc test coverage
18 | .nyc_output
19 |
20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
21 | .grunt
22 |
23 | # node-waf configuration
24 | .lock-wscript
25 |
26 | # Compiled binary addons (http://nodejs.org/api/addons.html)
27 | build/Release
28 |
29 | # Dependency directories
30 | node_modules
31 | jspm_packages
32 |
33 | # Optional npm cache directory
34 | .npm
35 |
36 | # Optional REPL history
37 | .node_repl_history
38 |
39 | # Custom Files
40 | scripts/nodejs/.env
41 | .idea/
42 | dist
43 | data/
44 | scripts/nodejs/node_modules
45 | notebooks/.ipynb_checkpoints/
46 | notebooks/tpot.ipynb
--------------------------------------------------------------------------------
/.tmux.conf:
--------------------------------------------------------------------------------
1 | # force a reload of the config file
2 | unbind r
3 | bind r source-file ~/.tmux.conf
4 |
5 | # behavior
6 | set -g base-index 1 # start window numbering from 1 instead of 0
7 | setw -g automatic-rename on # automatically name windows
8 | set -g set-titles on # auto set the terminal's window title
9 | set -g mouse on # enable mouse
10 |
11 |
12 | # Set the default terminal mode to 256color mode
13 | set -g default-terminal "screen-256color"
14 |
15 | # enable activity alerts
16 | setw -g monitor-activity on
17 | set -g visual-activity on
18 |
19 | # Center the window list
20 | set -g status-justify centre
21 |
22 |
23 | # appearance
24 | set -g default-terminal "screen-256color" # full colors for apps
25 | set -g status-left-length 45
26 | set -g status-left '⣿ #[underscore]#20H#[default]:#[fg=black]#S#[default] ⡇'
27 | set -g status-right ' ⣿ '
28 | setw -g window-status-format ' #I #W ' # window name formatting
29 | setw -g window-status-current-format ' #I #W '
30 | set -g status-bg colour3 # dark yellow status bar
31 | setw -g window-status-bg colour240 # dark grey window name bg
32 | setw -g window-status-fg white
33 | setw -g window-status-current-bg red # red bg for active window
34 | setw -g window-status-current-fg white
35 | setw -g window-status-current-attr bold
36 | setw -g window-status-attr bold
37 | set -g set-titles-string '[#I] #W'
38 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 AlphaMinds
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 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Github Repo Stars Predictor
2 |
3 | ## Overview
4 | It's a github repo star predictor that tries to predict the stars of
5 | any github repository having greater than 100 stars. It predicts based on
6 | the owner/organization's status and activities (commits, forks, comments,
7 | branches, update rate, etc.) on the repository. Different types of models
8 | (Gradient boost, Deep neural network, etc) have been tested successfully
9 | on the dataset we fetched from github apis.
10 |
11 | ## Dataset
12 | We used the github REST api and GraphQL api to collect data of repositories
13 | having more than 100 stars. The data is available in the dataset directory
14 | We were able to collect the data faster using the Digital Ocean's multiple
15 | servers. So we thanks [Digital Ocean](http://digitalocean.com) for providing
16 | free credits to students to use servers. For the details on dataset features
17 | refer the summary section below.
18 |
19 | ## Tools used
20 | - Python 2.7
21 | - Jupyter Notebook
22 | - NumPy
23 | - Sklearn
24 | - Pandas
25 | - Keras
26 | - Cat Boost
27 | - Matplot Lib
28 | - seaborn
29 |
30 | We also used [Google Colab's](http://colab.research.google.com/) GPU notebooks.
31 | So we thank to Google for starting thier colab project for
32 | providing GPUs
33 |
34 | ## Code details
35 | Below is a brief description for the Code files/folder in repo.
36 |
37 | ### Bash Script
38 | - **settingUpDOServer.sh**
39 | filepath: scripts/bash/settingUpDOServer.sh
40 | This is used for configuring the digital ocean server
41 |
42 | ### NodeJs scripts
43 | - **getting_repos_v2.js**
44 | filepath: scripts/nodejs/getting_repos_v2.js
45 | This script fetches the basic info of repos having more than 100 stars using the Github REST API
46 |
47 | - **githubGraphQLApiCallsDO_V2.js**
48 | filepath: scripts/nodejs/githubGraphQLApiCallsDO_V2.js
49 | This script fetches the complete info of the repositories that were fetched by the above
50 | script and uses the Github GraphQL API. It follows the approach of fetching the data
51 | at the fixed rate defined in env file (eg. 730ms per request)
52 |
53 | - **githubGraphQLApiCallsDO_V3.js**
54 | filepath: scripts/nodejs/githubGraphQLApiCallsDO_V3.js
55 | This script fetches the complete info of the repositories that were fetched by the above
56 | script and uses the Github GraphQL API. It follows the approach of requesting data for
57 | next repo after receiving the response of the already sent request.
58 |
59 | ### Python scripts
60 | - **json_to_csv.py**
61 | filepath: scripts/python/json_to_csv.py
62 | This script converts the json data fetched from Github's GraphQL API in the above script to the
63 | equivalent csv file.
64 |
65 | - **merge.py**
66 | filepath: scripts/python/merge.py
67 | This scripts merges all the data in multiple csv files to a single csv file
68 |
69 | ### Jupyter Notebooks
70 | - **VisualizePreprocess.ipynb**
71 | filepath: notebooks/VisualizePreprocess.ipynb
72 | We have done the feature engineering task in this notebook. It visualises the data and correspondingly
73 | creates new features, modifies existing features and removes redundant features. For details
74 | on features created, check the summary below
75 |
76 | - **training_models.ipynb**
77 | filepath: notebooks/training_models.ipynb
78 | In this notebook, we trained different models with hyper parameter tuning on our dataset and compared their result in the end.
79 | For details on models trained, their prediction scores, etc. check the summary below.
80 |
81 | ## Summary
82 | In this project we have tried to predict the number of stars
83 | of a github repository that have more than 100 stars. For this we have
84 | taken the github repository data from github REST api and GraphQL api.
85 | After generating the dataset we visualized and did some feature engineering
86 | with the dataset and after that , finally we come up to the stage where we
87 | applied various models and predicted the model's scores on training and
88 | test data.
89 |
90 | ### Feature Engineering
91 | There are total of 49 features before pre-processing. After pre-processing (adding new features, removal of redundant features and
92 | modifying existing features) the count changes to 54. All the features are listed below.
93 | Some features after pre-processing may not be clear. Please refer to the VisualizePreprocess.ipynb notebook for details.
94 |
95 |
96 | #### Original Features
97 | column 1 | column 2 | column 3
98 | ------------ | ------------- | -------------
99 | branches | commits | createdAt
100 | description | diskUsage | followers
101 | following | forkCount | gistComments
102 | gistStar | gists | hasWikiEnabled
103 | iClosedComments | iClosedParticipants | iOpenComments
104 | iOpenParticipants | isArchived | issuesClosed
105 | issuesOpen | license | location
106 | login | members | organizations
107 | prClosed | prClosedComments | prClosedCommits
108 | prMerged | prMergedComments | prMergedCommits
109 | prOpen | prOpenComments | prOpenCommits
110 | primaryLanguage | pushedAt | readmeCharCount
111 | readmeLinkCount | readmeSize | readmeWordCount
112 | releases | reponame | repositories
113 | siteAdmin | stars | subscribersCount
114 | tags | type | updatedAt
115 | websiteUrl |
116 |
117 | #### Features after pre-processing
118 | column 1 | column 2 | column 3
119 | ------------ | ------------- | -------------
120 | branches | commits | createdAt
121 | diskUsage | followers | following
122 | forkCount | gistComments | gistStar
123 | gists | hasWikiEnabled | iClosedComments
124 | iClosedParticipants | iOpenComments | iOpenParticipants
125 | issuesClosed | issuesOpen | members
126 | organizations | prClosed | prClosedComments
127 | prClosedCommits | prMerged | prMergedComments
128 | prMergedCommits | prOpen | prOpenComments
129 | prOpenCommits | pushedAt | readmeCharCount
130 | readmeLinkCount | readmeSize | readmeWordCount
131 | releases | repositories | subscribersCount
132 | tags | type | updatedAt
133 | websiteUrl | desWordCount | desCharCount
134 | mit_license | nan_license | apache_license
135 | other_license | remain_license | JavaScript
136 | Python | Java | Objective
137 | Ruby | PHP | other_language
138 |
139 |
140 | ### Models Trained
141 | - **Gradient Boost Regressor**
142 | - **Cat Boost Regressor**
143 | - **Random Forest Regressor**
144 | - **Deep Neural Network**
145 |
146 | ### Evaluation Metrics
147 | - **R^2 score**
148 | 
149 |
150 | ### Results
151 | 
152 |
--------------------------------------------------------------------------------
/images/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Doodies/Github-Stars-Predictor/dc8c16a0516fe85ec130caadde5c577493860cb6/images/1.png
--------------------------------------------------------------------------------
/images/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Doodies/Github-Stars-Predictor/dc8c16a0516fe85ec130caadde5c577493860cb6/images/2.png
--------------------------------------------------------------------------------
/images/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Doodies/Github-Stars-Predictor/dc8c16a0516fe85ec130caadde5c577493860cb6/images/3.png
--------------------------------------------------------------------------------
/images/4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Doodies/Github-Stars-Predictor/dc8c16a0516fe85ec130caadde5c577493860cb6/images/4.png
--------------------------------------------------------------------------------
/notebooks/training_models.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 6,
6 | "metadata": {
7 | "colab": {
8 | "autoexec": {
9 | "startup": false,
10 | "wait_interval": 0
11 | },
12 | "base_uri": "https://localhost:8080/",
13 | "height": 312,
14 | "output_extras": [
15 | {
16 | "item_id": 3
17 | }
18 | ]
19 | },
20 | "colab_type": "code",
21 | "executionInfo": {
22 | "elapsed": 2079,
23 | "status": "ok",
24 | "timestamp": 1519120778768,
25 | "user": {
26 | "displayName": "Pawan Bansal",
27 | "photoUrl": "//lh4.googleusercontent.com/-hQniqzw3AW0/AAAAAAAAAAI/AAAAAAAAAGs/dTfAX9OOw5w/s50-c-k-no/photo.jpg",
28 | "userId": "102337886470920224775"
29 | },
30 | "user_tz": -330
31 | },
32 | "id": "mKFskImGo9qc",
33 | "outputId": "d5204a20-3b54-4176-a625-fbcb8302e98d"
34 | },
35 | "outputs": [
36 | {
37 | "name": "stdout",
38 | "output_type": "stream",
39 | "text": [
40 | "--2018-02-20 09:59:37-- http://=/\n",
41 | "Resolving = (=)... failed: Name or service not known.\n",
42 | "wget: unable to resolve host address ‘=’\n",
43 | "--2018-02-20 09:59:37-- https://raw.githubusercontent.com/Doodies/Github-Stars-Predictor/master/PreprocessData.csv\n",
44 | "Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 151.101.0.133, 151.101.64.133, 151.101.128.133, ...\n",
45 | "Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|151.101.0.133|:443... connected.\n",
46 | "HTTP request sent, awaiting response... 200 OK\n",
47 | "Length: 18616347 (18M) [text/plain]\n",
48 | "Saving to: ‘PreprocessData.csv’\n",
49 | "\n",
50 | "PreprocessData.csv 100%[===================>] 17.75M 38.4MB/s in 0.5s \n",
51 | "\n",
52 | "2018-02-20 09:59:38 (38.4 MB/s) - ‘PreprocessData.csv’ saved [18616347/18616347]\n",
53 | "\n",
54 | "FINISHED --2018-02-20 09:59:38--\n",
55 | "Total wall clock time: 0.9s\n",
56 | "Downloaded: 1 files, 18M in 0.5s (38.4 MB/s)\n"
57 | ]
58 | }
59 | ],
60 | "source": [
61 | "!wget = 'https://raw.githubusercontent.com/Doodies/Github-Stars-Predictor/master/PreprocessData.csv'"
62 | ]
63 | },
64 | {
65 | "cell_type": "code",
66 | "execution_count": 7,
67 | "metadata": {
68 | "colab": {
69 | "autoexec": {
70 | "startup": false,
71 | "wait_interval": 0
72 | },
73 | "base_uri": "https://localhost:8080/",
74 | "height": 69,
75 | "output_extras": [
76 | {
77 | "item_id": 1
78 | }
79 | ]
80 | },
81 | "colab_type": "code",
82 | "executionInfo": {
83 | "elapsed": 981,
84 | "status": "ok",
85 | "timestamp": 1519120781777,
86 | "user": {
87 | "displayName": "Pawan Bansal",
88 | "photoUrl": "//lh4.googleusercontent.com/-hQniqzw3AW0/AAAAAAAAAAI/AAAAAAAAAGs/dTfAX9OOw5w/s50-c-k-no/photo.jpg",
89 | "userId": "102337886470920224775"
90 | },
91 | "user_tz": -330
92 | },
93 | "id": "CJaU70pspQCu",
94 | "outputId": "affdb0a4-3b24-4ba6-83ef-bf17f20739ed"
95 | },
96 | "outputs": [
97 | {
98 | "name": "stdout",
99 | "output_type": "stream",
100 | "text": [
101 | "total 18M\r\n",
102 | "drwxr-xr-x 1 root root 4.0K Feb 20 09:22 datalab\r\n",
103 | "-rw-r--r-- 1 root root 18M Feb 20 09:59 PreprocessData.csv\r\n"
104 | ]
105 | }
106 | ],
107 | "source": [
108 | "!ls -lh"
109 | ]
110 | },
111 | {
112 | "cell_type": "markdown",
113 | "metadata": {
114 | "colab_type": "text",
115 | "id": "yGS-YGdiqIEq"
116 | },
117 | "source": [
118 | "# Importing required modules"
119 | ]
120 | },
121 | {
122 | "cell_type": "code",
123 | "execution_count": 0,
124 | "metadata": {
125 | "colab": {
126 | "autoexec": {
127 | "startup": false,
128 | "wait_interval": 0
129 | }
130 | },
131 | "colab_type": "code",
132 | "collapsed": true,
133 | "id": "umNFuu0-xEGK"
134 | },
135 | "outputs": [],
136 | "source": [
137 | "!pip install catboost ipywidgets\n",
138 | "!pip install xgboost\n",
139 | "!pip install keras"
140 | ]
141 | },
142 | {
143 | "cell_type": "code",
144 | "execution_count": 2,
145 | "metadata": {
146 | "colab": {
147 | "autoexec": {
148 | "startup": false,
149 | "wait_interval": 0
150 | }
151 | },
152 | "colab_type": "code",
153 | "id": "MkaUKVnepe07"
154 | },
155 | "outputs": [
156 | {
157 | "name": "stderr",
158 | "output_type": "stream",
159 | "text": [
160 | "Using Theano backend.\n"
161 | ]
162 | },
163 | {
164 | "ename": "ImportError",
165 | "evalue": "No module named theano",
166 | "output_type": "error",
167 | "traceback": [
168 | "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
169 | "\u001b[0;31mImportError\u001b[0m Traceback (most recent call last)",
170 | "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 27\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0msklearn\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mensemble\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mRandomForestRegressor\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 28\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 29\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0mkeras\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmodels\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mSequential\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 30\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mkeras\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlayers\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mDense\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mDropout\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mBatchNormalization\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 31\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mkeras\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mwrappers\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mscikit_learn\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mKerasRegressor\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
171 | "\u001b[0;32m/home/pawan/anaconda3/envs/env2.7/lib/python2.7/site-packages/keras/__init__.py\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0m__future__\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mabsolute_import\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mutils\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 4\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mactivations\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mapplications\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
172 | "\u001b[0;32m/home/pawan/anaconda3/envs/env2.7/lib/python2.7/site-packages/keras/utils/__init__.py\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mdata_utils\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mio_utils\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 6\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mconv_utils\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 7\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 8\u001b[0m \u001b[0;31m# Globally-importable utils.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
173 | "\u001b[0;32m/home/pawan/anaconda3/envs/env2.7/lib/python2.7/site-packages/keras/utils/conv_utils.py\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 7\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0msix\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmoves\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mrange\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 8\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mnumpy\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 9\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m\u001b[0;34m.\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mbackend\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0mK\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 10\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 11\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
174 | "\u001b[0;32m/home/pawan/anaconda3/envs/env2.7/lib/python2.7/site-packages/keras/backend/__init__.py\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 79\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0m_BACKEND\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;34m'theano'\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 80\u001b[0m \u001b[0msys\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mstderr\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mwrite\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'Using Theano backend.\\n'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 81\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m\u001b[0mtheano_backend\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 82\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0m_BACKEND\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;34m'tensorflow'\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 83\u001b[0m \u001b[0msys\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mstderr\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mwrite\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'Using TensorFlow backend.\\n'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
175 | "\u001b[0;32m/home/pawan/anaconda3/envs/env2.7/lib/python2.7/site-packages/keras/backend/theano_backend.py\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mcollections\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mdefaultdict\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 6\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mcontextlib\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mcontextmanager\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 7\u001b[0;31m \u001b[0;32mimport\u001b[0m \u001b[0mtheano\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 8\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mtheano\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mtensor\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0mT\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 9\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mtheano\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msandbox\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrng_mrg\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mMRG_RandomStreams\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0mRandomStreams\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
176 | "\u001b[0;31mImportError\u001b[0m: No module named theano"
177 | ]
178 | }
179 | ],
180 | "source": [
181 | "# Handle table-like data and matrices\n",
182 | "import numpy as np\n",
183 | "import pandas as pd\n",
184 | "\n",
185 | "# Visualisation\n",
186 | "import matplotlib as mpl\n",
187 | "import matplotlib.pyplot as plt\n",
188 | "import matplotlib.pylab as pylab\n",
189 | "import seaborn as sns\n",
190 | "\n",
191 | "# Configure visualisations\n",
192 | "%matplotlib inline\n",
193 | "color = sns.color_palette()\n",
194 | "pd.options.mode.chained_assignment = None\n",
195 | "pd.options.display.max_columns = 999\n",
196 | "# mpl.style.use( 'ggplot' )\n",
197 | "sns.set_style( 'whitegrid' )\n",
198 | "pylab.rcParams[ 'figure.figsize' ] = 10,8\n",
199 | "seed = 7\n",
200 | "\n",
201 | "# importing libraries\n",
202 | "from sklearn.preprocessing import StandardScaler\n",
203 | "from sklearn.model_selection import train_test_split\n",
204 | "from sklearn.metrics import r2_score, mean_squared_error\n",
205 | "from sklearn.ensemble import GradientBoostingRegressor\n",
206 | "from catboost import CatBoostRegressor\n",
207 | "from sklearn.ensemble import RandomForestRegressor\n",
208 | "\n",
209 | "from keras.models import Sequential\n",
210 | "from keras.layers import Dense, Dropout, BatchNormalization\n",
211 | "from keras.wrappers.scikit_learn import KerasRegressor\n",
212 | "from sklearn.model_selection import cross_val_score, KFold\n",
213 | "from sklearn.pipeline import Pipeline\n",
214 | "\n",
215 | "np.random.seed(seed)"
216 | ]
217 | },
218 | {
219 | "cell_type": "code",
220 | "execution_count": 5,
221 | "metadata": {
222 | "colab": {
223 | "autoexec": {
224 | "startup": false,
225 | "wait_interval": 0
226 | }
227 | },
228 | "colab_type": "code",
229 | "collapsed": true,
230 | "id": "IJ4mvGdrpmTN"
231 | },
232 | "outputs": [],
233 | "source": [
234 | "data = pd.read_csv('../dataset/PreprocessData.csv').iloc[:, 1:]"
235 | ]
236 | },
237 | {
238 | "cell_type": "code",
239 | "execution_count": 6,
240 | "metadata": {
241 | "colab": {
242 | "autoexec": {
243 | "startup": false,
244 | "wait_interval": 0
245 | }
246 | },
247 | "colab_type": "code",
248 | "collapsed": true,
249 | "id": "YHMzBJLtp73R"
250 | },
251 | "outputs": [],
252 | "source": [
253 | "X = data.drop(['stars'] , axis =1)\n",
254 | "y = data.stars"
255 | ]
256 | },
257 | {
258 | "cell_type": "markdown",
259 | "metadata": {
260 | "colab_type": "text",
261 | "id": "BYAwV5zRqDfT"
262 | },
263 | "source": [
264 | "# Feature normalization"
265 | ]
266 | },
267 | {
268 | "cell_type": "code",
269 | "execution_count": 0,
270 | "metadata": {
271 | "colab": {
272 | "autoexec": {
273 | "startup": false,
274 | "wait_interval": 0
275 | }
276 | },
277 | "colab_type": "code",
278 | "collapsed": true,
279 | "id": "UsGtaizwp_Sq"
280 | },
281 | "outputs": [],
282 | "source": [
283 | "s = StandardScaler()\n",
284 | "X = s.fit_transform(X)"
285 | ]
286 | },
287 | {
288 | "cell_type": "code",
289 | "execution_count": 107,
290 | "metadata": {
291 | "colab": {
292 | "autoexec": {
293 | "startup": false,
294 | "wait_interval": 0
295 | },
296 | "base_uri": "https://localhost:8080/",
297 | "height": 243,
298 | "output_extras": [
299 | {
300 | "item_id": 1
301 | }
302 | ]
303 | },
304 | "colab_type": "code",
305 | "executionInfo": {
306 | "elapsed": 803,
307 | "status": "ok",
308 | "timestamp": 1519125771476,
309 | "user": {
310 | "displayName": "Pawan Bansal",
311 | "photoUrl": "//lh4.googleusercontent.com/-hQniqzw3AW0/AAAAAAAAAAI/AAAAAAAAAGs/dTfAX9OOw5w/s50-c-k-no/photo.jpg",
312 | "userId": "102337886470920224775"
313 | },
314 | "user_tz": -330
315 | },
316 | "id": "ipEcS8nmqC4v",
317 | "outputId": "6e653f89-1d99-4465-eca3-67442598c20a"
318 | },
319 | "outputs": [
320 | {
321 | "data": {
322 | "text/plain": [
323 | "array([[-0.09745647, 0.00614558, 0.23250482, ..., -0.23044367,\n",
324 | " -0.22388323, -0.84232977],\n",
325 | " [-0.09745647, -0.08776201, 0.23293463, ..., -0.23044367,\n",
326 | " -0.22388323, -0.84232977],\n",
327 | " [-0.09745647, -0.09548965, 0.23228991, ..., -0.23044367,\n",
328 | " -0.22388323, 1.1871835 ],\n",
329 | " ...,\n",
330 | " [ 0.00197165, -0.0922978 , 0.23218246, ..., -0.23044367,\n",
331 | " -0.22388323, 1.1871835 ],\n",
332 | " [-0.07259944, -0.11128091, 0.23223618, ..., -0.23044367,\n",
333 | " -0.22388323, 1.1871835 ],\n",
334 | " [-0.09745647, -0.10741709, 0.23304208, ..., -0.23044367,\n",
335 | " -0.22388323, 1.1871835 ]])"
336 | ]
337 | },
338 | "execution_count": 107,
339 | "metadata": {
340 | "tags": []
341 | },
342 | "output_type": "execute_result"
343 | }
344 | ],
345 | "source": [
346 | "X"
347 | ]
348 | },
349 | {
350 | "cell_type": "markdown",
351 | "metadata": {
352 | "colab_type": "text",
353 | "id": "OYVDATBlqNOq"
354 | },
355 | "source": [
356 | "# train test data splitting"
357 | ]
358 | },
359 | {
360 | "cell_type": "code",
361 | "execution_count": 0,
362 | "metadata": {
363 | "colab": {
364 | "autoexec": {
365 | "startup": false,
366 | "wait_interval": 0
367 | }
368 | },
369 | "colab_type": "code",
370 | "collapsed": true,
371 | "id": "Hg2sfmChqLFZ"
372 | },
373 | "outputs": [],
374 | "source": [
375 | "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.10, random_state=42)"
376 | ]
377 | },
378 | {
379 | "cell_type": "code",
380 | "execution_count": 0,
381 | "metadata": {
382 | "colab": {
383 | "autoexec": {
384 | "startup": false,
385 | "wait_interval": 0
386 | }
387 | },
388 | "colab_type": "code",
389 | "collapsed": true,
390 | "id": "pS1m7NZgqO28"
391 | },
392 | "outputs": [],
393 | "source": [
394 | "training_scores = []\n",
395 | "test_scores = []\n",
396 | "models = []"
397 | ]
398 | },
399 | {
400 | "cell_type": "markdown",
401 | "metadata": {
402 | "colab_type": "text",
403 | "id": "F0DCAR2DqSRD"
404 | },
405 | "source": [
406 | "\n",
407 | "# Training Models"
408 | ]
409 | },
410 | {
411 | "cell_type": "markdown",
412 | "metadata": {
413 | "colab_type": "text",
414 | "id": "mZTYSuGZqWkt"
415 | },
416 | "source": [
417 | "## 1. Gradient Boost"
418 | ]
419 | },
420 | {
421 | "cell_type": "code",
422 | "execution_count": 0,
423 | "metadata": {
424 | "colab": {
425 | "autoexec": {
426 | "startup": false,
427 | "wait_interval": 0
428 | }
429 | },
430 | "colab_type": "code",
431 | "collapsed": true,
432 | "id": "n6P0p8WyqQML"
433 | },
434 | "outputs": [],
435 | "source": [
436 | "models.append(\"gradient boost\")"
437 | ]
438 | },
439 | {
440 | "cell_type": "code",
441 | "execution_count": 18,
442 | "metadata": {
443 | "colab": {
444 | "autoexec": {
445 | "startup": false,
446 | "wait_interval": 0
447 | },
448 | "base_uri": "https://localhost:8080/",
449 | "height": 469,
450 | "output_extras": [
451 | {
452 | "item_id": 22
453 | }
454 | ]
455 | },
456 | "colab_type": "code",
457 | "executionInfo": {
458 | "elapsed": 145023,
459 | "status": "ok",
460 | "timestamp": 1519121157763,
461 | "user": {
462 | "displayName": "Pawan Bansal",
463 | "photoUrl": "//lh4.googleusercontent.com/-hQniqzw3AW0/AAAAAAAAAAI/AAAAAAAAAGs/dTfAX9OOw5w/s50-c-k-no/photo.jpg",
464 | "userId": "102337886470920224775"
465 | },
466 | "user_tz": -330
467 | },
468 | "id": "_mcw-FEgqcYC",
469 | "outputId": "b5b57af3-c9c1-4e87-8987-b6fe4d2f543d"
470 | },
471 | "outputs": [
472 | {
473 | "name": "stdout",
474 | "output_type": "stream",
475 | "text": [
476 | " Iter Train Loss Remaining Time \n",
477 | " 1 2314275.3681 2.45m\n",
478 | " 2 2034234.0235 2.41m\n",
479 | " 3 1803572.2337 2.37m\n",
480 | " 4 1608749.3223 2.34m\n",
481 | " 5 1445890.2822 2.33m\n",
482 | " 6 1307594.0384 2.31m\n",
483 | " 7 1188230.8595 2.30m\n",
484 | " 8 1093410.7788 2.31m\n",
485 | " 9 1009625.5156 2.30m\n",
486 | " 10 942921.5465 2.30m\n",
487 | " 20 596844.4649 2.25m\n",
488 | " 30 497781.8140 2.22m\n",
489 | " 40 452724.3501 2.20m\n",
490 | " 50 423902.1842 2.17m\n",
491 | " 60 400324.1880 2.14m\n",
492 | " 70 384742.5304 2.11m\n",
493 | " 80 371501.3233 2.07m\n",
494 | " 90 360896.1303 2.02m\n",
495 | " 100 351778.4518 1.97m\n",
496 | " 200 292815.3392 1.45m\n",
497 | " 300 262845.3144 57.60s\n",
498 | " 400 241005.6847 28.64s\n",
499 | " 500 224750.7518 0.00s\n",
500 | "('training set performance: ', 0.9152585634503211)\n",
501 | "('training set performance: ', 0.7994006303226393)\n"
502 | ]
503 | }
504 | ],
505 | "source": [
506 | "reg = GradientBoostingRegressor(verbose = 1, n_estimators = 500)\n",
507 | "reg.fit(X_train , y_train)\n",
508 | "\n",
509 | "training_score = reg.score(X_train, y_train)\n",
510 | "test_score = reg.score(X_test, y_test)\n",
511 | "\n",
512 | "training_scores.append(training_score)\n",
513 | "test_scores.append(test_score)\n",
514 | "print(\"training set performance: \", training_score)\n",
515 | "print(\"test set performance: \", test_score)"
516 | ]
517 | },
518 | {
519 | "cell_type": "code",
520 | "execution_count": 34,
521 | "metadata": {
522 | "colab": {
523 | "autoexec": {
524 | "startup": false,
525 | "wait_interval": 0
526 | },
527 | "base_uri": "https://localhost:8080/",
528 | "height": 390,
529 | "output_extras": [
530 | {
531 | "item_id": 1
532 | }
533 | ]
534 | },
535 | "colab_type": "code",
536 | "executionInfo": {
537 | "elapsed": 1096,
538 | "status": "ok",
539 | "timestamp": 1519121952990,
540 | "user": {
541 | "displayName": "Pawan Bansal",
542 | "photoUrl": "//lh4.googleusercontent.com/-hQniqzw3AW0/AAAAAAAAAAI/AAAAAAAAAGs/dTfAX9OOw5w/s50-c-k-no/photo.jpg",
543 | "userId": "102337886470920224775"
544 | },
545 | "user_tz": -330
546 | },
547 | "id": "LpUOOyN9qxZ3",
548 | "outputId": "3fd57b7e-60f6-4f4e-d4bc-f8d72ea1a2d5"
549 | },
550 | "outputs": [
551 | {
552 | "data": {
553 | "image/png": "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\nhsGfiIgowvx/v82+GHKQoUMAAAAASUVORK5CYII=\n",
554 | "text/plain": [
555 | ""
556 | ]
557 | },
558 | "metadata": {
559 | "tags": []
560 | },
561 | "output_type": "display_data"
562 | }
563 | ],
564 | "source": [
565 | "pred = reg.predict(X_test).astype(int)\n",
566 | "\n",
567 | "temp1 = y_test.values > 0\n",
568 | "# plt.axis((0,1000,0,1000))\n",
569 | "plt.scatter(y_test.values[temp1], pred[temp1])\n",
570 | "plt.xlabel(\"original\", fontsize=12)\n",
571 | "plt.ylabel(\"predictions\", fontsize=12)\n",
572 | "plt.show()"
573 | ]
574 | },
575 | {
576 | "cell_type": "markdown",
577 | "metadata": {
578 | "colab_type": "text",
579 | "id": "AE5vNO_eueCR"
580 | },
581 | "source": [
582 | "## 2. Cat Boost"
583 | ]
584 | },
585 | {
586 | "cell_type": "code",
587 | "execution_count": 0,
588 | "metadata": {
589 | "colab": {
590 | "autoexec": {
591 | "startup": false,
592 | "wait_interval": 0
593 | }
594 | },
595 | "colab_type": "code",
596 | "collapsed": true,
597 | "id": "ReF1DjVNxhOx"
598 | },
599 | "outputs": [],
600 | "source": [
601 | "models.append(\"cat boost\")"
602 | ]
603 | },
604 | {
605 | "cell_type": "code",
606 | "execution_count": 0,
607 | "metadata": {
608 | "colab": {
609 | "autoexec": {
610 | "startup": false,
611 | "wait_interval": 0
612 | }
613 | },
614 | "colab_type": "code",
615 | "collapsed": true,
616 | "id": "yqYXcoVBusGS"
617 | },
618 | "outputs": [],
619 | "source": [
620 | "model = CatBoostRegressor(iterations= 440 , depth= 8 , learning_rate= 0.1 , loss_function='RMSE' , use_best_model=True)\n",
621 | "model.fit(X_train[:90503], y_train[:90503] , eval_set=(X_train[90503:], y_train[90503:]),plot=True)"
622 | ]
623 | },
624 | {
625 | "cell_type": "code",
626 | "execution_count": 48,
627 | "metadata": {
628 | "colab": {
629 | "autoexec": {
630 | "startup": false,
631 | "wait_interval": 0
632 | },
633 | "base_uri": "https://localhost:8080/",
634 | "height": 52,
635 | "output_extras": [
636 | {
637 | "item_id": 1
638 | }
639 | ]
640 | },
641 | "colab_type": "code",
642 | "executionInfo": {
643 | "elapsed": 1213,
644 | "status": "ok",
645 | "timestamp": 1519122924101,
646 | "user": {
647 | "displayName": "Pawan Bansal",
648 | "photoUrl": "//lh4.googleusercontent.com/-hQniqzw3AW0/AAAAAAAAAAI/AAAAAAAAAGs/dTfAX9OOw5w/s50-c-k-no/photo.jpg",
649 | "userId": "102337886470920224775"
650 | },
651 | "user_tz": -330
652 | },
653 | "id": "lBWm2szKwBEl",
654 | "outputId": "bd21f432-ee9c-462c-fcca-e854140fd6e3"
655 | },
656 | "outputs": [
657 | {
658 | "name": "stdout",
659 | "output_type": "stream",
660 | "text": [
661 | "Training score - 0.9466853308679932\n",
662 | "Test score - 0.827240593918934\n"
663 | ]
664 | }
665 | ],
666 | "source": [
667 | "y_train_pred = model.predict(X_train)\n",
668 | "y_pred = model.predict(X_test)\n",
669 | "\n",
670 | "train_score = r2_score(y_train , y_train_pred)\n",
671 | "test_score = r2_score(y_test, y_pred)\n",
672 | "\n",
673 | "training_scores.append(training_score)\n",
674 | "test_scores.append(test_score)\n",
675 | "print(\"Training score - \" + str(train_score))\n",
676 | "print(\"Test score - \" + str(test_score))"
677 | ]
678 | },
679 | {
680 | "cell_type": "markdown",
681 | "metadata": {
682 | "colab_type": "text",
683 | "id": "lJFgf_2t04zZ"
684 | },
685 | "source": [
686 | "## 3. Random Forest"
687 | ]
688 | },
689 | {
690 | "cell_type": "code",
691 | "execution_count": 0,
692 | "metadata": {
693 | "colab": {
694 | "autoexec": {
695 | "startup": false,
696 | "wait_interval": 0
697 | }
698 | },
699 | "colab_type": "code",
700 | "collapsed": true,
701 | "id": "W-47YMYj3TNu"
702 | },
703 | "outputs": [],
704 | "source": [
705 | "models.append(\"random forest\")"
706 | ]
707 | },
708 | {
709 | "cell_type": "code",
710 | "execution_count": 81,
711 | "metadata": {
712 | "colab": {
713 | "autoexec": {
714 | "startup": false,
715 | "wait_interval": 0
716 | },
717 | "base_uri": "https://localhost:8080/",
718 | "height": 139,
719 | "output_extras": [
720 | {
721 | "item_id": 1
722 | },
723 | {
724 | "item_id": 2
725 | }
726 | ]
727 | },
728 | "colab_type": "code",
729 | "executionInfo": {
730 | "elapsed": 22547,
731 | "status": "ok",
732 | "timestamp": 1519124671151,
733 | "user": {
734 | "displayName": "Pawan Bansal",
735 | "photoUrl": "//lh4.googleusercontent.com/-hQniqzw3AW0/AAAAAAAAAAI/AAAAAAAAAGs/dTfAX9OOw5w/s50-c-k-no/photo.jpg",
736 | "userId": "102337886470920224775"
737 | },
738 | "user_tz": -330
739 | },
740 | "id": "Zy__IZ1AwC-s",
741 | "outputId": "3e0e82aa-8f77-49d1-ec5b-83d533215db9"
742 | },
743 | "outputs": [
744 | {
745 | "name": "stderr",
746 | "output_type": "stream",
747 | "text": [
748 | "[Parallel(n_jobs=-1)]: Done 10 out of 10 | elapsed: 21.9s finished\n"
749 | ]
750 | },
751 | {
752 | "data": {
753 | "text/plain": [
754 | "RandomForestRegressor(bootstrap=True, criterion='mse', max_depth=None,\n",
755 | " max_features='auto', max_leaf_nodes=None,\n",
756 | " min_impurity_decrease=0.0, min_impurity_split=None,\n",
757 | " min_samples_leaf=1, min_samples_split=2,\n",
758 | " min_weight_fraction_leaf=0.0, n_estimators=10, n_jobs=-1,\n",
759 | " oob_score=False, random_state=7, verbose=1, warm_start=False)"
760 | ]
761 | },
762 | "execution_count": 81,
763 | "metadata": {
764 | "tags": []
765 | },
766 | "output_type": "execute_result"
767 | }
768 | ],
769 | "source": [
770 | "model = RandomForestRegressor(n_jobs=-1, n_estimators=10, verbose=1, random_state=seed)\n",
771 | "model.fit(X_train, y_train)"
772 | ]
773 | },
774 | {
775 | "cell_type": "code",
776 | "execution_count": 82,
777 | "metadata": {
778 | "colab": {
779 | "autoexec": {
780 | "startup": false,
781 | "wait_interval": 0
782 | },
783 | "base_uri": "https://localhost:8080/",
784 | "height": 86,
785 | "output_extras": [
786 | {
787 | "item_id": 1
788 | },
789 | {
790 | "item_id": 2
791 | }
792 | ]
793 | },
794 | "colab_type": "code",
795 | "executionInfo": {
796 | "elapsed": 1335,
797 | "status": "ok",
798 | "timestamp": 1519124674034,
799 | "user": {
800 | "displayName": "Pawan Bansal",
801 | "photoUrl": "//lh4.googleusercontent.com/-hQniqzw3AW0/AAAAAAAAAAI/AAAAAAAAAGs/dTfAX9OOw5w/s50-c-k-no/photo.jpg",
802 | "userId": "102337886470920224775"
803 | },
804 | "user_tz": -330
805 | },
806 | "id": "liEZwYXY1E1o",
807 | "outputId": "7ea3b5d7-3d0b-4dbe-c1aa-b12019b639bd"
808 | },
809 | "outputs": [
810 | {
811 | "name": "stdout",
812 | "output_type": "stream",
813 | "text": [
814 | "('training score: ', 0.9621975488319267)\n",
815 | "('test score: ', 0.7932394748872148)\n"
816 | ]
817 | },
818 | {
819 | "name": "stderr",
820 | "output_type": "stream",
821 | "text": [
822 | "[Parallel(n_jobs=2)]: Done 10 out of 10 | elapsed: 0.3s finished\n",
823 | "[Parallel(n_jobs=2)]: Done 10 out of 10 | elapsed: 0.0s finished\n"
824 | ]
825 | }
826 | ],
827 | "source": [
828 | "training_score = model.score(X_train, y_train)\n",
829 | "test_score = model.score(X_test, y_test)\n",
830 | "\n",
831 | "print(\"training score: \", training_score)\n",
832 | "print(\"test score: \", test_score)"
833 | ]
834 | },
835 | {
836 | "cell_type": "code",
837 | "execution_count": 0,
838 | "metadata": {
839 | "colab": {
840 | "autoexec": {
841 | "startup": false,
842 | "wait_interval": 0
843 | }
844 | },
845 | "colab_type": "code",
846 | "collapsed": true,
847 | "id": "PESOXPwY27SO"
848 | },
849 | "outputs": [],
850 | "source": [
851 | "training_scores.append(training_score)\n",
852 | "test_scores.append(test_score)"
853 | ]
854 | },
855 | {
856 | "cell_type": "markdown",
857 | "metadata": {
858 | "colab_type": "text",
859 | "id": "stPUH9TL4CYh"
860 | },
861 | "source": [
862 | "## 4. Neural Network"
863 | ]
864 | },
865 | {
866 | "cell_type": "code",
867 | "execution_count": 0,
868 | "metadata": {
869 | "colab": {
870 | "autoexec": {
871 | "startup": false,
872 | "wait_interval": 0
873 | }
874 | },
875 | "colab_type": "code",
876 | "collapsed": true,
877 | "id": "7ybHijZj5wRv"
878 | },
879 | "outputs": [],
880 | "source": [
881 | "models.append(\"neural network\")"
882 | ]
883 | },
884 | {
885 | "cell_type": "code",
886 | "execution_count": 126,
887 | "metadata": {
888 | "colab": {
889 | "autoexec": {
890 | "startup": false,
891 | "wait_interval": 0
892 | },
893 | "base_uri": "https://localhost:8080/",
894 | "height": 402,
895 | "output_extras": [
896 | {
897 | "item_id": 107
898 | },
899 | {
900 | "item_id": 191
901 | },
902 | {
903 | "item_id": 300
904 | },
905 | {
906 | "item_id": 416
907 | },
908 | {
909 | "item_id": 492
910 | },
911 | {
912 | "item_id": 598
913 | },
914 | {
915 | "item_id": 599
916 | }
917 | ]
918 | },
919 | "colab_type": "code",
920 | "executionInfo": {
921 | "elapsed": 224494,
922 | "status": "ok",
923 | "timestamp": 1519128490356,
924 | "user": {
925 | "displayName": "Pawan Bansal",
926 | "photoUrl": "//lh4.googleusercontent.com/-hQniqzw3AW0/AAAAAAAAAAI/AAAAAAAAAGs/dTfAX9OOw5w/s50-c-k-no/photo.jpg",
927 | "userId": "102337886470920224775"
928 | },
929 | "user_tz": -330
930 | },
931 | "id": "GOZfkMlQ4EtJ",
932 | "outputId": "1b0036ca-d929-4adb-d97a-b856e0dd84e4"
933 | },
934 | "outputs": [
935 | {
936 | "name": "stdout",
937 | "output_type": "stream",
938 | "text": [
939 | "Epoch 1/10\n",
940 | "95503/95503 [==============================] - 23s 236us/step - loss: 1426592.9792\n",
941 | "Epoch 2/10\n",
942 | "80064/95503 [========================>.....] - ETA: 3s - loss: 1140652.504595503/95503 [==============================] - 22s 232us/step - loss: 2178143.3739\n",
943 | "Epoch 3/10\n",
944 | "95503/95503 [==============================] - 22s 234us/step - loss: 1195133.7699\n",
945 | "Epoch 4/10\n",
946 | "19328/95503 [=====>........................] - ETA: 17s - loss: 919646.060095503/95503 [==============================] - 22s 234us/step - loss: 999633.2443\n",
947 | "Epoch 5/10\n",
948 | "95503/95503 [==============================] - 22s 232us/step - loss: 862275.2634\n",
949 | "Epoch 6/10\n",
950 | " 3168/95503 [..............................] - ETA: 21s - loss: 466866.896795503/95503 [==============================] - 22s 231us/step - loss: 910655.6377\n",
951 | "Epoch 7/10\n",
952 | "93888/95503 [============================>.] - ETA: 0s - loss: 792743.879995503/95503 [==============================] - 22s 233us/step - loss: 802929.4407\n",
953 | "Epoch 8/10\n",
954 | "95503/95503 [==============================] - 22s 233us/step - loss: 856054.5725\n",
955 | "Epoch 9/10\n",
956 | "24096/95503 [======>.......................] - ETA: 16s - loss: 796268.264295503/95503 [==============================] - 23s 236us/step - loss: 854576.2596\n",
957 | "Epoch 10/10\n",
958 | "95503/95503 [==============================] - 22s 233us/step - loss: 716396.9110\n"
959 | ]
960 | },
961 | {
962 | "data": {
963 | "text/plain": [
964 | ""
965 | ]
966 | },
967 | "execution_count": 126,
968 | "metadata": {
969 | "tags": []
970 | },
971 | "output_type": "execute_result"
972 | }
973 | ],
974 | "source": [
975 | "def baseline_model():\n",
976 | " model = Sequential()\n",
977 | " model.add(Dense(100,input_dim=54, activation='relu', kernel_initializer='glorot_normal'))\n",
978 | " model.add(Dropout(0.2)) \n",
979 | " model.add(Dense(80, activation='relu', kernel_initializer='glorot_normal'))\n",
980 | " model.add(Dropout(0.2))\n",
981 | " model.add(Dense(60, activation='relu', kernel_initializer='glorot_normal'))\n",
982 | " model.add(Dropout(0.2)) \n",
983 | " model.add(Dense(40, activation='relu', kernel_initializer='glorot_normal'))\n",
984 | " model.add(Dropout(0.2))\n",
985 | " model.add(Dense(20, activation='relu', kernel_initializer='glorot_normal'))\n",
986 | " model.add(Dropout(0.2))\n",
987 | " model.add(Dense(10, activation='relu', kernel_initializer='glorot_normal'))\n",
988 | " model.add(Dropout(0.2))\n",
989 | " model.add(Dense(1, kernel_initializer='glorot_normal'))\n",
990 | " \n",
991 | " model.compile(loss='mean_squared_error', optimizer='adam')\n",
992 | " return model\n",
993 | "\n",
994 | "estimator = KerasRegressor(build_fn=baseline_model, nb_epoch=200, epochs=10, batch_size=32, verbose=True)\n",
995 | "# kfold = KFold(n_splits=10, random_state=seed)\n",
996 | "# results = cross_val_score(estimator, X_train.values, y_train.values, cv=kfold)\n",
997 | "# print(\"Results: %.2f (%.2f) MSE\" % (results.mean(), results.std()))\n",
998 | "\n",
999 | "estimator.fit(X_train, y_train)"
1000 | ]
1001 | },
1002 | {
1003 | "cell_type": "code",
1004 | "execution_count": 127,
1005 | "metadata": {
1006 | "colab": {
1007 | "autoexec": {
1008 | "startup": false,
1009 | "wait_interval": 0
1010 | },
1011 | "base_uri": "https://localhost:8080/",
1012 | "height": 86,
1013 | "output_extras": [
1014 | {
1015 | "item_id": 11
1016 | }
1017 | ]
1018 | },
1019 | "colab_type": "code",
1020 | "executionInfo": {
1021 | "elapsed": 5115,
1022 | "status": "ok",
1023 | "timestamp": 1519128546517,
1024 | "user": {
1025 | "displayName": "Pawan Bansal",
1026 | "photoUrl": "//lh4.googleusercontent.com/-hQniqzw3AW0/AAAAAAAAAAI/AAAAAAAAAGs/dTfAX9OOw5w/s50-c-k-no/photo.jpg",
1027 | "userId": "102337886470920224775"
1028 | },
1029 | "user_tz": -330
1030 | },
1031 | "id": "IyToCFgS5c7K",
1032 | "outputId": "5546c597-cb24-437a-fb1b-fdc31b46cfbe"
1033 | },
1034 | "outputs": [
1035 | {
1036 | "name": "stdout",
1037 | "output_type": "stream",
1038 | "text": [
1039 | "95503/95503 [==============================] - 4s 43us/step\n",
1040 | "10612/10612 [==============================] - 0s 45us/step\n",
1041 | "('training score: ', 0.8259016551067639)\n",
1042 | "('test score: ', 0.7981640331110263)\n"
1043 | ]
1044 | }
1045 | ],
1046 | "source": [
1047 | "train_pred = estimator.predict(X_train)\n",
1048 | "test_pred = estimator.predict(X_test)\n",
1049 | "\n",
1050 | "training_score = r2_score(y_train, train_pred)\n",
1051 | "test_score = r2_score(y_test, test_pred)\n",
1052 | "\n",
1053 | "print(\"training score: \", training_score)\n",
1054 | "print(\"test score: \", test_score)"
1055 | ]
1056 | },
1057 | {
1058 | "cell_type": "code",
1059 | "execution_count": 0,
1060 | "metadata": {
1061 | "colab": {
1062 | "autoexec": {
1063 | "startup": false,
1064 | "wait_interval": 0
1065 | }
1066 | },
1067 | "colab_type": "code",
1068 | "collapsed": true,
1069 | "id": "QN8YlA525tpE"
1070 | },
1071 | "outputs": [],
1072 | "source": [
1073 | "training_scores.append(training_score)\n",
1074 | "test_scores.append(test_score)"
1075 | ]
1076 | },
1077 | {
1078 | "cell_type": "markdown",
1079 | "metadata": {
1080 | "colab_type": "text",
1081 | "id": "fNyX2xkpcmcx"
1082 | },
1083 | "source": [
1084 | "# Comparing all model's results"
1085 | ]
1086 | },
1087 | {
1088 | "cell_type": "code",
1089 | "execution_count": 131,
1090 | "metadata": {
1091 | "colab": {
1092 | "autoexec": {
1093 | "startup": false,
1094 | "wait_interval": 0
1095 | },
1096 | "base_uri": "https://localhost:8080/",
1097 | "height": 69,
1098 | "output_extras": [
1099 | {
1100 | "item_id": 1
1101 | }
1102 | ]
1103 | },
1104 | "colab_type": "code",
1105 | "executionInfo": {
1106 | "elapsed": 840,
1107 | "status": "ok",
1108 | "timestamp": 1519130258549,
1109 | "user": {
1110 | "displayName": "Pawan Bansal",
1111 | "photoUrl": "//lh4.googleusercontent.com/-hQniqzw3AW0/AAAAAAAAAAI/AAAAAAAAAGs/dTfAX9OOw5w/s50-c-k-no/photo.jpg",
1112 | "userId": "102337886470920224775"
1113 | },
1114 | "user_tz": -330
1115 | },
1116 | "id": "OTFvPxEeN4MY",
1117 | "outputId": "c2ed0976-4f05-41de-d0a7-a702ba8ad39d"
1118 | },
1119 | "outputs": [
1120 | {
1121 | "name": "stdout",
1122 | "output_type": "stream",
1123 | "text": [
1124 | "['gradient boost', 'cat boost', 'random forest', 'neural network']\n",
1125 | "[0.7936297533635706, 0.7936297533635706, 0.9621975488319267, 0.8259016551067639]\n",
1126 | "[0.7696216055989064, 0.827240593918934, 0.7932394748872148, 0.7981640331110263]\n"
1127 | ]
1128 | }
1129 | ],
1130 | "source": [
1131 | "print(models)\n",
1132 | "print(training_scores)\n",
1133 | "print(test_scores)"
1134 | ]
1135 | },
1136 | {
1137 | "cell_type": "code",
1138 | "execution_count": 224,
1139 | "metadata": {
1140 | "colab": {
1141 | "autoexec": {
1142 | "startup": false,
1143 | "wait_interval": 0
1144 | },
1145 | "base_uri": "https://localhost:8080/",
1146 | "height": 522,
1147 | "output_extras": [
1148 | {
1149 | "item_id": 1
1150 | }
1151 | ]
1152 | },
1153 | "colab_type": "code",
1154 | "executionInfo": {
1155 | "elapsed": 924,
1156 | "status": "ok",
1157 | "timestamp": 1519134063364,
1158 | "user": {
1159 | "displayName": "Pawan Bansal",
1160 | "photoUrl": "//lh4.googleusercontent.com/-hQniqzw3AW0/AAAAAAAAAAI/AAAAAAAAAGs/dTfAX9OOw5w/s50-c-k-no/photo.jpg",
1161 | "userId": "102337886470920224775"
1162 | },
1163 | "user_tz": -330
1164 | },
1165 | "id": "1Sue-rrkOnFc",
1166 | "outputId": "ee20a996-e6ef-4db8-fbfd-6bd6f0afbab3"
1167 | },
1168 | "outputs": [
1169 | {
1170 | "data": {
1171 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAAlUAAAH5CAYAAACoMMu6AAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMS4yLCBo\ndHRwOi8vbWF0cGxvdGxpYi5vcmcvNQv5yAAAIABJREFUeJzs3Xt8zvXj//GnjU2W4wjNWg7tQjNm\nm400LDk2WeSwGUVKxTp8nFbER0V8wmfIIdEHn4ys5ZeUckwqZCgy5FA2otYUbbXNdv3+8N316Wpn\nXjtYj/vt5nbj/X5dr/frdV2vzfN6vV/v97uS1Wq1CgAAANfFoawbAAAAUBEQqgAAAAwgVAEAABhA\nqAIAADCAUAUAAGAAoQoAAMAAQhWAUrd7924NGDBAPj4+slgsiouLK3YdSUlJslgsmj9/foHbJOn3\n33/XSy+9pM6dO6tFixYKDg627XvrrbfUo0cPeXl5yWKxKCkp6do7hiKLiIiw+xyKa+LEibJYLAZb\nBFy/ymXdAMCkPXv2aOjQoXbbqlWrpttvv13333+/hgwZosqV/zfsrVar3nvvPe3YsUOHDx/Wjz/+\nqNq1a6t58+Z6/PHH1bp169LuQoX366+/asyYMWrQoIEmTpyoqlWrqm3btiV6zKVLl2rVqlUaPny4\nLBaLbr75ZklXw920adN0zz33aOTIkapcubLq1KlTom0xZc+ePdq7d6+GDRumGjVqlHVzAIhQhQrq\nvvvuU1BQkKxWq5KTk/X//t//04wZM3Ty5Em9+OKLtnIZGRkaP368WrRooV69eqlRo0b66aeftGbN\nGg0cOFAzZ87U/fffX4Y9qXgOHTqkS5cu6eWXX1a3bt2M1u3m5qavv/5ajo6Odts///xzeXp6asKE\nCbm2S9L06dNVq1Yto20paXv37tWCBQsUGhpKqALKCUIVKqSWLVvahaGwsDD17NlT69at0zPPPGOb\njXB0dNSqVavUrl07u9cPGDBAvXv31syZMxUSEiIHhxvnTHlWVpYyMjJ00003lXVT8pScnCxJqlmz\npvG6K1WqJGdn51zbf/rpJ9166615bpdkPFBlZmYqOzs7z7YAqLhunP8pgOtQrVo1tW7dWlarVWfO\nnLFtr1y5cq5AJUl169ZVu3bt9PPPP+vnn38utP4ffvhBUVFR6tKli7y8vNS+fXsNGjRI7777rl05\nq9Wqt99+Ww8++KB8fHzk4+OjkJAQRUdH25VLSUnRP//5T3Xq1EleXl7q1KmT/vnPf+rixYt25eLi\n4mSxWPT555/rtddeU9euXeXt7a0PP/zQVubQoUN68sknFRAQIC8vL3Xv3l2LFi3SlStX7Or69ttv\nFRkZqbvvvlteXl666667FBERoR07dhTaf0k6evSo7TitWrVSr169tHTpUmVlZdnKBAcH22aLhg4d\nKovFUqR1Mfv27dOgQYPk7e2tDh06aNq0aUpLS8tV7q9rqnLen6SkJO3du9d2vJz1ODlruXK2R0RE\n2Or68ccfNWXKFHXu3FleXl7q2LGjJk+enGs8zJ8/XxaLRd9++61mzJihoKAgeXt76+DBg7Yyn3/+\nuYYPHy4/Pz+1atVKISEhiomJydX+4OBgRURE6OTJk3r00Ufl4+MjX19fRUZG2gKgdHU90YIFCyRJ\n99xzj639f11L9lc565iSkpL05JNPys/PT/7+/po4caJSU1OVnZ2txYsXKzg4WK1atVJoaKji4+Nz\n1ZOWlqbZs2era9eutrEyfvx4nT17NlfZX3/9VZMmTVJAQIDatGmjiIgIHT58ON82FnW85qWoP4dA\nSWGmCn8biYmJkoo+Q3L+/HlVqVKl0FMrV65c0cMPP6wLFy4oLCxMt99+u3777TcdO3ZM+/btU2ho\nqK3suHHjtGHDBrVu3VqjRo1S9erVderUKX300Ud66qmnJEmXL1/W4MGD9f3336tfv35q2bKlEhIS\nFBMTo927d2vdunW2NUE5Zs6cqStXrmjAgAFycXFR48aNJUk7duzQ6NGj5eHhoeHDh6tmzZo6ePCg\n5s2bp4SEBM2bN0+SdPHiRQ0bNkySNGjQIN166626ePGiDh8+rK+++kqdO3cu8D04dOiQIiIiVLly\nZYWHh6tu3bravn27Xn31VR09elSzZ8+WJD333HPauXOn1q5dq1GjRqlJkyaFfg5fffWVHn74Ybm4\nuGjkyJGqXr26Pvjgg1yn8vLi7++vWbNmacaMGapdu7ZGjRol6WqIat++vd5++23t27dPs2bNknQ1\nTEvSuXPnNHDgQGVmZqp///667bbb9P333ysmJkZ79uzRO++8o+rVq9sda+zYsapataqGDx8uSapX\nr54kae3atZoyZYratGmjUaNG6aabbtLnn3+uqVOn6syZM7n6ceHCBQ0dOlRdu3bV+PHjdfToUa1d\nu1a//fabli9fLkkaOHCgfvvtN23evFlRUVGqXbu2rV+FSUtL07Bhw9SuXTv94x//0KFDh/TOO+8o\nPT1dtWrV0ldffaWIiAhlZmZq+fLlevzxx7Vt2zbbmMvMzNSIESO0f/9+de/eXQ8//LDtvfnss8/0\nzjvvqEGDBnZlDx06pPvvv1+tW7fW0aNH9fDDD+c5O1jU8ZqX4vwcAiXGClQgu3fvtnp6elrnz59v\n/fnnn60///yz9ejRo9apU6daPT09rf379y9SPTt27LB6enpax40bV2jZhIQEq6enp/X1118vsNzG\njRutnp6e1rFjx1qzsrLs9v3533PmzLF6enpa//vf/9qV+e9//2v19PS0zp0717btnXfesXp6elq7\ndetmTUtLsyv/xx9/WDt06GANCwuzZmZm2u178803rZ6entbdu3dbrVardcuWLVZPT0/rxo0bC+1v\nXgYOHGht0aKFNSEhwbYtOzvbGhkZafX09LR+/vnnudqcc+yi1H3nnXdaT506ZduWnp5u7devn9XT\n09M6b9482/bExMRc26xWq7VLly7WIUOG5Kp7woQJVk9Pz1zbR40aZQ0MDLT+8MMPdtu//vpra4sW\nLezqnzdvntXT09M6ZMiQXO/zhQsXrF5eXtZnn3021zFefPFFa/Pmza1nzpyxa2den0PO+D158mSu\n4yYmJuaqOz9Dhgyxenp6WpcuXWq3/cknn7RaLBZraGioNSMjw7Y9Z1zExMTYtq1du9bq6elpnTlz\npl0d27dvt43vHGvWrLF6enpao6Oj7crmjL8uXbrYthVnvFqtuT+7ov4cAiWJ03+okObPn6/27dur\nffv26tOnj1avXq1u3bpp4cKFhb72u+++0/jx41W/fn1NnDix0PI5MxZ79uwp8FThhg0bJEkTJkzI\ntUbrz//evHmz6tSpo4EDB9qVGThwoOrUqaMtW7bkqnvw4MG51lB99tlnSk5O1gMPPKBLly4pJSXF\n9icoKMhW5s99+PTTT/Xbb78V2uc/+/nnn3XgwAEFBwerefPmtu2VKlXS448/buvTtfhz3Tmzb5Lk\n5OSkhx566JrqLMzly5e1Y8cOBQcHy8nJye59c3Nz02233WZ73/5s2LBhdleWStJHH32kjIwM9e/f\n366elJQUBQcHKzs727ZYPsctt9yiXr162W0LDAyUJH3//ffX3T9HR0e705yS5OfnJ6vVqsGDB6tK\nlSp22/963M2bN8vBwUGPPfaYXR05t6vYunWrsrOzJUlbtmyRo6OjbfYuR1hYWK7Z1uKM17wU9ecQ\nKEmc/kOFNHDgQPXo0UOZmZk6fvy43njjDZ0/f77QhcOJiYm2/6yXLl1apMvr3dzcNGrUKL3++uvq\n2LGjWrRoocDAQPXo0UPe3t62ct9//73q1atnO8WUn6SkJHl5eeX6D7py5cq6/fbbdeTIkVyv+XPg\nyHHy5ElJV0+55Sdn0Xi7du3Ut29fxcXFacOGDfLy8lKHDh3Uq1cvNWvWrND2SsqzXJMmTeTg4GA7\n9VpcOa/L6zRhYe26VqdPn1Z2drZiY2MVGxubZxl3d/dc226//fZc23I+g4ICYM5nUFDdOafKfvnl\nl3zrKap69erl+jnIOcXdqFEju+05p8r/fNykpCTdcssteZ5Gb9asmRISEnTx4kW5uroqMTFR9erV\nyxWgnJyc5O7urkuXLtm2FWe85qWoP4dASSJUoULy8PBQhw4dJEmdOnWSr6+vwsLCNGXKFM2dOzfP\n1yQlJWnYsGFKS0vTf/7zn2LdWPCZZ55R//79tWPHDu3bt0+xsbFatmyZHnnkEY0bN85InwpStWrV\nXNusVqsk2W4ZkZdbbrnF9veZM2dqxIgR2rlzp/bt26c333xTixcv1nPPPachQ4aUTMPLoZz3rU+f\nPvmuw8krnBf0GcycOdPuvf6zv4aov94OIq/6rkdB9ed3lauJ4xamuOM1L2X9cwgQqvC30LZtW91/\n//1av369IiIict1sMikpSUOHDtXly5f15ptvqmXLlsU+hru7uyIiIhQREaH09HSNGDFCb7zxhoYP\nHy5XV1fdfvvt2rp1q5KTkwucrXJ3d9fp06d15coVu9mqK1eu6LvvvstzJiMvOTMnN910ky1gFsbT\n01Oenp565JFHdOnSJT344IOaPXu2wsPDValSpTxfkzO7ceLEiVz7Tp06pezs7CK3Ob+6T506lWtf\nXscz4bbbblOlSpWUmZlZ5PctPzmfQe3ata+7rr/K7/Moae7u7vr000916dKlXBdxnDx5UjfffLNt\n4by7u7s+++wz/fbbb3azVRkZGUpMTLSb7bqW8Zpf+wr6OQRKEmuq8LfxxBNPyNHRMdcVRGfPntXQ\noUN16dIlLVu2TF5eXsWq9/Lly8rMzLTb5uzsbDtl9euvv0qSQkJCJEn/+te/bGtOcvx5JqBr165K\nSUnRunXr7Mq8/fbbSklJUdeuXYvUro4dO8rV1VVLly7N87TRH3/8YVs/9csvv+RqU40aNdSoUSP9\n/vvvSk9Pz/c4rq6u8vHx0fbt23X8+HG7Pr3++uuSpHvvvbdIbf6runXrqk2bNtq2bZtOnz5t256R\nkaH//Oc/11RnYWrXrq1OnTpp8+bNdrdFyGG1WpWSklKkunr27CknJyfNnz9ff/zxR679ly9fVkZG\nxjW1s1q1apL+N75KS9euXZWdnW37bHN88sknOnLkiIKDg20zXvfcc4+ysrJsVy3mWL16da61e8UZ\nr3kp6s8hUJKYqcLfhoeHh3r16qUNGzZo37598vPz02+//aahQ4fq7NmzioiI0OnTp+3+85aku+66\nq8CZpT179mjy5Mnq1q2bGjduLBcXFx0+fFixsbFq3bq17Zd6z5499fHHH2v9+vX6/vvvFRwcrBo1\naui7777Trl279P7770uSHnnkEW3atEnTpk3TkSNH1KJFCyUkJCg2NlaNGzfWI488UqT+VqtWTTNn\nztSTTz6pHj16qF+/fvLw8NClS5d06tQpbd68WQsWLFBAQIDWr1+vFStWqGvXrvLw8FDlypX15Zdf\nateuXerZs2eep7b+7Pnnn1dERITCw8MVFhamevXqafv27dq1a5fuu+8+tW/fvkhtzsvEiRMVERGh\nwYMHKzw83HZLhT/f/8q0qVOnKiwsTEOGDNH999+vli1bKjs7W4mJidq6dav69u2rMWPGFFpPgwYN\nNHXqVE2aNEm9evVSnz595ObmppSUFB0/flxbtmzRxo0bc61lKoqcRyi9+uqrCgkJkbOzs+644w55\nenoWu67iCA0N1bvvvqulS5fq7Nmz8vPz05kzZ7R69WrVrVtXzz77rK3sAw88oLfffluvvfaakpKS\n1KZNGyUkJGjTpk267bbb7D7D4ozXvBT15xAoSYQq/K08/vjj2rhxo6Kjo7Vq1Sr98ssvtoXWq1at\nyvM1K1euLDBUWSwW3Xvvvdq7d682bNig7OxsNWzYUI899liuq55mz54tPz8/xcbG6rXXXpODg4Ma\nNWqkHj162MpUr15dMTExmjdvnrZt26a4uDi5urpq0KBBGjNmTK5FvwW5++67FRsbq9dff13vvfee\nLl68qBo1aui2227TQw89ZFs3FhAQoISEBO3YsUM//fSTrV0TJkwo0nqqVq1aac2aNZo3b55iYmKU\n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\nzVJJ0j333COLxaI9e/bkOnZSUpJGjBghf39/eXt7q3v37po3b55t/8GDBzV8+HAFBgbKx8dHAwYM\nsB3/6NGjGjFihAICAhQYGKhRo0bp1KlTdv2yWCxatGiRevfuLW9vb0nSxYsX9cILLyg4OFg+Pj4a\nNGiQ9u3bZ/ItzRen/wAAqMAeeOABLV++XKmpqerevbvq16+vZs2a6dNPP9UTTzyh2rVr695779X3\n33+vN998U7/++qtmzJih5cuX66OPPlKzZs3k5+enc+fO6cCBA5KuhrOVK1fa6r/55pvVoEGDXMf+\n97//rV27dumuu+5So0aNdObMGX311VeSpOPHjysiIkIZGRny8/OTh4eHvvzyS2VmZury5cuKiIjQ\npUuX1LlzZ2VmZmr79u06fPiwNm7cqJo1a9qOMX/+fHXv3l1NmzZVdna2nnjiCe3fv19+fn4KDAzU\npk2bNHz4cK1fv15NmjQp0feaUAUAQAU2evRoxcXFKTU1VeHh4bY1VY8++qgkqWXLlqpRo4aaN2+u\nAwcO6N1339ULL7ygK1euSJKaNWumfv36qWnTpqpataok6fnnn7eFqieffDLfNVU5dQQEBOjuu+9W\n06ZNVbny1eixZs0aZWRkKDg4WIsWLZIkZWVlqVKlSlq7dq0uXbqkdu3aacmSJZKkvn37KiEhQZs2\nbdLAgQNtx3jsscf01FNPSZK+/vpr7d+/Xy4uLmrZsqUkycPDQ0eOHFFcXJzGjh1r6F3NG6EKAIC/\noZxTgp999pk+++wz23ar1arExEQNGzZMR48e1ebNm7Vp0yY5OjqqZ8+e+te//iUHh6KtHhozZozO\nnz+v6OhozZkzR05OThoyZIgmTJigpKQkSVKbNm1s5R0dHe3a1rRpU9u+Jk2aKCEhQefOnbM7Rtu2\nbXP1KTU11Rb6cpw5c6ZIbb4ehCoAACq4nBCUnZ1t2+bm5qYTJ07o+eef19ChQ23bExMT5e7uroyM\nDC1btky7d+9WrVq1NH78eL3//vsaPHiw/Pz85ODgoOzsbFmt1nyP6+7urjVr1igtLU0nTpzQE088\noeXLl2vo0KG22a2c04E57atUqZLc3NwkyW4N1enTpyVJt956q90xnJyc7PokSfXq1dO2bdts+/74\n4w9dvny5GO/YtSFUAQBQwTVs2FCJiYmaN2+etm3bpuHDhys8PFyffPKJXn31VR08eFDOzs46duyY\n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\ngYGB+uCDD4w2FgAAoLwqdKbqr6xWa57bMzIyJEn16tXT008/rZdeeklRUVEKCgrSzTffXGCd8fHx\nxW1GsaSnpZZo/cWVnZ11TfvSylE/SvozK2uMGfMYM6WnoDFR2H7GTOmpCGOmPI0XqezHTKGhqlGj\nRpKk8+fPS5IuXLggSXJ3d1d6erocHBxUpUoVW7mePXuqW7du2rRpkzZu3Kgff/yx0FDl6+t7XZ0o\nzMG31pZo/cXl4OCY5/bs7Kx890lStWouJdWkYvP1bV7WTShRjBnzGDOlp6AxwZgpPyrCmClP40Uq\nnTFTUHAr9PRfUFCQXF1dFRMTo9WrVys2NlZubm5yc3OTt7e3Ro8eLUnq1auXnJycFBcXp7fffltf\nfPGF6tevr9tuu81cTwAAAMqpQkOVs7OzoqOj5eLiounTp8vV1VXR0dFycLB/af369TV79mylpKTo\n5ZdfloeHhxYtWqTKlYt9hhEAAOCGU6TE4+/vrw0bNuTafuzYMbt/d+vWTd26dTPTMgAAgBsId1QH\nAAAwgFAFAABgAKEKAADAAEIVAACAAYQqAAAAAwhVAAAABhCqAAAADCBUAQAAGECoAgAAMIBQBQAA\nYAChCgAAwABCFQAAgAGEKgAAAAMIVQAAAAYQqgAAAAwgVAEAABhAqAIAADCAUAUAAGAAoQoAAMAA\nQhUAAIABhCoAAAADCFUAAAAGEKoAAAAMIFQBAAAYQKgCAAAwgFAFAABgAKEKAADAAEIVAACAAYQq\nAAAAAwhVAAAABhCqAAAADCBUAQAAGECoAgAAMIBQBQAAYAChCgAAwABCFQAAgAGEKgAAAAMIVQAA\nAAYQqgAAAAwgVAEAABhAqAIAADCAUAUAAGAAoQoAAMAAQhUAAIABhCoAAAADCFUAAAAGEKoAAAAM\nIFQBAAAYQKgCAAAwgFAFAABgAKEKAADAAEIVAACAAYQqAAAAAwhVAAAABhCqAAAADCBUAQAAGECo\nAgAAMIBQBQAAYAChCgAAwABCFQAAgAGEKgAAAAMIVQAAAAYQqgAAAAwgVAEAABhAqAIAADCAUAUA\nAGAAoQoAAMAAQhUAAIABhCoAAAADCFUAAAAGEKoAAAAMIFQBAAAYQKgCAAAwgFAFAABgAKEKAADA\nAEIVAACAAYQqAAAAA4oUquLj4xUSEiIvLy+Fhobqm2++ybfsyZMn1apVK1ksFm3atMlYQwEAAMqz\n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\nAz799FO2b99O+/bta+z3dVWXLl2YMmUKenp6XLx4kVu3bpGXl1fteXwZr9r3aqKrX6rHt0OHDnHo\n0CEA7t69i76+vs5xrHv37qSnp5OVlYWZmRmVlZWcPn2aS5cuMWDAAODZIwetW7fG398fgISEBNLT\n07ViWbhwIR06dKiyzc7OjrCwsCrfn/ku1Iuk6mUYGBhgaGgIPEt8YmNj6dmzJxMmTGDnzp2kpaXx\n9OnTKn/3d1ONDRs2JCoqCn19feDZcwfPa9asmaacet/LZtrq99YVg7oOXXXp2hceHk5ycjIXL15k\n8+bNbN++nfT09Hee9dc1UVFR5OXl4evrS6dOnZgyZQpPnjwBpN3rmlatWml+37FjB9nZ2ZpbMoGB\ngTx8qL1m2vNjAWg/2/m6bf7BBx8AoFAoAGjatKnmg+fFsagmNb2HiYlJlQ+zb775RpOgwbOZr9at\nW2NlZUVmZiYpKSlERUWRmJhY7/uaut11fUboOo8nT54E/t8/dN3GfdW+9zLx6eqX4eHhGBsba+Ju\n3Lixzva0s7MjKSmJvXv30rVrVyorK9m5cycqlYoePXq8dCzPH5eakZERFy9e5Nq1a1hbW790Xf+U\nd5/WvQXqK+3t27ezd+9eranrmjx+/JgbN25w9uxZnXXt27dP5xS6mrOzM2VlZcTGxnL79m2OHz+u\nNWtVHfVAmJ6errkK0CU1NZVdu3YRGRkJgL29PT179kShULBlyxb279/P1q1bUSgUODk50bdvXwCW\nLVvGjh07SElJwczMDHNzc1auXElxcTEdOnTA2NiY+/fvU1ZWpoklKSmpyn1sUT1nZ2fg2bnev38/\nq1atIj8/X7O/pKSE5ORkrZlQafe6788//+T06dNVno2qjnq8iYyMZNeuXaSmpmr21dTmtcXCwgIz\nMzNSUlLYsWOH5p9w1H3qReqYjhw5wq1bt/jll19YuXIlKpWKPXv2kJ2dTdu2bWnbti0VFRUUFxdr\n+tqZM2dITEyktLS01uL/r6rpPKrX2U1LS2P//v1aM1k1edW+VxP1+BYbG0thYSGZmZlERkby/vvv\n6xzH1InT8ePH6dq1K127dtUkh3Z2dgD069ePoqIiVqxYwYoVKygqKqq2nz1v7dq16OvrM2nSpFo5\ntjdVL5KqDh064O/vz927d9mzZ49mEWd147+oV69euLi4cPnyZRITEzXPl6jrmjdvHnfv3mXnzp3Y\n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\nAABJRU5ErkJggg==\n",
1172 | "text/plain": [
1173 | ""
1174 | ]
1175 | },
1176 | "metadata": {
1177 | "tags": []
1178 | },
1179 | "output_type": "display_data"
1180 | }
1181 | ],
1182 | "source": [
1183 | "SMALL_SIZE = 8\n",
1184 | "MEDIUM_SIZE = 10\n",
1185 | "BIGGER_SIZE = 12\n",
1186 | "\n",
1187 | "mpl.rc('font', size=MEDIUM_SIZE) # controls default text sizes\n",
1188 | "mpl.rc('axes', titlesize=18) # fontsize of the axes title\n",
1189 | "mpl.rc('axes', labelsize=16) # fontsize of the x and y labels\n",
1190 | "mpl.rc('xtick', labelsize=MEDIUM_SIZE) # fontsize of the tick labels\n",
1191 | "mpl.rc('ytick', labelsize=MEDIUM_SIZE) # fontsize of the tick labels\n",
1192 | "mpl.rc('legend', fontsize=BIGGER_SIZE) # legend fontsize\n",
1193 | "mpl.rc('figure', titlesize=BIGGER_SIZE) # fontsize of the figure title\n",
1194 | "\n",
1195 | "y_pos = np.arange(len(models))\n",
1196 | "rects1 = plt.bar(y_pos-0.12, training_scores, 0.35, alpha=0.8, color=color[2], label=\"train score\")\n",
1197 | "rects2 = plt.bar(y_pos+0.13, test_scores, 0.35, alpha=0.8, color=color[5], label=\"test score\")\n",
1198 | "plt.xticks(y_pos, models)\n",
1199 | "plt.xlabel('Models')\n",
1200 | "plt.title('R2 scores of different models')\n",
1201 | "plt.legend()\n",
1202 | "\n",
1203 | "def autolabel(rects):\n",
1204 | " \"\"\"\n",
1205 | " Attach a text label above each bar displaying its height\n",
1206 | " \"\"\"\n",
1207 | " for rect in rects:\n",
1208 | " height = rect.get_height()\n",
1209 | " plt.text(rect.get_x() + rect.get_width()/2., 1.01*height,\n",
1210 | " '%.2f' % float(height),\n",
1211 | " ha='center', va='bottom')\n",
1212 | "\n",
1213 | "autolabel(rects1)\n",
1214 | "autolabel(rects2)\n",
1215 | "\n",
1216 | "plt.show()"
1217 | ]
1218 | }
1219 | ],
1220 | "metadata": {
1221 | "accelerator": "GPU",
1222 | "colab": {
1223 | "default_view": {},
1224 | "name": "Untitled0.ipynb",
1225 | "provenance": [],
1226 | "version": "0.3.2",
1227 | "views": {}
1228 | },
1229 | "kernelspec": {
1230 | "display_name": "Python 3",
1231 | "language": "python",
1232 | "name": "python3"
1233 | },
1234 | "language_info": {
1235 | "codemirror_mode": {
1236 | "name": "ipython",
1237 | "version": 3
1238 | },
1239 | "file_extension": ".py",
1240 | "mimetype": "text/x-python",
1241 | "name": "python",
1242 | "nbconvert_exporter": "python",
1243 | "pygments_lexer": "ipython3",
1244 | "version": "3.6.4"
1245 | }
1246 | },
1247 | "nbformat": 4,
1248 | "nbformat_minor": 1
1249 | }
1250 |
--------------------------------------------------------------------------------
/scripts/bash/git_star_pred_DO_conf cmds:
--------------------------------------------------------------------------------
1 | git clone https://github.com/Doodies/Github-Stars-Predictor.git
2 | cd Github-Stars-Predictor/scripts/bash
3 | vim settingUpDOServer.sh
4 |
5 | chmod +x settingUpDOServer.sh
6 | ./settingUpDOServer.sh
7 |
8 | cd ./../nodejs/
9 | tmux new -s dataset
10 | node githubGraphQLApiCallsDO_V3.js
11 |
--------------------------------------------------------------------------------
/scripts/bash/settingUpDOServer.sh:
--------------------------------------------------------------------------------
1 | cd ./../nodejs
2 | curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
3 | sudo apt-get install -y nodejs
4 | npm install
5 | echo "TOKEN =
6 | START = 0
7 | END = 10000" > .env
8 | mkdir graphQlData
9 | cd ./../../
10 | cp .tmux.conf ~/.tmux.conf
11 |
--------------------------------------------------------------------------------
/scripts/nodejs/getting_repos_v2.js:
--------------------------------------------------------------------------------
1 | const request = require('request');
2 | let url = 'https://api.github.com/search/repositories';
3 | const json2csv = require('json2csv');
4 | const fs = require('fs');
5 | const dateFormat = require('dateformat');
6 | const dotenv = require("dotenv");
7 | dotenv.config();
8 | dotenv.load();
9 |
10 | let data = [], countExceeds = 0;
11 | let fD = new Date();
12 | let startTime = new Date();
13 | let nReq = 0, nRes = 0, setI, reqSetI;
14 |
15 | function getRepos() {
16 | if (fD <= new Date("2008-1-1")) {
17 | clearInterval(reqSetI);
18 | console.log("Task completed");
19 | // saving data
20 | setI = setInterval(() => {
21 | if (nRes === nReq) {
22 | console.log("total requests: " + nReq + "\ttotal responses: " + nRes + "\texceed count: " + countExceeds);
23 | return saveData();
24 | }
25 | }, 10 * 1000);
26 | return;
27 | }
28 | nReq++;
29 | let myDate;
30 | myDate = fD = new Date(fD - 1000 * 60 * 60 * 24);
31 | let options = {
32 | method: 'GET',
33 | url: url,
34 | qs: {
35 | q: "stars:>=100 created:" + dateFormat(myDate, "yyyy-mm-dd"),
36 | sort: "stars",
37 | order: "asc",
38 | page: 1,
39 | per_page: 101,
40 | client_id: process.env.CLIENT_ID,
41 | client_secret: process.env.CLIENT_SECRET
42 | },
43 | headers: {"User-Agent": "hackbansu"}
44 | };
45 | request(options, (err, res, body) => {
46 | // error handling
47 | if (err || !body) {
48 | console.log("body ==> ", body);
49 | console.log("error ==> ", err);
50 | console.log("some error occurred");
51 | clearInterval(reqSetI);
52 | return saveData();
53 | }
54 | body = JSON.parse(body);
55 | if (!body.items) {
56 | console.log("body ==> ", body);
57 | console.log("body.items not found");
58 | clearInterval(reqSetI);
59 | return saveData();
60 | }
61 |
62 | // this request work
63 | let modItems = body.items.map(x => {
64 | return {
65 | "RepoName": x.name,
66 | "ownerName": x.owner["login"],
67 | "Type": x.owner.type,
68 | "SideAdmin": x.owner["site_admin"],
69 | };
70 | });
71 | data = data.concat(modItems);
72 | nRes++;
73 | console.log(dateFormat(myDate, "dd-mm-yyyy") + "\tResults: " + body["total_count"] + "\tresNum: " + nRes
74 | + "\tcompleted at: " + (new Date() - startTime) / 1000.0 + "s" + "\trepos fetched: " + data.length);
75 | if (body["total_count"] > 100) {
76 | countExceeds++;
77 | console.log("************ count exceeded *************");
78 | }
79 | })
80 | }
81 |
82 | reqSetI = setInterval(getRepos, 2050);
83 |
84 | function saveData() {
85 | clearInterval(setI);
86 | let fields = ['RepoName', 'ownerName', 'Type', 'SideAdmin'];
87 | console.log("len: ", data.length);
88 | let csv = json2csv({data: data, fields: fields});
89 | fs.writeFile('./repos/file_2014-01-01_2018-02-15.csv', csv, function (err) {
90 | if (err) throw err;
91 | console.log('file saved');
92 | });
93 | }
--------------------------------------------------------------------------------
/scripts/nodejs/githubGraphQLApiCallsDO_V2.js:
--------------------------------------------------------------------------------
1 | //setInterval based implementation
2 |
3 | const fs = require('fs');
4 | const csv = require('csvtojson');
5 | const jsonfile = require("jsonfile");
6 | const dotenv = require("dotenv");
7 | dotenv.config();
8 | dotenv.load();
9 | const {request, GraphQLClient} = require('graphql-request');
10 | let url = "https://api.github.com/graphql";
11 | const client = new GraphQLClient(url, {
12 | headers: {
13 | Authorization: 'bearer ' + process.env.TOKEN,
14 | },
15 | });
16 |
17 | // get query for data
18 | function getQuery() {
19 | let q = 'query ($owner: String!, $name: String!, $isUser:Boolean!) { \n' +
20 | ' \n' +
21 | ' organization(login: $owner) @skip(if: $isUser){\n' +
22 | ' login\n' +
23 | ' \n' +
24 | ' repositories{\n' +
25 | ' totalCount\n' +
26 | ' } \n' +
27 | ' \n' +
28 | ' location\t\t#location of organization\n' +
29 | ' \n' +
30 | ' members{\n' +
31 | ' totalCount\n' +
32 | ' }\n' +
33 | ' \n' +
34 | ' websiteUrl \n' +
35 | ' }\n' +
36 | ' \n' +
37 | ' user(login: $owner) @include(if: $isUser){ \n' +
38 | ' login\n' +
39 | ' \n' +
40 | ' followers{\t\t# number of followers of the user\n' +
41 | ' totalCount\n' +
42 | ' } \n' +
43 | '\trepositories{\t\t# number of repositories of the user\n' +
44 | ' totalCount\n' +
45 | ' }\n' +
46 | ' \n' +
47 | ' following{\t# following\n' +
48 | ' totalCount\n' +
49 | ' }\n' +
50 | ' \n' +
51 | ' location # location of user\n' +
52 | ' \n' +
53 | ' organizations{\n' +
54 | ' totalCount\n' +
55 | ' }\n' +
56 | ' \n' +
57 | ' gists(last:100){\n' +
58 | ' edges{\n' +
59 | ' node{ \n' +
60 | ' comments{\n' +
61 | ' totalCount\n' +
62 | ' }\n' +
63 | ' stargazers{\n' +
64 | ' totalCount\n' +
65 | ' } \n' +
66 | ' }\n' +
67 | ' }\n' +
68 | ' totalCount\n' +
69 | ' } \n' +
70 | ' \n' +
71 | ' websiteUrl\n' +
72 | ' }\n' +
73 | ' \n' +
74 | ' repository(owner: $owner, name: $name) {\n' +
75 | ' name\t\t# name of the repo \n' +
76 | '\n' +
77 | ' primaryLanguage{\n' +
78 | ' name\n' +
79 | ' }\n' +
80 | '\n' +
81 | ' license\n' +
82 | ' \n' +
83 | ' isArchived\n' +
84 | '\n' +
85 | ' hasWikiEnabled\n' +
86 | ' \n' +
87 | ' forkCount\n' +
88 | ' \n' +
89 | ' # readme.md of the repo\n' +
90 | ' readme_md:object(expression: "master:README.md"){\n' +
91 | ' ... on Blob{\n' +
92 | ' text\n' +
93 | ' byteSize\n' +
94 | ' }\n' +
95 | ' }\n' +
96 | ' readme_txt:object(expression: "master:README.txt"){\n' +
97 | ' ... on Blob{\n' +
98 | ' text\n' +
99 | ' byteSize\n' +
100 | ' }\n' +
101 | ' }\n' +
102 | ' readme_markdown:object(expression: "master:README.markdown"){\n' +
103 | ' ... on Blob{\n' +
104 | ' text\n' +
105 | ' byteSize\n' +
106 | ' }\n' +
107 | ' }\n' +
108 | ' readme_tst:object(expression: "master:README.tst"){\n' +
109 | ' ... on Blob{\n' +
110 | ' text\n' +
111 | ' byteSize\n' +
112 | ' }\n' +
113 | ' }\n' +
114 | ' readme_:object(expression: "master:README"){\n' +
115 | ' ... on Blob{\n' +
116 | ' text\n' +
117 | ' byteSize\n' +
118 | ' }\n' +
119 | ' }\n' +
120 | ' \n' +
121 | ' stars: stargazers{\n' +
122 | ' totalCount\n' +
123 | ' }\n' +
124 | ' createdAt\n' +
125 | ' updatedAt\n' +
126 | ' pushedAt\n' +
127 | '\n' +
128 | ' \n' +
129 | ' description\n' +
130 | ' \n' +
131 | ' subscribersCount: watchers{\n' +
132 | ' totalCount\n' +
133 | ' }\n' +
134 | ' \n' +
135 | ' # size of repository\n' +
136 | ' diskUsage\n' +
137 | ' \n' +
138 | ' # pull requests number\n' +
139 | ' pullRequestsOpen: pullRequests(states: OPEN){ \n' +
140 | ' totalCount\n' +
141 | ' }\n' +
142 | ' pullRequestsClosed: pullRequests(states: CLOSED){\n' +
143 | ' totalCount\n' +
144 | ' }\n' +
145 | ' pullRequestsMerged: pullRequests(states: MERGED){\n' +
146 | ' totalCount\n' +
147 | ' }\n' +
148 | '\n' +
149 | ' # total number of comments and commits for last open 100 PRs\n' +
150 | ' PROpenCommentsCommitsCount: pullRequests(last:100, states: OPEN){\n' +
151 | ' edges{\n' +
152 | ' node{\n' +
153 | ' comments{\n' +
154 | ' totalCount\n' +
155 | ' }\n' +
156 | ' commits{\n' +
157 | ' totalCount\n' +
158 | ' } \n' +
159 | ' }\n' +
160 | ' }\n' +
161 | ' }\n' +
162 | ' \n' +
163 | ' # total number of comments and commits for last 100 closed PRs\n' +
164 | ' PRClosedCommentsCommitsCount: pullRequests(last:100, states: CLOSED){\n' +
165 | ' edges{\n' +
166 | ' node{\n' +
167 | ' comments{\n' +
168 | ' totalCount\n' +
169 | ' }\n' +
170 | ' commits{\n' +
171 | ' totalCount\n' +
172 | ' } \n' +
173 | ' }\n' +
174 | ' }\n' +
175 | ' }\n' +
176 | ' \n' +
177 | ' # total number of comments and commits for last 100 merged PRs\n' +
178 | ' PRMergedCommentsCommitsCount: pullRequests(last:100, states: MERGED){\n' +
179 | ' edges{\n' +
180 | ' node{\n' +
181 | ' comments{\n' +
182 | ' totalCount\n' +
183 | ' }\n' +
184 | ' commits{\n' +
185 | ' totalCount\n' +
186 | ' } \n' +
187 | ' }\n' +
188 | ' }\n' +
189 | ' }\n' +
190 | ' \n' +
191 | ' # issues number\n' +
192 | ' issuesOpen:issues(states:OPEN){\n' +
193 | ' totalCount\n' +
194 | ' }\n' +
195 | ' issuesClosed:issues(states:CLOSED){\n' +
196 | ' totalCount\n' +
197 | ' }\n' +
198 | ' \n' +
199 | ' # number of comments on last 100 open issues\n' +
200 | ' iOpenCommentsParticipantsCount: issues(last: 100, states:OPEN){\n' +
201 | ' edges{\n' +
202 | ' node{\n' +
203 | ' comments{\n' +
204 | ' totalCount\n' +
205 | ' }\n' +
206 | ' participants{\n' +
207 | ' totalCount\n' +
208 | ' } \n' +
209 | ' }\n' +
210 | ' }\n' +
211 | ' }\n' +
212 | ' \n' +
213 | ' # number of comments on last 100 closed issues\n' +
214 | ' iClosedCommentsParticipantsCount: issues(last: 100, states:CLOSED){\n' +
215 | ' edges{\n' +
216 | ' node{\n' +
217 | ' comments{\n' +
218 | ' totalCount\n' +
219 | ' }\n' +
220 | ' participants{\n' +
221 | ' totalCount\n' +
222 | ' } \n' +
223 | ' }\n' +
224 | ' }\n' +
225 | ' }\n' +
226 | ' \n' +
227 | ' # total number of branches\n' +
228 | ' numBranches:refs(refPrefix: "refs/heads/") {\n' +
229 | ' totalCount \n' +
230 | ' }\n' +
231 | ' \n' +
232 | ' # total commits on master branch\n' +
233 | ' numCommits:ref(qualifiedName: "master"){\n' +
234 | ' target{\n' +
235 | ' ... on Commit{\n' +
236 | ' history{\n' +
237 | ' totalCount\n' +
238 | ' }\n' +
239 | ' }\n' +
240 | ' }\n' +
241 | ' }\n' +
242 | ' \n' +
243 | ' # total number of tags\n' +
244 | ' tags:refs(refPrefix:"refs/tags/"){\n' +
245 | ' totalCount\n' +
246 | ' }\n' +
247 | ' \n' +
248 | ' # total number of releases\n' +
249 | ' releases {\n' +
250 | ' \ttotalCount \n' +
251 | ' }\n' +
252 | ' }\n' +
253 | '}\n';
254 | return q;
255 | }
256 |
257 | //get query for rateLimit enquiry
258 | function getRateLimitQuery() {
259 | let q = "{\n" +
260 | " viewer {\n" +
261 | " login\n" +
262 | " }\n" +
263 | " rateLimit {\n" +
264 | " limit\n" +
265 | " cost\n" +
266 | " remaining\n" +
267 | " resetAt\n" +
268 | " }\n" +
269 | "}";
270 | return q;
271 | }
272 |
273 | let start = parseInt(process.env.START), end = parseInt(process.env.END);
274 | let fMid = "" + start + "_" + end;
275 | let input = "./repos/file_2008-01-01_2018-02-15.csv", output = "./graphQlData/file_" + fMid + ".json";
276 | let nReq = -1, nRes = -1, setI, reqSetI;
277 | let basicData = [], graphQLData = [], errors = 0, errorsList = [];
278 | let startTime = new Date();
279 | const query = getQuery();
280 |
281 | // const query = getRateLimitQuery();
282 |
283 |
284 | function readData() {
285 | console.log("reading csv data from " + input + "...");
286 | csv().fromFile(input).on('json', (jsonObj) => {
287 | basicData.push(jsonObj);
288 | })
289 | .on('done', (error) => {
290 | //error handling
291 | if (error) {
292 | return console.log(error);
293 | }
294 |
295 | // slicing the data
296 | basicData = basicData.slice(start, end + 1);
297 | console.log('done reading data! having length ' + basicData.length + " from " + start + " to " + end);
298 |
299 | //starting the request cycle
300 | console.log("starting to fetch data...");
301 | reqSetI = setInterval(callRequest, parseInt(process.env.LOOPDELAY));
302 | });
303 | }
304 |
305 | function callRequest() {
306 | if (nReq === basicData.length - 1) {
307 | clearInterval(reqSetI);
308 | console.log("Task completed");
309 | // saving data
310 | setI = setInterval(() => {
311 | if (nRes === nReq) {
312 | console.log("total requests: " + nReq + "\ttotal responses: " + nRes
313 | + "\tdataCount: " + graphQLData.length + "\terrors count: " + errors);
314 | console.log("errorList: ", errorsList);
315 | return saveData();
316 | }
317 | }, 10 * 1000);
318 | return;
319 | }
320 |
321 | nReq++;
322 | let myReq = nReq;
323 | let repo = basicData[myReq];
324 | let variables = {
325 | "owner": repo["ownerName"],
326 | "name": repo["RepoName"],
327 | "isUser": repo["Type"] === "User",
328 | };
329 | // console.log(variables);
330 | client
331 | .request(query, variables)
332 | .then(data => {
333 | data["repository"]["type"] = variables["isUser"] ? "user" : "organization";
334 | data["siteAdmin"] = repo["SideAdmin"];
335 | graphQLData.push(data);
336 | nRes++;
337 | console.log("got " + nRes + " response for reqNum " + myReq + "\ttotal data len: " + (graphQLData.length)
338 | + "\terrors: " + errors + "\tat: " + (new Date() - startTime) / 1000.0 + "s");
339 | })
340 | .catch((err) => {
341 | nRes++;
342 | console.log("got error on " + myReq + " data! ************************************");
343 | errors++;
344 | errorsList.push(myReq);
345 | console.log(err.response);
346 | });
347 | }
348 |
349 | function saveData() {
350 | clearInterval(setI);
351 | console.log("saving data having length: " + graphQLData.length + " to " + output + "...");
352 | jsonfile.writeFile(output, graphQLData, function (err) {
353 | if (err) {
354 | return console.log(err);
355 | }
356 | console.log("done saving! " + graphQLData.length + " items");
357 | })
358 | }
359 |
360 | function callRateLimitRequest() {
361 | client
362 | .request(query)
363 | .then(data => {
364 | console.log(data);
365 | console.log("fetched!");
366 | })
367 | .catch((err) => {
368 | console.log("error: ");
369 | console.log(err.response)
370 | });
371 | }
372 |
373 | //starting to read data
374 | readData();
375 | // callRateLimitRequest();
--------------------------------------------------------------------------------
/scripts/nodejs/githubGraphQLApiCallsDO_V3.js:
--------------------------------------------------------------------------------
1 | //request-response-request based implementation
2 |
3 | const fs = require('fs');
4 | const csv = require('csvtojson');
5 | const jsonfile = require("jsonfile");
6 | const dotenv = require("dotenv");
7 | dotenv.config();
8 | dotenv.load();
9 | const {request, GraphQLClient} = require('graphql-request');
10 | let url = "https://api.github.com/graphql";
11 | const client = new GraphQLClient(url, {
12 | headers: {
13 | Authorization: 'bearer ' + process.env.TOKEN,
14 | },
15 | });
16 |
17 | // get query for data
18 | function getQuery() {
19 | let q = 'query ($owner: String!, $name: String!, $isUser:Boolean!) { \n' +
20 | ' \n' +
21 | ' organization(login: $owner) @skip(if: $isUser){\n' +
22 | ' login\n' +
23 | ' \n' +
24 | ' repositories{\n' +
25 | ' totalCount\n' +
26 | ' } \n' +
27 | ' \n' +
28 | ' location\t\t#location of organization\n' +
29 | ' \n' +
30 | ' members{\n' +
31 | ' totalCount\n' +
32 | ' }\n' +
33 | ' \n' +
34 | ' websiteUrl \n' +
35 | ' }\n' +
36 | ' \n' +
37 | ' user(login: $owner) @include(if: $isUser){ \n' +
38 | ' login\n' +
39 | ' \n' +
40 | ' followers{\t\t# number of followers of the user\n' +
41 | ' totalCount\n' +
42 | ' } \n' +
43 | '\trepositories{\t\t# number of repositories of the user\n' +
44 | ' totalCount\n' +
45 | ' }\n' +
46 | ' \n' +
47 | ' following{\t# following\n' +
48 | ' totalCount\n' +
49 | ' }\n' +
50 | ' \n' +
51 | ' location # location of user\n' +
52 | ' \n' +
53 | ' organizations{\n' +
54 | ' totalCount\n' +
55 | ' }\n' +
56 | ' \n' +
57 | ' gists(last:100){\n' +
58 | ' edges{\n' +
59 | ' node{ \n' +
60 | ' comments{\n' +
61 | ' totalCount\n' +
62 | ' }\n' +
63 | ' stargazers{\n' +
64 | ' totalCount\n' +
65 | ' } \n' +
66 | ' }\n' +
67 | ' }\n' +
68 | ' totalCount\n' +
69 | ' } \n' +
70 | ' \n' +
71 | ' websiteUrl\n' +
72 | ' }\n' +
73 | ' \n' +
74 | ' repository(owner: $owner, name: $name) {\n' +
75 | ' name\t\t# name of the repo \n' +
76 | '\n' +
77 | ' primaryLanguage{\n' +
78 | ' name\n' +
79 | ' }\n' +
80 | '\n' +
81 | ' license\n' +
82 | ' \n' +
83 | ' isArchived\n' +
84 | '\n' +
85 | ' hasWikiEnabled\n' +
86 | ' \n' +
87 | ' forkCount\n' +
88 | ' \n' +
89 | ' # readme.md of the repo\n' +
90 | ' readme_md:object(expression: "master:README.md"){\n' +
91 | ' ... on Blob{\n' +
92 | ' text\n' +
93 | ' byteSize\n' +
94 | ' }\n' +
95 | ' }\n' +
96 | ' readme_txt:object(expression: "master:README.txt"){\n' +
97 | ' ... on Blob{\n' +
98 | ' text\n' +
99 | ' byteSize\n' +
100 | ' }\n' +
101 | ' }\n' +
102 | ' readme_markdown:object(expression: "master:README.markdown"){\n' +
103 | ' ... on Blob{\n' +
104 | ' text\n' +
105 | ' byteSize\n' +
106 | ' }\n' +
107 | ' }\n' +
108 | ' readme_tst:object(expression: "master:README.tst"){\n' +
109 | ' ... on Blob{\n' +
110 | ' text\n' +
111 | ' byteSize\n' +
112 | ' }\n' +
113 | ' }\n' +
114 | ' readme_:object(expression: "master:README"){\n' +
115 | ' ... on Blob{\n' +
116 | ' text\n' +
117 | ' byteSize\n' +
118 | ' }\n' +
119 | ' }\n' +
120 | ' \n' +
121 | ' stars: stargazers{\n' +
122 | ' totalCount\n' +
123 | ' }\n' +
124 | ' createdAt\n' +
125 | ' updatedAt\n' +
126 | ' pushedAt\n' +
127 | '\n' +
128 | ' \n' +
129 | ' description\n' +
130 | ' \n' +
131 | ' subscribersCount: watchers{\n' +
132 | ' totalCount\n' +
133 | ' }\n' +
134 | ' \n' +
135 | ' # size of repository\n' +
136 | ' diskUsage\n' +
137 | ' \n' +
138 | ' # pull requests number\n' +
139 | ' pullRequestsOpen: pullRequests(states: OPEN){ \n' +
140 | ' totalCount\n' +
141 | ' }\n' +
142 | ' pullRequestsClosed: pullRequests(states: CLOSED){\n' +
143 | ' totalCount\n' +
144 | ' }\n' +
145 | ' pullRequestsMerged: pullRequests(states: MERGED){\n' +
146 | ' totalCount\n' +
147 | ' }\n' +
148 | '\n' +
149 | ' # total number of comments and commits for last open 100 PRs\n' +
150 | ' PROpenCommentsCommitsCount: pullRequests(last:100, states: OPEN){\n' +
151 | ' edges{\n' +
152 | ' node{\n' +
153 | ' comments{\n' +
154 | ' totalCount\n' +
155 | ' }\n' +
156 | ' commits{\n' +
157 | ' totalCount\n' +
158 | ' } \n' +
159 | ' }\n' +
160 | ' }\n' +
161 | ' }\n' +
162 | ' \n' +
163 | ' # total number of comments and commits for last 100 closed PRs\n' +
164 | ' PRClosedCommentsCommitsCount: pullRequests(last:100, states: CLOSED){\n' +
165 | ' edges{\n' +
166 | ' node{\n' +
167 | ' comments{\n' +
168 | ' totalCount\n' +
169 | ' }\n' +
170 | ' commits{\n' +
171 | ' totalCount\n' +
172 | ' } \n' +
173 | ' }\n' +
174 | ' }\n' +
175 | ' }\n' +
176 | ' \n' +
177 | ' # total number of comments and commits for last 100 merged PRs\n' +
178 | ' PRMergedCommentsCommitsCount: pullRequests(last:100, states: MERGED){\n' +
179 | ' edges{\n' +
180 | ' node{\n' +
181 | ' comments{\n' +
182 | ' totalCount\n' +
183 | ' }\n' +
184 | ' commits{\n' +
185 | ' totalCount\n' +
186 | ' } \n' +
187 | ' }\n' +
188 | ' }\n' +
189 | ' }\n' +
190 | ' \n' +
191 | ' # issues number\n' +
192 | ' issuesOpen:issues(states:OPEN){\n' +
193 | ' totalCount\n' +
194 | ' }\n' +
195 | ' issuesClosed:issues(states:CLOSED){\n' +
196 | ' totalCount\n' +
197 | ' }\n' +
198 | ' \n' +
199 | ' # number of comments on last 100 open issues\n' +
200 | ' iOpenCommentsParticipantsCount: issues(last: 100, states:OPEN){\n' +
201 | ' edges{\n' +
202 | ' node{\n' +
203 | ' comments{\n' +
204 | ' totalCount\n' +
205 | ' }\n' +
206 | ' participants{\n' +
207 | ' totalCount\n' +
208 | ' } \n' +
209 | ' }\n' +
210 | ' }\n' +
211 | ' }\n' +
212 | ' \n' +
213 | ' # number of comments on last 100 closed issues\n' +
214 | ' iClosedCommentsParticipantsCount: issues(last: 100, states:CLOSED){\n' +
215 | ' edges{\n' +
216 | ' node{\n' +
217 | ' comments{\n' +
218 | ' totalCount\n' +
219 | ' }\n' +
220 | ' participants{\n' +
221 | ' totalCount\n' +
222 | ' } \n' +
223 | ' }\n' +
224 | ' }\n' +
225 | ' }\n' +
226 | ' \n' +
227 | ' # total number of branches\n' +
228 | ' numBranches:refs(refPrefix: "refs/heads/") {\n' +
229 | ' totalCount \n' +
230 | ' }\n' +
231 | ' \n' +
232 | ' # total commits on master branch\n' +
233 | ' numCommits:ref(qualifiedName: "master"){\n' +
234 | ' target{\n' +
235 | ' ... on Commit{\n' +
236 | ' history{\n' +
237 | ' totalCount\n' +
238 | ' }\n' +
239 | ' }\n' +
240 | ' }\n' +
241 | ' }\n' +
242 | ' \n' +
243 | ' # total number of tags\n' +
244 | ' tags:refs(refPrefix:"refs/tags/"){\n' +
245 | ' totalCount\n' +
246 | ' }\n' +
247 | ' \n' +
248 | ' # total number of releases\n' +
249 | ' releases {\n' +
250 | ' \ttotalCount \n' +
251 | ' }\n' +
252 | ' }\n' +
253 | '}\n';
254 | return q;
255 | }
256 |
257 | //get query for rateLimit enquiry
258 | function getRateLimitQuery() {
259 | let q = "{\n" +
260 | " viewer {\n" +
261 | " login\n" +
262 | " }\n" +
263 | " rateLimit {\n" +
264 | " limit\n" +
265 | " cost\n" +
266 | " remaining\n" +
267 | " resetAt\n" +
268 | " }\n" +
269 | "}";
270 | return q;
271 | }
272 |
273 | let start = parseInt(process.env.START), end = parseInt(process.env.END);
274 | let fMid = "" + start + "_" + end;
275 | let input = "./repos/file_2008-01-01_2018-02-15.csv", output = "./graphQlData/file_" + fMid + ".json";
276 | let nReq = -1, nRes = -1;
277 | let basicData = [], graphQLData = [], errors = 0, errorsList = [];
278 | let startTime = new Date();
279 | const query = getQuery();
280 |
281 | // const query = getRateLimitQuery();
282 |
283 |
284 | function readData() {
285 | console.log("reading csv data from " + input + "...");
286 | csv().fromFile(input).on('json', (jsonObj) => {
287 | basicData.push(jsonObj);
288 | })
289 | .on('done', (error) => {
290 | //error handling
291 | if (error) {
292 | return console.log(error);
293 | }
294 |
295 | // slicing the data
296 | basicData = basicData.slice(start, end + 1);
297 | console.log('done reading data! having length ' + basicData.length + " from " + start + " to " + end);
298 |
299 | //starting the request cycle
300 | console.log("starting to fetch data...");
301 | callRequest();
302 | });
303 | }
304 |
305 | function callRequest() {
306 | if (nReq === basicData.length - 1) {
307 | console.log("Task completed");
308 | // saving data
309 | console.log("total requests: " + nReq + "\ttotal responses: " + nRes
310 | + "\tdataCount: " + graphQLData.length + "\terrors count: " + errors);
311 | console.log("errorList: ", errorsList);
312 | return saveData();
313 | }
314 |
315 | nReq++;
316 | let myReq = nReq;
317 | let repo = basicData[myReq];
318 | let variables = {
319 | "owner": repo["ownerName"],
320 | "name": repo["RepoName"],
321 | "isUser": repo["Type"] === "User",
322 | };
323 | // console.log(variables);
324 | client
325 | .request(query, variables)
326 | .then(data => {
327 | data["repository"]["type"] = variables["isUser"] ? "user" : "organization";
328 | data["siteAdmin"] = repo["SideAdmin"];
329 | graphQLData.push(data);
330 | nRes++;
331 | console.log("got " + nRes + " response for reqNum " + myReq + "\ttotal data len: " + (graphQLData.length)
332 | + "\terrors: " + errors + "\tat: " + (new Date() - startTime) / 1000.0 + "s");
333 | callRequest();
334 | })
335 | .catch((err) => {
336 | nRes++;
337 | console.log("got error on " + myReq + " data! ************************************");
338 | errors++;
339 | errorsList.push(myReq);
340 | console.log(err.response);
341 | callRequest();
342 | });
343 | }
344 |
345 | function saveData() {
346 | console.log("saving data having length: " + graphQLData.length + " to " + output + "...");
347 | jsonfile.writeFile(output, graphQLData, function (err) {
348 | if (err) {
349 | return console.log(err);
350 | }
351 | console.log("done saving! " + graphQLData.length + " items");
352 | })
353 | }
354 |
355 | function callRateLimitRequest() {
356 | client
357 | .request(query)
358 | .then(data => {
359 | console.log(data);
360 | console.log("fetched!");
361 | })
362 | .catch((err) => {
363 | console.log("error: ");
364 | console.log(err.response)
365 | });
366 | }
367 |
368 | //starting to read data
369 | readData();
370 | // callRateLimitRequest();
--------------------------------------------------------------------------------
/scripts/nodejs/graphql queries:
--------------------------------------------------------------------------------
1 | query ($owner: String!, $name: String!, $isUser:Boolean!) {
2 |
3 | organization(login: $owner) @skip(if: $isUser){
4 | login
5 |
6 | repositories{
7 | totalCount
8 | }
9 |
10 | location #location of organization
11 |
12 | members{
13 | totalCount
14 | }
15 |
16 | websiteUrl
17 | }
18 |
19 | user(login: $owner) @include(if: $isUser){
20 | login
21 |
22 | followers{ # number of followers of the user
23 | totalCount
24 | }
25 | repositories{ # number of repositories of the user
26 | totalCount
27 | }
28 |
29 | following{ # following
30 | totalCount
31 | }
32 |
33 | location # location of user
34 |
35 | organizations{
36 | totalCount
37 | }
38 |
39 | gists(last:100){
40 | edges{
41 | node{
42 | comments{
43 | totalCount
44 | }
45 | stargazers{
46 | totalCount
47 | }
48 | }
49 | }
50 | totalCount
51 | }
52 |
53 | websiteUrl
54 | }
55 |
56 | repository(owner: $owner, name: $name) {
57 | name # name of the repo
58 |
59 | primaryLanguage{
60 | name
61 | }
62 |
63 | license
64 |
65 | isArchived
66 |
67 | hasWikiEnabled
68 |
69 | forkCount
70 |
71 | # readme.md of the repo
72 | readme_md:object(expression: "master:README.md"){
73 | ... on Blob{
74 | text
75 | byteSize
76 | }
77 | }
78 | readme_txt:object(expression: "master:README.txt"){
79 | ... on Blob{
80 | text
81 | byteSize
82 | }
83 | }
84 | readme_markdown:object(expression: "master:README.markdown"){
85 | ... on Blob{
86 | text
87 | byteSize
88 | }
89 | }
90 | readme_tst:object(expression: "master:README.tst"){
91 | ... on Blob{
92 | text
93 | byteSize
94 | }
95 | }
96 | readme_:object(expression: "master:README"){
97 | ... on Blob{
98 | text
99 | byteSize
100 | }
101 | }
102 |
103 | stars: stargazers{
104 | totalCount
105 | }
106 | createdAt
107 | updatedAt
108 | pushedAt
109 |
110 |
111 | description
112 |
113 | subscribersCount: watchers{
114 | totalCount
115 | }
116 |
117 | # size of repository
118 | diskUsage
119 |
120 | # pull requests number
121 | pullRequestsOpen: pullRequests(states: OPEN){
122 | totalCount
123 | }
124 | pullRequestsClosed: pullRequests(states: CLOSED){
125 | totalCount
126 | }
127 | pullRequestsMerged: pullRequests(states: MERGED){
128 | totalCount
129 | }
130 |
131 | # total number of comments and commits for last open 100 PRs
132 | PROpenCommentsCommitsCount: pullRequests(last:100, states: OPEN){
133 | edges{
134 | node{
135 | comments{
136 | totalCount
137 | }
138 | commits{
139 | totalCount
140 | }
141 | }
142 | }
143 | }
144 |
145 | # total number of comments and commits for last 100 closed PRs
146 | PRClosedCommentsCommitsCount: pullRequests(last:100, states: CLOSED){
147 | edges{
148 | node{
149 | comments{
150 | totalCount
151 | }
152 | commits{
153 | totalCount
154 | }
155 | }
156 | }
157 | }
158 |
159 | # total number of comments and commits for last 100 merged PRs
160 | PRMergedCommentsCommitsCount: pullRequests(last:100, states: MERGED){
161 | edges{
162 | node{
163 | comments{
164 | totalCount
165 | }
166 | commits{
167 | totalCount
168 | }
169 | }
170 | }
171 | }
172 |
173 | # issues number
174 | issuesOpen:issues(states:OPEN){
175 | totalCount
176 | }
177 | issuesClosed:issues(states:CLOSED){
178 | totalCount
179 | }
180 |
181 | # number of comments on last 100 open issues
182 | iOpenCommentsParticipantsCount: issues(last: 100, states:OPEN){
183 | edges{
184 | node{
185 | comments{
186 | totalCount
187 | }
188 | participants{
189 | totalCount
190 | }
191 | }
192 | }
193 | }
194 |
195 | # number of comments on last 100 closed issues
196 | iClosedCommentsParticipantsCount: issues(last: 100, states:CLOSED){
197 | edges{
198 | node{
199 | comments{
200 | totalCount
201 | }
202 | participants{
203 | totalCount
204 | }
205 | }
206 | }
207 | }
208 |
209 | # total number of branches
210 | numBranches:refs(refPrefix: "refs/heads/") {
211 | totalCount
212 | }
213 |
214 | # total commits on master branch
215 | numCommits:ref(qualifiedName: "master"){
216 | target{
217 | ... on Commit{
218 | history{
219 | totalCount
220 | }
221 | }
222 | }
223 | }
224 |
225 | # total number of tags
226 | tags:refs(refPrefix:"refs/tags/"){
227 | totalCount
228 | }
229 |
230 | # total number of releases
231 | releases {
232 | totalCount
233 | }
234 | }
235 | }
236 |
--------------------------------------------------------------------------------
/scripts/nodejs/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "git-star-predictor",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "Get-Contributors.js",
6 | "dependencies": {
7 | "csvtojson": "^1.1.9",
8 | "dateformat": "^3.0.3",
9 | "dotenv": "^5.0.0",
10 | "graphql-request": "^1.4.1",
11 | "json2csv": "^3.11.5",
12 | "jsonfile": "^4.0.0",
13 | "request": "^2.83.0"
14 | },
15 | "devDependencies": {},
16 | "scripts": {
17 | "test": "echo \"Error: no test specified\" && exit 1"
18 | },
19 | "author": "",
20 | "license": "ISC"
21 | }
22 |
--------------------------------------------------------------------------------
/scripts/nodejs/test.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Doodies/Github-Stars-Predictor/dc8c16a0516fe85ec130caadde5c577493860cb6/scripts/nodejs/test.js
--------------------------------------------------------------------------------
/scripts/nodejs/test3.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Doodies/Github-Stars-Predictor/dc8c16a0516fe85ec130caadde5c577493860cb6/scripts/nodejs/test3.js
--------------------------------------------------------------------------------
/scripts/python/json_to_csv.py:
--------------------------------------------------------------------------------
1 | import json
2 | from pprint import pprint
3 | import pandas as pd
4 | import sys
5 | import re
6 | import os
7 |
8 | reload(sys)
9 | sys.setdefaultencoding('utf-8')
10 |
11 | user_values = []
12 | org_values = []
13 | user_col = []
14 | org_col = []
15 |
16 | isEmptyUser = True
17 | isEmptyOrg = True
18 |
19 | def isReadmeFileExist(repo):
20 | value = ''
21 | find = False
22 | for readme in repo.keys():
23 | if str(readme).startswith('readme'):
24 | if i['repository'][str(readme)] != None and len(i['repository'][str(readme)]) > 0:
25 | find = True
26 | value = readme
27 |
28 | return value if find else None
29 | def handle_gist(gists):
30 | gists = gists['edges']
31 | gistStars = 0
32 | gistComments = 0
33 | for gist in gists:
34 | gistStars += gist['node']['stargazers']['totalCount']
35 | gistComments += gist['node']['comments']['totalCount']
36 | return gistStars, gistComments
37 |
38 | def handle_pr(pr):
39 | pr = pr['edges']
40 | prComments = 0
41 | prCommits = 0
42 | for p in pr:
43 | prComments += p['node']['comments']['totalCount']
44 | prCommits += p['node']['commits']['totalCount']
45 | # print(str(pr['node']['comments']['totalCount']))
46 | return prCommits, prComments
47 |
48 | def handle_issues(issues):
49 | issues = issues['edges']
50 | issuesComments = 0
51 | issuesParticipants = 0
52 | for issue in issues:
53 | issuesComments += issue['node']['comments']['totalCount']
54 | issuesParticipants += issue['node']['participants']['totalCount']
55 | return issuesParticipants, issuesComments
56 |
57 | def handle_readme(string):
58 | links_count = len(re.findall(r'(https?://[^\s]+)', string))
59 | word_count = len(re.findall(r'\w+', string))
60 | char_count = len(string)
61 | return char_count, word_count, links_count
62 |
63 | def handle_objects(obj):
64 | global isEmptyUser
65 | global isEmptyOrg
66 | global user_values
67 | global org_values
68 | global user_col
69 | global org_col
70 | data_dict = {}
71 |
72 | data_dict['siteAdmin'] = obj['siteAdmin']
73 |
74 | repo = obj['repository']
75 | # print repo
76 |
77 | data_dict['reponame'] = str(repo['name'])
78 | data_dict['createdAt'] = repo['createdAt']
79 | data_dict['pushedAt'] = repo['pushedAt']
80 | data_dict['updatedAt'] = repo['updatedAt']
81 | data_dict['description'] = repo['description']
82 | data_dict['diskUsage'] = repo['diskUsage']
83 | data_dict['forkCount'] = repo['forkCount']
84 | data_dict['hasWikiEnabled'] = repo['hasWikiEnabled']
85 | data_dict['isArchived'] = repo['isArchived']
86 | data_dict['issuesClosed'] = repo['issuesClosed']['totalCount']
87 | data_dict['issuesOpen'] = repo['issuesOpen']['totalCount']
88 | data_dict['license'] = repo['license'] if repo['license'] is not None else ""
89 | data_dict['primaryLanguage'] = repo['primaryLanguage']['name'] if repo['primaryLanguage'] is not None else ""
90 | data_dict['prClosed'] = repo['pullRequestsClosed']['totalCount']
91 | data_dict['prMerged'] = repo['pullRequestsMerged']['totalCount']
92 | data_dict['prOpen'] = repo['pullRequestsOpen']['totalCount']
93 | data_dict['releases'] = repo['releases']['totalCount']
94 | data_dict['stars'] = repo['stars']['totalCount']
95 | data_dict['subscribersCount'] = repo['subscribersCount']['totalCount']
96 | data_dict['tags'] = repo['tags']['totalCount']
97 | data_dict['branches'] = repo['numBranches']['totalCount']
98 | data_dict['commits'] = repo['numCommits']['target']['history']['totalCount'] if repo['numCommits'] is not None else ""
99 | data_dict['prMergedCommits'], data_dict['prMergedComments'] = handle_pr(repo['PRMergedCommentsCommitsCount'])
100 | data_dict['prOpenCommits'], data_dict['prOpenComments'] = handle_pr(repo['PROpenCommentsCommitsCount'])
101 | data_dict['prClosedCommits'], data_dict['prClosedComments'] = handle_pr(repo['PRClosedCommentsCommitsCount'])
102 | data_dict['iOpenParticipants'], data_dict['iOpenComments'] = handle_issues(repo['iOpenCommentsParticipantsCount'])
103 | data_dict['iClosedParticipants'], data_dict['iClosedComments'] = handle_issues(repo['iClosedCommentsParticipantsCount'])
104 | data_dict['type'] = repo['type']
105 |
106 | # Handle the readme file
107 |
108 | data_dict["readmeCharCount"] = 0
109 | data_dict["readmeWordCount"] = 0
110 | data_dict["readmeLinkCount"] = 0
111 | data_dict["readmeSize"] = 0
112 |
113 | readmeExt = isReadmeFileExist(repo)
114 | if readmeExt != None:
115 | # print readmeExt
116 | data_dict['readmeSize'] = repo[readmeExt]["byteSize"]
117 | data_dict['readmeCharCount'], data_dict['readmeWordCount'], data_dict['readmeLinkCount'] = handle_readme(repo[readmeExt]['text'])
118 |
119 |
120 |
121 | # if the repo from the user
122 | if obj.keys()[0] == 'user':
123 | user = obj['user']
124 | # pprint(user)
125 | data_dict['login'] = user['login']
126 | data_dict['followers'] = user["followers"]["totalCount"]
127 | data_dict['following'] = user["following"]["totalCount"]
128 | data_dict['gists'] = user['gists']['totalCount']
129 | data_dict['gistStar'], data_dict['gistComments'] = handle_gist(user['gists'])
130 | data_dict['location'] = user['location']
131 | data_dict['organizations'] = user["organizations"]["totalCount"]
132 | data_dict['repositories'] = user["repositories"]["totalCount"]
133 | data_dict['websiteUrl'] = user["websiteUrl"]
134 |
135 | if isEmptyUser:
136 | user_col = list(data_dict.keys())
137 | isEmptyUser = False
138 | user_values.append(list(data_dict.values()))
139 |
140 | # if the repository from the organization
141 | elif obj.keys()[0] == 'organization':
142 | org = obj['organization']
143 | data_dict['login'] = org['login']
144 | data_dict['websiteUrl'] = org['websiteUrl']
145 | data_dict['members'] = org['members']["totalCount"]
146 | data_dict['location'] = org['location']
147 | data_dict['repositories'] = org["repositories"]["totalCount"]
148 |
149 | if isEmptyOrg:
150 | org_col = list(data_dict.keys())
151 | isEmptyOrg = False
152 | org_values.append(list(data_dict.values()))
153 |
154 |
155 | def save_files(file_name):
156 | file_name += '.csv'
157 | global user_col
158 | global org_col
159 | global user_values
160 | global org_values
161 | df_user = pd.DataFrame(data = user_values, columns = user_col)
162 | df_org = pd.DataFrame(data = org_values, columns = org_col)
163 | # print("\nsaving..... user dataframe")
164 | # df_user.to_csv('user.csv', index = False)
165 | # print("\nsaving..... org dataframe")
166 | # df_org.to_csv('org.csv', index = False)
167 |
168 | merge = df_user.append(df_org)
169 | print("\nsaving..... + " + file_name + " dataframe")
170 | merge.to_csv(file_name, index = False)
171 |
172 | # # user data
173 | # # pprint(repo)
174 |
175 |
176 |
177 | # # if isEmpty:
178 | # # df = pd.DataFrame(columns = list(data_dict.keys()))
179 | # # isEmpty = False
180 | # # append the row to the pandas dataframe
181 | # df.loc[df.index.max() + 1, list(data_dict.keys())] = list(data_dict.values())
182 | # pprint(data_dict)
183 |
184 |
185 | # count = 0
186 | # for i in data:
187 | # if i['repository']['object'] == None:
188 | # count+=1
189 | # print count
190 |
191 | # print(len(data_dict))
192 | # print(createdAt,pushedAt,updatedAt,diskUsage,forkCount,hasWikiEnabled,isArchived,issuesClosed,issuesOpen,license,primaryLanguage,prClosed,prMerged,prOpen,releases,stars,subscribersCount,tags)
193 | # handle_objects(data[2])
194 |
195 | # print(data)
196 |
197 |
198 | # for i, j in zip(data[0]["user"].keys(), data[4]["organization"].keys()):
199 | # print "{0: <32} {1: <32}".format(i, j)
200 |
201 |
202 | # print data[0]
203 |
204 |
205 |
206 |
207 | path = os.getcwd() + "/"
208 | json_files = []
209 | files = os.listdir(path)
210 | for file in files:
211 | if os.path.splitext(path + file)[1] == '.json':
212 | json_files.append(file)
213 |
214 | print '---------------------------- total files : ' + str(len(json_files))
215 | for file in json_files:
216 | user_values = []
217 | org_values = []
218 | user_col = []
219 | org_col = []
220 |
221 | isEmptyUser = True
222 | isEmptyOrg = True
223 | data = json.load(open(path + file))
224 | count = 0
225 | print '----------------- ' + str(file) + ' -----------------------'
226 | for i in data:
227 | if count % 1000 == 0 and count !=0:
228 | print 'rows :' + str(count)
229 | handle_objects(i)
230 | count+=1
231 | save_files(file[:-5])
232 |
233 |
234 | # for i in data[0]['repository'].keys():
235 | # print i + " " + str(data[0]['repository'][i])
236 | # print(data[2]["organization"].keys())
237 |
238 |
--------------------------------------------------------------------------------
/scripts/python/merge.py:
--------------------------------------------------------------------------------
1 | import pandas as pd
2 | import os
3 | import sys
4 |
5 | merge_file_name = sys.argv[1]
6 | if '.csv' not in merge_file_name:
7 | merge_file_name += '.csv'
8 |
9 | path = os.getcwd() + "/"
10 | csv_files = []
11 | files = os.listdir(path)
12 | for file in files:
13 | if os.path.splitext(path + file)[1] == '.csv':
14 | csv_files.append(file)
15 |
16 | print '----------------------- total files : ' + str(len(csv_files))
17 | df_dict = {}
18 | total_files = len(csv_files)
19 | for index in range(total_files):
20 | df_dict["df"+str(index)] = pd.read_csv(path + csv_files[index])
21 |
22 | temp = pd.DataFrame()
23 | for i in range(total_files):
24 | temp = temp.append(df_dict["df"+str(i)])
25 | print(csv_files[i] + " shape:" + str(df_dict["df"+str(i)].shape))
26 |
27 | print("------------------\n")
28 | print("final_shape :"+str(temp.shape))
29 | temp.to_csv(merge_file_name, index = False)
30 |
--------------------------------------------------------------------------------