From 1b1b849eb854cdd8a328f7bd8d87f17be78ceb58 Mon Sep 17 00:00:00 2001 From: Keanu Nichols Date: Thu, 9 Aug 2018 16:44:03 -0400 Subject: [PATCH] Documentation Added documentation for the jupyter notebooks I worked on --- notebooks/PiperMail.ipynb | 209 +++-- notebooks/Sentiment_Piper.ipynb | 830 +++----------------- notebooks/github-issues.ipynb | 63 +- notebooks/github_issues_scores.ipynb | 250 ++---- notebooks/github_pull_requests.ipynb | 54 +- notebooks/github_pull_requests_scores.ipynb | 217 ++--- 6 files changed, 422 insertions(+), 1201 deletions(-) diff --git a/notebooks/PiperMail.ipynb b/notebooks/PiperMail.ipynb index 1cbdc62292..13017a49ed 100644 --- a/notebooks/PiperMail.ipynb +++ b/notebooks/PiperMail.ipynb @@ -3,14 +3,14 @@ { "cell_type": "code", "execution_count": 1, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "import augur\n", "from augur.piper_reader import PiperMail\n", "from sqlalchemy.ext.declarative import declarative_base\n", - "# import everything from githubapi.py and ghtorrent.py so we can\n", - "# just copy and paste our function later\n", "import json\n", "import pandas as pd\n", "from perceval.backends.core.pipermail import Pipermail,PipermailList\n", @@ -24,6 +24,14 @@ "from dateutil.parser import parse" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Load:\n", + "First loads the users data from 'augur.config.json' so will take the Database information (e.g. name of database, port of database). Then connects to the database using augur.App.ghtorrentplus() and also loads the piper_reader and loads the path to the list of mailing lists 'runtine/mailing_lists.csv'" + ] + }, { "cell_type": "code", "execution_count": 2, @@ -40,14 +48,12 @@ ] }, { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "collapsed": true - }, - "outputs": [], + "cell_type": "markdown", + "metadata": {}, "source": [ - "#connect.db.execute(\"\"\"DROP TABLE mailing_list_jobs\"\"\")" + "## Connect:\n", + "\n", + "Queries what tables are in the database and determines if 'mail_lists' is there if it is 'mail_lists' is set as 'True' if it isn't 'mail_lists' is set at 'False'. Then we determine what mailing lists are in 'mailing_list_jobs' and we determine how many rows are in it. If 'mailing_list_jobs' is not in the Database it is created and the column 'augurlistID' is set as the primary key. We then add a connection to 'mailing_list_jobs' so that we can change the column 'last_message_date' if new messages were downloaded for a mailing list." ] }, { @@ -107,6 +113,15 @@ "res = session.query(table).all()" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Sifting through messages:\n", + "\n", + "The function 'write_message' is used to fetch the messages from the downloaded MBox's. The messages downloaded can either be from the last message was downloaded when the jupyter notebook was downloaded previously or if it's the first time all the messages are downloaded. The function 'write_message' then determines which message contains the full message thread by looking to see if the 'ID' for the message is stored in 'References'. Only if the next message downloaded does not reference the previous message will the message be added to dictionary and if a certain amount of messages are stored it is added to the table 'mail_lists' using piper_reader." + ] + }, { "cell_type": "code", "execution_count": 5, @@ -120,72 +135,43 @@ " store = None\n", " k = 0\n", " di = {}\n", - " #print(\"HEREEEE\")\n", " for message in repo.fetch(from_date=time):\n", - " #print(message,\"\\n\\n\\n\\n\\n\\n\\n\\n\")\n", - " #print(message['data']['Message-ID'])\n", " if(type_archive == 'not_new'):\n", " mess_check = Piper.convert_date(message['data']['Date'])\n", - " #mess_check = Piper.convert_date(\"Thu, 24 Mar 2019 20:37:11 +0000\")\n", - " #print(time)\n", " if(type_archive == 'not_new' and mess_check <= time ):\n", - " print(\"Right here\")\n", " continue \n", " elif(type_archive == 'not_new' and mess_check > time):\n", " mail_check[pos] = 'update'\n", " \n", " ID = message['data']['Message-ID']\n", " try:\n", - " message['data']['References']\n", - " '''if(message['data']['Message-ID'] == ''):\n", - " print(thread)\n", - " print(store)''' \n", + " message['data']['References'] \n", " if((not thread == None) and (thread['data']['Message-ID'] not in message['data']['References'])):\n", - " #bj = json.dumps(thread, indent=4, sort_keys=True)\n", " di[k] = thread\n", - " #utfile.write(obj)\n", - " #utfile.write('\\n')\n", " store = None\n", " k+=1\n", - " print(\"why\")\n", " \n", " elif( (not store == None) and (store['data']['Message-ID'] not in message['data']['References'])):\n", - " #print(message['data']['References'])\n", " di[k] = store\n", - " #bj = json.dumps(store, indent=4, sort_keys=True)\n", - " #utfile.write(obj)\n", - " #utfile.write('\\n')\n", " store = None\n", - " print(\"yep\")\n", " k+=1\n", " thread = message\n", " except:\n", - " #print(\"got'em\")\n", " if(not thread == None):\n", " di[k] = thread\n", - " #bj = json.dumps(thread, indent=4, sort_keys=True)\n", - " #utfile.write(obj)\n", - " #utfile.write('\\n')\n", " thread = None\n", - " print(\"got-em\")\n", " k+=1\n", " elif(not store == None):\n", " di[k] = store\n", - " #bj = json.dumps(store, indent=4, sort_keys=True)\n", - " #utfile.write(obj)\n", - " #utfile.write('\\n')\n", " store = None\n", - " print(\"getting\") \n", " k+=1\n", " store = message\n", " if(len(di) == 5000):\n", " numb,mail_lists = Piper.make(connect.db,mail_check,archives,mail_lists,res,session,di,numb)\n", " di = {}\n", " k = 0\n", - " #print(\"!\"*50,\"NEW MESSAGE\",\"!\"*50)\n", " if(len(di) < 5000 and len(di) > 0):\n", " print(len(di))\n", - " #print(di)\n", " numb,mail_lists = Piper.make(connect.db,mail_check,archives,mail_lists,res,session,di,numb)\n", " di = {}\n", " k = 0\n", @@ -196,44 +182,130 @@ " good = 1\n", " elif( (thread == None) and (not store == None) ):\n", " di[k] = store\n", - " #obj = json.dumps(store, indent=4, sort_keys=True)\n", - " #outfile.write(obj)\n", - " #outfile.write('\\n')\n", " elif( (store == None) and (not thread == None)):\n", " di[k] = thread\n", - " #obj = json.dumps(thread, indent=4, sort_keys=True)\n", - " #outfile.write(obj)\n", - " #outfile.write('\\n')\n", " elif(store['data']['Message-ID'] in thread['data']['References']):\n", " di[k] = thread\n", - " #obj = json.dumps(thread, indent=4, sort_keys=True)\n", - " #outfile.write(obj)\n", - " #outfile.write('\\n')\n", " else:\n", " di[k] = store\n", - " #obj = json.dumps(store, indent=4, sort_keys=True)\n", - " #outfile.write(obj)\n", - " #outfile.write('\\n') \n", - " #outfile.close()\n", " if(bool(di)):\n", " numb,mail_lists = Piper.make(connect.db,mail_check,archives,mail_lists,res,session,di,numb)\n", " return numb,mail_lists\n", " " ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Iteration through mailing lists:\n", + "\n", + "Determines if the file with the mailing lists was created, if not it writes a set of default mailing lists (to show how the program would work). The mailing lists are then loaded into a dataframe and we iterate through the mailing lists by grouping them by the links. We then check to see if the mailing list is in the 'mailing_list_jobs' table in the SQL Database and if so we assign 'not_new' to 'mail_check' and store the last message date that is stored in 'mailing_list_jobs' to 'time'. If the mailing list is not in 'mailing_list_jobs' we assign 'new' to 'mail_check' and the date is set to 'None' for 'time'." + ] + }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "metadata": { - "collapsed": true + "scrolled": false }, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2018-08-01 16:50:02 keanu-Inspiron-5567 perceval.backends.core.pipermail[18033] INFO Looking for messages from 'https://lists.opendaylight.org/pipermail/aalldp-dev/' since 1970-01-01 00:00:00+00:00\n", + "2018-08-01 16:50:02 keanu-Inspiron-5567 perceval.backends.core.pipermail[18033] INFO Downloading mboxes from 'https://lists.opendaylight.org/pipermail/aalldp-dev/' to since 1970-01-01 00:00:00+00:00\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "runtime/mailing_lists.csv Place\n", + "yeah\n", + "Link,mail_list\n", + "\n", + "https://lists.opendaylight.org/pipermail/,\"aalldp-dev\"\n", + "\n", + "['aalldp-dev', 'archetypes-dev'] mail_list\n", + "{'aalldp-dev': False, 'archetypes-dev': False}\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2018-08-01 16:50:07 keanu-Inspiron-5567 perceval.backends.core.pipermail[18033] INFO 2/2 MBoxes downloaded\n", + "2018-08-01 16:50:07 keanu-Inspiron-5567 perceval.backends.core.mbox[18033] INFO Done. 6/6 messages fetched; 0 ignored\n", + "2018-08-01 16:50:07 keanu-Inspiron-5567 perceval.backends.core.pipermail[18033] INFO Fetch process completed\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "getting\n", + "getting\n", + "yep\n", + "got-em\n", + "4\n", + "['aalldp-dev']\n", + "2018-07-06 18:39:58\n", + "File uploaded 13\n", + "Mailing List Job uploaded\n", + "Finished\n", + "['aalldp-dev']\n", + "File uploaded 4\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2018-08-01 16:50:31 keanu-Inspiron-5567 perceval.backends.core.pipermail[18033] INFO Looking for messages from 'https://lists.opendaylight.org/pipermail/archetypes-dev/' since 1970-01-01 00:00:00+00:00\n", + "2018-08-01 16:50:31 keanu-Inspiron-5567 perceval.backends.core.pipermail[18033] INFO Downloading mboxes from 'https://lists.opendaylight.org/pipermail/archetypes-dev/' to since 1970-01-01 00:00:00+00:00\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Mailing List Job uploaded\n", + "Finished\n", + "Created File aalldp-dev\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2018-08-01 16:50:33 keanu-Inspiron-5567 perceval.backends.core.pipermail[18033] INFO 1/1 MBoxes downloaded\n", + "2018-08-01 16:50:33 keanu-Inspiron-5567 perceval.backends.core.mbox[18033] INFO Done. 2/2 messages fetched; 0 ignored\n", + "2018-08-01 16:50:33 keanu-Inspiron-5567 perceval.backends.core.pipermail[18033] INFO Fetch process completed\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "getting\n", + "1\n", + "['archetypes-dev']\n", + "File uploaded 4\n", + "Mailing List Job uploaded\n", + "Finished\n", + "['archetypes-dev']\n", + "File uploaded 4\n", + "Mailing List Job uploaded\n", + "Finished\n", + "Created File archetypes-dev\n", + "{'aalldp-dev': 'new', 'archetypes-dev': 'new'}\n", + "Finished downloading files\n" + ] + } + ], "source": [ - "# create an Augur application so we can test our function\n", - "if \"notebooks\" in os.getcwd():\n", - " os.chdir(\"..\")\n", - "Piper, path= augurApp.piper()\n", - "print(path,\"Place\")\n", "if(not os.path.exists(path)):\n", " file = open(path, \"w+\")\n", "else:\n", @@ -253,21 +325,15 @@ " if(count == 2):\n", " break\n", "if(count == 2):\n", - " #print(pd.read_csv(path))\n", + " file.close()\n", " df = pd.read_csv(path)\n", " groups = df.groupby('Link').groups\n", " for group in groups:\n", " link = group\n", " mail_list = (df.loc[df['Link'] == group]['mail_list']).tolist()\n", " print(mail_list,\"mail_list\") \n", - " #link = \"https://lists.opendaylight.org/pipermail/\"\n", - " #mail = [\"aalldp-dev\",\"alto-dev\",\"archetypes-dev\"]\n", - " #mail = [\"aalldp-dev\",\"alto-dev\",\"archetypes-dev\",\"dev\"]\n", - " #mail = [\"aalldp-dev\",\"archetypes-dev\",\"alto-dev\"]\n", - " #mail = [\"aalldp-dev\",\"archetypes-dev\"]\n", " mail_check = {key:False for key in mail_list}\n", " print(mail_check)\n", - " #print(os.getcwd())\n", " file = \"mail_list\"\n", " path = \"/augur/data/archive-\" \n", " #numb = 0\n", @@ -275,14 +341,8 @@ " #print(link+mail[x])\n", " if(mail_list[x] not in df1['project'].values ):\n", " mail_check[mail_list[x]] = 'new'\n", - " #print(os.getcwd())\n", - " #print(os.path.join(os.getcwd() + path+'.json'))\n", " place = os.path.join(os.getcwd() + path + mail_list[x] +'.json') \n", " repo = Pipermail(url = link+ mail_list[x] + \"/\",dirpath=\"tmp/archives_\"+mail_list[x])\n", - " #print(\"Broken\")\n", - " #break\n", - " #print(repo)\n", - " outfile = open(place,\"w+\")\n", " numb,mail_lists = write_message(repo,'new',mail_check,mail_list[x],connect.db,res,session,\\\n", " [mail_list[x]],numb,mail_lists)\n", " print(\"Created File\",mail_list[x])\n", @@ -294,7 +354,6 @@ " time = time.astype(object)\n", " place = os.path.join(os.getcwd() + path + 'temp_' + mail_list[x] +'.json') \n", " repo = Pipermail(url = link+ mail_list[x] + \"/\",dirpath=\"tmp/archives_\"+mail_list[x])\n", - " outfile = open(place,\"w+\")\n", " print(time[0])\n", " print(type(time[0]))\n", " numb,mail_lists = write_message(repo,'not_new',mail_check,mail_list[x],connect.db,\\\n", diff --git a/notebooks/Sentiment_Piper.ipynb b/notebooks/Sentiment_Piper.ipynb index a935ba8d48..d625a321a9 100644 --- a/notebooks/Sentiment_Piper.ipynb +++ b/notebooks/Sentiment_Piper.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 10, + "execution_count": 11, "metadata": { "collapsed": true, "scrolled": true @@ -24,16 +24,21 @@ "import matplotlib.pyplot as plot\n", "import matplotlib.dates as mdates\n", "import pandas as pd\n", - "%matplotlib inline\n", - "#nltk.download('punkt')\n", - "#nltk.download('stopwords')\n", - "#pip install twython\n", - "#nltk.download('vader_lexicon')" + "from scipy import stats\n", + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Load:\n", + "First loads the users data from 'augur.config.json' so will take the Database information (e.g. name of database, port of database). Then connects to the database using augur.App.ghtorrentplus(), loads piper_reader and loads the path to the list of mailing lists 'runtine/mailing_lists.csv'" ] }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 2, "metadata": { "collapsed": true }, @@ -46,32 +51,24 @@ ] }, { - "cell_type": "code", - "execution_count": 12, + "cell_type": "markdown", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "['github_issues', 'github_issues_sentiment_scores', 'issue_response_time', 'mail_lists', 'mailing_list_jobs']\n" - ] - } - ], "source": [ - "table_names = s.inspect(connect.db).get_table_names()\n", - "print(table_names)" + "## Connect:\n", + "\n", + "Gets the tables that are in the database and checks so see if 'mailing_list_jobs' is in the Database if it is it stores it in a dataframe 'df1'." ] }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ + "['github_issues', 'github_issues_2', 'github_issues_repo_jobs', 'github_issues_sentiment_scores', 'github_pull_request_repo_jobs', 'github_pull_requests', 'github_pull_requests_2', 'github_pull_requests_sentiment_scores', 'github_pull_requests_sentiment_scores_2', 'issue_response_time', 'mail_lists', 'mail_lists_sentiment_scores', 'mailing_list_jobs']\n", " project\n", "0 aalldp-dev\n", "1 aalldp-dev\n", @@ -81,6 +78,9 @@ } ], "source": [ + "table_names = s.inspect(connect.db).get_table_names()\n", + "print(table_names)\n", + "\n", "if(\"mailing_list_jobs\" in table_names):\n", " lists_createdSQL = s.sql.text(\"\"\"SELECT project FROM mailing_list_jobs\"\"\")\n", " df1 = pd.read_sql(lists_createdSQL, connect.db)\n", @@ -88,9 +88,18 @@ " val = True" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Sentiment Scores:\n", + "\n", + "Loads the SentimentIntensityAnalyzer from NLTK (Natural Language Tool Kit) and pulls all the messages from 'mail_lists' for a specific mailing lists and groups them by 'message_id'. It then goes about getting a score for the message and calculates the average score for when the sentences are broken up into smaller pieces." + ] + }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 4, "metadata": {}, "outputs": [ { @@ -168,454 +177,61 @@ ] }, { - "cell_type": "code", - "execution_count": 15, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " score sentiment\n", - "0 0.271 Positive\n", - "0 0.271 Positive\n", - "0 0.345 Positive\n", - "0 0.345 Positive\n", - "0 0.031 Positive\n", - "0 0.031 Positive\n", - "0 0.140 Positive\n", - "0 0.140 Positive\n", - "0 0.625 Positive\n", - "0 0.625 Positive\n", - "0 0.271 Positive\n", - "0 0.271 Positive\n", - "0 0.345 Positive\n", - "0 0.345 Positive\n", - "0 0.031 Positive\n", - "0 0.031 Positive\n", - "0 0.140 Positive\n", - "0 0.140 Positive\n", - "0 0.625 Positive\n", - "0 0.625 Positive\n", - "0 0.148 Positive\n", - "0 0.148 Positive\n", - "0 0.286 Positive\n", - "0 0.286 Positive\n", - "0 0.148 Positive\n", - "0 0.148 Positive\n", - "0 0.286 Positive\n", - "0 0.286 Positive\n", - " augurmsgID backend_name project \\\n", - "0 1 Pipermail https://lists.opendaylight.org/pipermail/aalld... \n", - "1 2 Pipermail https://lists.opendaylight.org/pipermail/aalld... \n", - "2 3 Pipermail https://lists.opendaylight.org/pipermail/aalld... \n", - "3 4 Pipermail https://lists.opendaylight.org/pipermail/aalld... \n", - "4 5 Pipermail https://lists.opendaylight.org/pipermail/aalld... \n", - "5 6 Pipermail https://lists.opendaylight.org/pipermail/aalld... \n", - "6 7 Pipermail https://lists.opendaylight.org/pipermail/aalld... \n", - "7 8 Pipermail https://lists.opendaylight.org/pipermail/aalld... \n", - "8 9 Pipermail https://lists.opendaylight.org/pipermail/aalld... \n", - "9 10 Pipermail https://lists.opendaylight.org/pipermail/aalld... \n", - "0 1 Pipermail https://lists.opendaylight.org/pipermail/aalld... \n", - "1 2 Pipermail https://lists.opendaylight.org/pipermail/aalld... \n", - "2 3 Pipermail https://lists.opendaylight.org/pipermail/aalld... \n", - "3 4 Pipermail https://lists.opendaylight.org/pipermail/aalld... \n", - "4 5 Pipermail https://lists.opendaylight.org/pipermail/aalld... \n", - "5 6 Pipermail https://lists.opendaylight.org/pipermail/aalld... \n", - "6 7 Pipermail https://lists.opendaylight.org/pipermail/aalld... \n", - "7 8 Pipermail https://lists.opendaylight.org/pipermail/aalld... \n", - "8 9 Pipermail https://lists.opendaylight.org/pipermail/aalld... \n", - "9 10 Pipermail https://lists.opendaylight.org/pipermail/aalld... \n", - "0 11 Pipermail https://lists.opendaylight.org/pipermail/arche... \n", - "1 12 Pipermail https://lists.opendaylight.org/pipermail/arche... \n", - "2 13 Pipermail https://lists.opendaylight.org/pipermail/arche... \n", - "3 14 Pipermail https://lists.opendaylight.org/pipermail/arche... \n", - "0 11 Pipermail https://lists.opendaylight.org/pipermail/arche... \n", - "1 12 Pipermail https://lists.opendaylight.org/pipermail/arche... \n", - "2 13 Pipermail https://lists.opendaylight.org/pipermail/arche... \n", - "3 14 Pipermail https://lists.opendaylight.org/pipermail/arche... \n", - "\n", - " mailing_list category message_part message_parts_tot \\\n", - "0 aalldp-dev message 1 2 \n", - "1 aalldp-dev message 2 2 \n", - "2 aalldp-dev message 1 2 \n", - "3 aalldp-dev message 2 2 \n", - "4 aalldp-dev message 1 2 \n", - "5 aalldp-dev message 2 2 \n", - "6 aalldp-dev message 1 2 \n", - "7 aalldp-dev message 2 2 \n", - "8 aalldp-dev message 1 2 \n", - "9 aalldp-dev message 2 2 \n", - "0 aalldp-dev message 1 2 \n", - "1 aalldp-dev message 2 2 \n", - "2 aalldp-dev message 1 2 \n", - "3 aalldp-dev message 2 2 \n", - "4 aalldp-dev message 1 2 \n", - "5 aalldp-dev message 2 2 \n", - "6 aalldp-dev message 1 2 \n", - "7 aalldp-dev message 2 2 \n", - "8 aalldp-dev message 1 2 \n", - "9 aalldp-dev message 2 2 \n", - "0 archetypes-dev message 1 2 \n", - "1 archetypes-dev message 2 2 \n", - "2 archetypes-dev message 1 2 \n", - "3 archetypes-dev message 2 2 \n", - "0 archetypes-dev message 1 2 \n", - "1 archetypes-dev message 2 2 \n", - "2 archetypes-dev message 1 2 \n", - "3 archetypes-dev message 2 2 \n", - "\n", - " subject date \\\n", - "0 [aalldp-dev] AALLDP Active Committers 2016-03-24 20:37:11 \n", - "1 [aalldp-dev] AALLDP Active Committers 2016-03-24 20:37:11 \n", - "2 [aalldp-dev] Plans for Archiving AALLDP Project 2016-03-24 20:37:08 \n", - "3 [aalldp-dev] Plans for Archiving AALLDP Project 2016-03-24 20:37:08 \n", - "4 [aalldp-dev] change LLDP Multicast Mac 2018-07-05 14:41:28 \n", - "5 [aalldp-dev] change LLDP Multicast Mac 2018-07-05 14:41:28 \n", - "6 [aalldp-dev] [OpenDaylight Discuss] Fwd: Topol... 2018-07-06 18:39:58 \n", - "7 [aalldp-dev] [OpenDaylight Discuss] Fwd: Topol... 2018-07-06 18:39:58 \n", - "8 [aalldp-dev] OpenDaylight AALLDP archive proposal 2018-07-11 10:19:16 \n", - "9 [aalldp-dev] OpenDaylight AALLDP archive proposal 2018-07-11 10:19:16 \n", - "0 [aalldp-dev] AALLDP Active Committers 2016-03-24 20:37:11 \n", - "1 [aalldp-dev] AALLDP Active Committers 2016-03-24 20:37:11 \n", - "2 [aalldp-dev] Plans for Archiving AALLDP Project 2016-03-24 20:37:08 \n", - "3 [aalldp-dev] Plans for Archiving AALLDP Project 2016-03-24 20:37:08 \n", - "4 [aalldp-dev] change LLDP Multicast Mac 2018-07-05 14:41:28 \n", - "5 [aalldp-dev] change LLDP Multicast Mac 2018-07-05 14:41:28 \n", - "6 [aalldp-dev] [OpenDaylight Discuss] Fwd: Topol... 2018-07-06 18:39:58 \n", - "7 [aalldp-dev] [OpenDaylight Discuss] Fwd: Topol... 2018-07-06 18:39:58 \n", - "8 [aalldp-dev] OpenDaylight AALLDP archive proposal 2018-07-11 10:19:16 \n", - "9 [aalldp-dev] OpenDaylight AALLDP archive proposal 2018-07-11 10:19:16 \n", - "0 [archetypes-dev] Mailing archive list test 2018-04-17 21:37:58 \n", - "1 [archetypes-dev] Mailing archive list test 2018-04-17 21:37:58 \n", - "2 [archetypes-dev] archetypes-dev mailing list a... 2018-04-18 09:11:16 \n", - "3 [archetypes-dev] archetypes-dev mailing list a... 2018-04-18 09:11:16 \n", - "0 [archetypes-dev] Mailing archive list test 2018-04-17 21:37:58 \n", - "1 [archetypes-dev] Mailing archive list test 2018-04-17 21:37:58 \n", - "2 [archetypes-dev] archetypes-dev mailing list a... 2018-04-18 09:11:16 \n", - "3 [archetypes-dev] archetypes-dev mailing list a... 2018-04-18 09:11:16 \n", - "\n", - " message_from \\\n", - "0 An.Ho at huawei.com (An Ho) \n", - "1 An.Ho at huawei.com (An Ho) \n", - "2 An.Ho at huawei.com (An Ho) \n", - "3 An.Ho at huawei.com (An Ho) \n", - "4 corajososprojetosdn at gmail.com (Projeto sdn) \n", - "5 corajososprojetosdn at gmail.com (Projeto sdn) \n", - "6 tompantelis at gmail.com (Tom Pantelis) \n", - "7 tompantelis at gmail.com (Tom Pantelis) \n", - "8 skitt at redhat.com (Stephen Kitt) \n", - "9 skitt at redhat.com (Stephen Kitt) \n", - "0 An.Ho at huawei.com (An Ho) \n", - "1 An.Ho at huawei.com (An Ho) \n", - "2 An.Ho at huawei.com (An Ho) \n", - "3 An.Ho at huawei.com (An Ho) \n", - "4 corajososprojetosdn at gmail.com (Projeto sdn) \n", - "5 corajososprojetosdn at gmail.com (Projeto sdn) \n", - "6 tompantelis at gmail.com (Tom Pantelis) \n", - "7 tompantelis at gmail.com (Tom Pantelis) \n", - "8 skitt at redhat.com (Stephen Kitt) \n", - "9 skitt at redhat.com (Stephen Kitt) \n", - "0 agrimberg at linuxfoundation.org (Andrew Grimb... \n", - "1 agrimberg at linuxfoundation.org (Andrew Grimb... \n", - "2 vorburger at redhat.com (Michael Vorburger) \n", - "3 vorburger at redhat.com (Michael Vorburger) \n", - "0 agrimberg at linuxfoundation.org (Andrew Grimb... \n", - "1 agrimberg at linuxfoundation.org (Andrew Grimb... \n", - "2 vorburger at redhat.com (Michael Vorburger) \n", - "3 vorburger at redhat.com (Michael Vorburger) \n", - "\n", - " message_id \\\n", - "0 \n", - "9 <20180711121916.55d667c9@skrht450s.lan> \n", - "0 \n", - "9 <20180711121916.55d667c9@skrht450s.lan> \n", - "0 <34dc81cb-f265-875a-ba4c-eac4fc664c6c@linuxfou... \n", - "1 <34dc81cb-f265-875a-ba4c-eac4fc664c6c@linuxfou... \n", - "2 , ... \n", - "1 this email to indicate that you are still an a... \n", - "2 Hi AALLDP Team,\\n\\n\\n\\n1. Does your project ha... \n", - "3 for any future active development, project co... \n", - "4 Hi guys,\\n\\nI'm new to the opendaylight univer... \n", - "5 in the topology, I wonder if there is any way ... \n", - "6 On Fri, Jul 6, 2018 at 10:48 AM, Projeto sdn <... \n", - "7 uys,\\n>\\n> I need to manage non-Openflow SNMP ... \n", - "8 Dear AALLDP developers,\\n\\nThe OpenDaylight TS... \n", - "9 the AALLDP project [1], as per section 2.3.5 ... \n", - "0 Hi Brian Kaczynski , ... \n", - "1 this email to indicate that you are still an a... \n", - "2 Hi AALLDP Team,\\n\\n\\n\\n1. Does your project ha... \n", - "3 for any future active development, project co... \n", - "4 Hi guys,\\n\\nI'm new to the opendaylight univer... \n", - "5 in the topology, I wonder if there is any way ... \n", - "6 On Fri, Jul 6, 2018 at 10:48 AM, Projeto sdn <... \n", - "7 uys,\\n>\\n> I need to manage non-Openflow SNMP ... \n", - "8 Dear AALLDP developers,\\n\\nThe OpenDaylight TS... \n", - "9 the AALLDP project [1], as per section 2.3.5 ... \n", - "0 This is just a test.\\n\\n-- \\nAndrew J Grimberg... \n", - "1 --------- next part --------------\\nA non-text... \n", - "2 Hello archetypians,\\n\\nJust to let you all kno... \n", - "3 es-dev/ works now (thanks\\nAndy!).\\n\\nJust in ... \n", - "0 This is just a test.\\n\\n-- \\nAndrew J Grimberg... \n", - "1 --------- next part --------------\\nA non-text... \n", - "2 Hello archetypians,\\n\\nJust to let you all kno... \n", - "3 es-dev/ works now (thanks\\nAndy!).\\n\\nJust in ... \n" - ] - } - ], + "cell_type": "markdown", + "metadata": {}, "source": [ - "print(df3)\n", - "print(df_list)\n", - "df3 = df3.reset_index(drop=True)\n", - "df_list = df_list.reset_index(drop=True)\n", - "combine = (df_list.join(df3))" + "## Combine\n", + "\n", + "Combines the dataframe with all the messages and joins that with the scores for the messages. Then uploads this to the database as 'mail_lists_sentiment_scores'." ] }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 5, "metadata": { - "scrolled": false + "collapsed": true, + "scrolled": true }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " augurmsgID backend_name project \\\n", - "0 1 Pipermail https://lists.opendaylight.org/pipermail/aalld... \n", - "1 2 Pipermail https://lists.opendaylight.org/pipermail/aalld... \n", - "2 3 Pipermail https://lists.opendaylight.org/pipermail/aalld... \n", - "3 4 Pipermail https://lists.opendaylight.org/pipermail/aalld... \n", - "4 5 Pipermail https://lists.opendaylight.org/pipermail/aalld... \n", - "5 6 Pipermail https://lists.opendaylight.org/pipermail/aalld... \n", - "6 7 Pipermail https://lists.opendaylight.org/pipermail/aalld... \n", - "7 8 Pipermail https://lists.opendaylight.org/pipermail/aalld... \n", - "8 9 Pipermail https://lists.opendaylight.org/pipermail/aalld... \n", - "9 10 Pipermail https://lists.opendaylight.org/pipermail/aalld... \n", - "10 1 Pipermail https://lists.opendaylight.org/pipermail/aalld... \n", - "11 2 Pipermail https://lists.opendaylight.org/pipermail/aalld... \n", - "12 3 Pipermail https://lists.opendaylight.org/pipermail/aalld... \n", - "13 4 Pipermail https://lists.opendaylight.org/pipermail/aalld... \n", - "14 5 Pipermail https://lists.opendaylight.org/pipermail/aalld... \n", - "15 6 Pipermail https://lists.opendaylight.org/pipermail/aalld... \n", - "16 7 Pipermail https://lists.opendaylight.org/pipermail/aalld... \n", - "17 8 Pipermail https://lists.opendaylight.org/pipermail/aalld... \n", - "18 9 Pipermail https://lists.opendaylight.org/pipermail/aalld... \n", - "19 10 Pipermail https://lists.opendaylight.org/pipermail/aalld... \n", - "20 11 Pipermail https://lists.opendaylight.org/pipermail/arche... \n", - "21 12 Pipermail https://lists.opendaylight.org/pipermail/arche... \n", - "22 13 Pipermail https://lists.opendaylight.org/pipermail/arche... \n", - "23 14 Pipermail https://lists.opendaylight.org/pipermail/arche... \n", - "24 11 Pipermail https://lists.opendaylight.org/pipermail/arche... \n", - "25 12 Pipermail https://lists.opendaylight.org/pipermail/arche... \n", - "26 13 Pipermail https://lists.opendaylight.org/pipermail/arche... \n", - "27 14 Pipermail https://lists.opendaylight.org/pipermail/arche... \n", - "\n", - " mailing_list category message_part message_parts_tot \\\n", - "0 aalldp-dev message 1 2 \n", - "1 aalldp-dev message 2 2 \n", - "2 aalldp-dev message 1 2 \n", - "3 aalldp-dev message 2 2 \n", - "4 aalldp-dev message 1 2 \n", - "5 aalldp-dev message 2 2 \n", - "6 aalldp-dev message 1 2 \n", - "7 aalldp-dev message 2 2 \n", - "8 aalldp-dev message 1 2 \n", - "9 aalldp-dev message 2 2 \n", - "10 aalldp-dev message 1 2 \n", - "11 aalldp-dev message 2 2 \n", - "12 aalldp-dev message 1 2 \n", - "13 aalldp-dev message 2 2 \n", - "14 aalldp-dev message 1 2 \n", - "15 aalldp-dev message 2 2 \n", - "16 aalldp-dev message 1 2 \n", - "17 aalldp-dev message 2 2 \n", - "18 aalldp-dev message 1 2 \n", - "19 aalldp-dev message 2 2 \n", - "20 archetypes-dev message 1 2 \n", - "21 archetypes-dev message 2 2 \n", - "22 archetypes-dev message 1 2 \n", - "23 archetypes-dev message 2 2 \n", - "24 archetypes-dev message 1 2 \n", - "25 archetypes-dev message 2 2 \n", - "26 archetypes-dev message 1 2 \n", - "27 archetypes-dev message 2 2 \n", - "\n", - " subject date \\\n", - "0 [aalldp-dev] AALLDP Active Committers 2016-03-24 20:37:11 \n", - "1 [aalldp-dev] AALLDP Active Committers 2016-03-24 20:37:11 \n", - "2 [aalldp-dev] Plans for Archiving AALLDP Project 2016-03-24 20:37:08 \n", - "3 [aalldp-dev] Plans for Archiving AALLDP Project 2016-03-24 20:37:08 \n", - "4 [aalldp-dev] change LLDP Multicast Mac 2018-07-05 14:41:28 \n", - "5 [aalldp-dev] change LLDP Multicast Mac 2018-07-05 14:41:28 \n", - "6 [aalldp-dev] [OpenDaylight Discuss] Fwd: Topol... 2018-07-06 18:39:58 \n", - "7 [aalldp-dev] [OpenDaylight Discuss] Fwd: Topol... 2018-07-06 18:39:58 \n", - "8 [aalldp-dev] OpenDaylight AALLDP archive proposal 2018-07-11 10:19:16 \n", - "9 [aalldp-dev] OpenDaylight AALLDP archive proposal 2018-07-11 10:19:16 \n", - "10 [aalldp-dev] AALLDP Active Committers 2016-03-24 20:37:11 \n", - "11 [aalldp-dev] AALLDP Active Committers 2016-03-24 20:37:11 \n", - "12 [aalldp-dev] Plans for Archiving AALLDP Project 2016-03-24 20:37:08 \n", - "13 [aalldp-dev] Plans for Archiving AALLDP Project 2016-03-24 20:37:08 \n", - "14 [aalldp-dev] change LLDP Multicast Mac 2018-07-05 14:41:28 \n", - "15 [aalldp-dev] change LLDP Multicast Mac 2018-07-05 14:41:28 \n", - "16 [aalldp-dev] [OpenDaylight Discuss] Fwd: Topol... 2018-07-06 18:39:58 \n", - "17 [aalldp-dev] [OpenDaylight Discuss] Fwd: Topol... 2018-07-06 18:39:58 \n", - "18 [aalldp-dev] OpenDaylight AALLDP archive proposal 2018-07-11 10:19:16 \n", - "19 [aalldp-dev] OpenDaylight AALLDP archive proposal 2018-07-11 10:19:16 \n", - "20 [archetypes-dev] Mailing archive list test 2018-04-17 21:37:58 \n", - "21 [archetypes-dev] Mailing archive list test 2018-04-17 21:37:58 \n", - "22 [archetypes-dev] archetypes-dev mailing list a... 2018-04-18 09:11:16 \n", - "23 [archetypes-dev] archetypes-dev mailing list a... 2018-04-18 09:11:16 \n", - "24 [archetypes-dev] Mailing archive list test 2018-04-17 21:37:58 \n", - "25 [archetypes-dev] Mailing archive list test 2018-04-17 21:37:58 \n", - "26 [archetypes-dev] archetypes-dev mailing list a... 2018-04-18 09:11:16 \n", - "27 [archetypes-dev] archetypes-dev mailing list a... 2018-04-18 09:11:16 \n", - "\n", - " message_from \\\n", - "0 An.Ho at huawei.com (An Ho) \n", - "1 An.Ho at huawei.com (An Ho) \n", - "2 An.Ho at huawei.com (An Ho) \n", - "3 An.Ho at huawei.com (An Ho) \n", - "4 corajososprojetosdn at gmail.com (Projeto sdn) \n", - "5 corajososprojetosdn at gmail.com (Projeto sdn) \n", - "6 tompantelis at gmail.com (Tom Pantelis) \n", - "7 tompantelis at gmail.com (Tom Pantelis) \n", - "8 skitt at redhat.com (Stephen Kitt) \n", - "9 skitt at redhat.com (Stephen Kitt) \n", - "10 An.Ho at huawei.com (An Ho) \n", - "11 An.Ho at huawei.com (An Ho) \n", - "12 An.Ho at huawei.com (An Ho) \n", - "13 An.Ho at huawei.com (An Ho) \n", - "14 corajososprojetosdn at gmail.com (Projeto sdn) \n", - "15 corajososprojetosdn at gmail.com (Projeto sdn) \n", - "16 tompantelis at gmail.com (Tom Pantelis) \n", - "17 tompantelis at gmail.com (Tom Pantelis) \n", - "18 skitt at redhat.com (Stephen Kitt) \n", - "19 skitt at redhat.com (Stephen Kitt) \n", - "20 agrimberg at linuxfoundation.org (Andrew Grimb... \n", - "21 agrimberg at linuxfoundation.org (Andrew Grimb... \n", - "22 vorburger at redhat.com (Michael Vorburger) \n", - "23 vorburger at redhat.com (Michael Vorburger) \n", - "24 agrimberg at linuxfoundation.org (Andrew Grimb... \n", - "25 agrimberg at linuxfoundation.org (Andrew Grimb... \n", - "26 vorburger at redhat.com (Michael Vorburger) \n", - "27 vorburger at redhat.com (Michael Vorburger) \n", - "\n", - " message_id \\\n", - "0 \n", - "9 <20180711121916.55d667c9@skrht450s.lan> \n", - "10 \n", - "19 <20180711121916.55d667c9@skrht450s.lan> \n", - "20 <34dc81cb-f265-875a-ba4c-eac4fc664c6c@linuxfou... \n", - "21 <34dc81cb-f265-875a-ba4c-eac4fc664c6c@linuxfou... \n", - "22 , ... 0.271 Positive \n", - "1 this email to indicate that you are still an a... 0.271 Positive \n", - "2 Hi AALLDP Team,\\n\\n\\n\\n1. Does your project ha... 0.345 Positive \n", - "3 for any future active development, project co... 0.345 Positive \n", - "4 Hi guys,\\n\\nI'm new to the opendaylight univer... 0.031 Positive \n", - "5 in the topology, I wonder if there is any way ... 0.031 Positive \n", - "6 On Fri, Jul 6, 2018 at 10:48 AM, Projeto sdn <... 0.140 Positive \n", - "7 uys,\\n>\\n> I need to manage non-Openflow SNMP ... 0.140 Positive \n", - "8 Dear AALLDP developers,\\n\\nThe OpenDaylight TS... 0.625 Positive \n", - "9 the AALLDP project [1], as per section 2.3.5 ... 0.625 Positive \n", - "10 Hi Brian Kaczynski , ... 0.271 Positive \n", - "11 this email to indicate that you are still an a... 0.271 Positive \n", - "12 Hi AALLDP Team,\\n\\n\\n\\n1. Does your project ha... 0.345 Positive \n", - "13 for any future active development, project co... 0.345 Positive \n", - "14 Hi guys,\\n\\nI'm new to the opendaylight univer... 0.031 Positive \n", - "15 in the topology, I wonder if there is any way ... 0.031 Positive \n", - "16 On Fri, Jul 6, 2018 at 10:48 AM, Projeto sdn <... 0.140 Positive \n", - "17 uys,\\n>\\n> I need to manage non-Openflow SNMP ... 0.140 Positive \n", - "18 Dear AALLDP developers,\\n\\nThe OpenDaylight TS... 0.625 Positive \n", - "19 the AALLDP project [1], as per section 2.3.5 ... 0.625 Positive \n", - "20 This is just a test.\\n\\n-- \\nAndrew J Grimberg... 0.148 Positive \n", - "21 --------- next part --------------\\nA non-text... 0.148 Positive \n", - "22 Hello archetypians,\\n\\nJust to let you all kno... 0.286 Positive \n", - "23 es-dev/ works now (thanks\\nAndy!).\\n\\nJust in ... 0.286 Positive \n", - "24 This is just a test.\\n\\n-- \\nAndrew J Grimberg... 0.148 Positive \n", - "25 --------- next part --------------\\nA non-text... 0.148 Positive \n", - "26 Hello archetypians,\\n\\nJust to let you all kno... 0.286 Positive \n", - "27 es-dev/ works now (thanks\\nAndy!).\\n\\nJust in ... 0.286 Positive \n", - "['augurmsgID', 'backend_name', 'project', 'mailing_list', 'category', 'message_part', 'message_parts_tot', 'subject', 'date', 'message_from', 'message_id', 'message_text', 'score', 'sentiment']\n" - ] - } - ], + "outputs": [], "source": [ - "print(combine)\n", - "print(list(combine))" + "#print(df3)\n", + "#print(df_list)\n", + "df3 = df3.reset_index(drop=True)\n", + "df_list = df_list.reset_index(drop=True)\n", + "combine = (df_list.join(df3))\n", + "\n", + "print(combine.head())\n", + "#print(list(combine))\n", + "\n", + "combine.to_sql(name='mail_lists_sentiment_scores',con=connect.db,\\\n", + " if_exists='replace',index=False)" ] }, { - "cell_type": "code", - "execution_count": 17, - "metadata": { - "collapsed": true - }, - "outputs": [], + "cell_type": "markdown", + "metadata": {}, "source": [ - "combine.to_sql(name='mail_lists_sentiment_scores',con=connect.db,\\\n", - " if_exists='replace',index=False)" + "## Graphs\n", + "\n", + "Takes all the mailing lists in combine and groups by the column 'mailing_list' and gets the dates and sentiment scores and plots a graph based on this." ] }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 12, "metadata": {}, "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(5,)\n", + "(5,)\n" + ] + }, { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "
" ] @@ -623,9 +239,17 @@ "metadata": {}, "output_type": "display_data" }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(2,)\n", + "(2,)\n" + ] + }, { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "
" ] @@ -647,299 +271,23 @@ " dates = np.unique(x)\n", " #print(dates)\n", " dates1 = [x.to_pydatetime() for x in dates]\n", - " dates2 = mdates.date2num(dates1)\n", - " plot.plot_date(dates2, values)\n", - " plot.plot(dates2,values)\n", - " # beautify the x-labels\n", + " fin_dates = mdates.date2num(dates1)\n", + " fin_values = np.asarray(values)\n", + " print(fin_dates.shape)\n", + " print(fin_values.shape)\n", + " plot.plot_date(fin_dates, fin_values)\n", + " #plot.plot(fin_dates,fin_values)\n", " plot.gcf().autofmt_xdate()\n", - " plot.title(\"Mailing list: \" + group)\n", + " plot.title(\"Mailing lst: \"+ group)\n", " plot.ylabel('Score')\n", " plot.xlabel('Date')\n", - " #plot.savefig('mailing_list' + str(j) + '.png')\n", - " plot.show()\n", - " j+=1" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "message_text = \"\"\"Sarah Sharp recently posted a tirade about verbal abuse on here and \n", - "her blog - where she dismisses all comments disagreeing with her as \n", - "being from trolls, and deletes them - and takes pride in being \n", - "\"accidentally racist\", when she's not attention-whoring on the LKML. \n", - "\n", - "I want to say, as a female developer: Sarah Sharp is not \n", - "representative of us. She's not representative of the women at Intel. \n", - "She's not representative of women in technology. \n", - "\n", - "She's a bully. She bullies her husband. She dismisses bullying of her \n", - "coworkers. (Google: 'intel kick me'). And she's trying to bully Linus. \n", - "\n", - "I know he's a big boy. But dare I say, Linus is too nice to tell this \n", - "drama queen to bugger off. \n", - "\n", - "No one was talking to her. Linus' 'Shut the fuck up' was to a \n", - "developer who refused to take responsibility for his code, and blamed \n", - "someone else's code. It was deserved criticism. Then, Linus went and \n", - "explained just that: \n", - "\n", - "\"Similarly, you will see fireworks if some long-term maintainer makes \n", - "excuses for breaking user space etc. That will make me go into \n", - "incoherent rages.\" \n", - "\n", - "Which is exactly what the emails held up as \"verbal abuse\" show. \n", - "\n", - "Sarah's exclaiming how she won't take any of this abuse, yet no one \n", - "was directing any of it at her. It's sickening she's got nothing \n", - "better to do then stick her nose in and decide to dictate to her \n", - "betters how to behave. Yes I said her betters: We all run Linux. Not \n", - "Sarax. \n", - "\n", - "Sarah justifies pissing in the Linux sandbox because Intel 'pays her' \n", - "to develop kernel drivers. Perhaps her direct manager might rethink \n", - "this decision in light of how she's representing Intel in her \"off\" \n", - "time. \n", - "\n", - "To Linus: You're a hero to many of us. Don't change. Please. You DO \n", - "NOT need to take time away from doing code to grow a pair of breasts \n", - "and judge people's emotional states: \n", - "\n", - "\"It does not matter if your cursing fits have causes. The fact is that \n", - "if you misjudge someone's emotional state for the day, you yelling at \n", - "them is not productive.\" \n", - "\n", - "As a woman, I couldn't be silent and stand by while Sarah bullied and \n", - "assaulted this list with her profanity and self-indulgent narcissism. \n", - "She's the problem. Not you. Not your style of communication. We \n", - "technical women appreciate being treated equally by our male peers, \n", - "with blunt directness and unambiguous criticism. We are not fragile flowers. \n", - "\n", - "We can do our jobs without demanding others interact with us on our \n", - "terms and tiptoe around our fragile egos while being considerate of \n", - "our ever changing emotional needs. \n", - "\n", - "I promise you, it's true. We're not all Sarah Sharps. \n", - "\n", - "I see a lot of the devs including Linus handling her with kid gloves \n", - "to be diplomatic. Don't. If you want to be really nice, maybe drop an \n", - "email to her direct manager extending an apology for how hurtful it \n", - "was to her, having to observe others having a conversation in which \n", - "she wasn't involved. Managers like hearing about that. \n", - "\n", - "We love you Linus, just the grumptastic way you are. Don't change how \n", - "you interact, especially because of Sarah Sharp and her ilk. Please and \n", - "thanks.. \n", - "-- \n", - "To unsubscribe from this list: send the line \"unsubscribe linux-kernel\" in \n", - "the body of a message to majordomo@vger.kernel.org \n", - "More majordomo info at http://vger.kernel.org/majordomo-info.html \n", - "Please read the FAQ at http://www.tux.org/lkml/\n", - "\"\"\"" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "message_text = \"\"\"_Dear reader from `${externalSource}`: I neither like nor support personal abuse or attacks. If you are showing up here getting angry at any party involved, I would ask you to refrain from targeting them, privately or in public. Specifically to people who think they may be supporting me by engaging in abusive behaviour: I do not appreciate, want or need it, in any form and it is not helpful in any way._\n", - "\n", - "Yep, this is a long post, but no apologies for the length this time. Buckle up.\n", - "\n", - "I'm sad that we have reached this point, and that the CTC is being asked to make such a difficult decision. One of the reasons that we initially split the TSC into two groups was to insulate the technical _doers_ on the CTC from the overhead of administrative and political tedium. I know many of you never imagined you'd have to deal with something like this when you agreed to join and that this is a very uncomfortable experience for you.\n", - "\n", - "It's obvious that we never figured out a suitable structure that made the TSC a useful, functional, and healthy body that might be able to deal more effectively with these kinds of problems, more isolated from the CTC. I'm willing to accept a sizeable share of the blame for not improving our organisational structure during my tenure in leadership.\n", - "\n", - "## My response\n", - "\n", - "Regarding the request for me to resign from the CTC: in lieu of clear justification that my removal is for the benefit of the Node.js project, or a case for my removal that is not built primarily on hearsay and innuendo, I respectfully decline.\n", - "\n", - "There are two primary reasons for which I am standing my ground.\n", - "\n", - "I cannot, in good conscience, give credence to the straw-man version of me being touted loudly on social media and on GitHub. This caricature of me and vague notions regarding my \"toxicity\", my propensity for \"harassment\", the \"systematic\" breaking of rules and other slanderous claims against my character has no basis in fact. I will not dignify these attacks by taking tacit responsibility through voluntary resignation.\n", - "\n", - "Secondly, and arguably more importantly for the CTC: I absolutely will not take responsibility for the precedent that is currently being set. The dogged pursuit of a leader of this project, the strong-arm tactics being deployed with the goal of having me voluntarily resign, or my eventual removal from this organisation are not the behavior of a healthy, productive, or inclusive community. \n", - "\n", - "My primary concern is that the consequences of these actions endanger the future health of the Node.js project. I do not believe that I am an irreplaceable snowflake (I’m entirely replaceable). There is reason to pause before making this an acceptable part of how we conduct our governance and our internal relationships.\n", - "\n", - "However, while I am not happy to have the burden of this decision being foisted upon all of you, I am content with standing to be judged by this group. As the creative force behind Node.js and the legitimate owners of this project, my respect for you as individuals and as a group and your rightful position as final arbiters of the technical Node.js project makes entirely comfortable living with whatever decision you arrive at regarding my removal.\n", - "\n", - "I will break the rest of this post into the following sections: \n", - " * My critique of the process so far\n", - " * My response to list of complaints made against me [to the TSC](https://github.com/nodejs/TSC/issues/310)\n", - " * Addressing the claims often repeated across the internet regarding me as a hinderance to progress on inclusivity and diversity\n", - " * The independence of the technical group, the new threats posed to that independence\n", - " * The threats posed to future leadership of the project\n", - "\n", - "### The process so far\n", - "\n", - "My personal experience so far has been approximately as follows:\n", - "\n", - "* Some time ago I received notification via email that there are complaints against me. No details were provided and I was informed that I would neither receive those details or be involved in the whatever process was to take place. Further, TSC members were not allowed to speak to me directly about these matters, _including_ my work colleagues also on the TSC. I was never provided with an opportunity to understand the specific charges against me or be involved in any discussions on this topic from that point onward.\n", - "* 3 days ago, I saw [nodejs/TSC#310](https://github.com/nodejs/TSC/issues/310) at the same time as the public. **This was the first time that I had seen the list of complaints**. It was the first that I heard that there was a vote taking place regarding my position.\n", - "* At no point have I been provided with an opportunity to answer to these complaints, correct the factual errors contained in them (see below), apologise and make amends where possible, or provide additional context that may further explain accusations against me.\n", - "* At no point have I been approached by a member of the TSC or CTC regarding any of these items other than what the record that we have here on GitHub shows—primarily in the threads involved and in the moderation repository, the record is open for you to view regarding the due diligence undertaken either by my accusers or those executing the process. I have had interactions with only a single member of the TSC regarding one of these matters in private email and in person which has, on both occasions, involved me attempting to coax out the source of bad feelings that I had sensed and attempting to (relatively blindly) make amends.\n", - "\n", - "I hope you can empathise that to me this process is rather unfair and regardless of whether this process is informed or dictated by our governance documents as has been claimed, it should be changed so that in the future accused parties have the chance to at least respond to accusations.\n", - "\n", - "### Response to the list of complaints\n", - "\n", - "I am including the text that was redacted from [nodejs/TSC#310](https://github.com/nodejs/TSC/issues/310) as it is already in the public domain, on social media, also on GitHub and now in the press. Please note that I did not ask for this text to be redacted.\n", - "\n", - "#### 1.\n", - "\n", - "> In [link to moderation repository discussion, not copied here out of respect for additional parties involved], Rod’s first action was to apologize to a contributor who had been repeatedly moderated. Rod did not discuss the issue with other members of the CTC/TSC first. The result undermined the moderation process as it was occurring. It also undercut the authority as moderators of other CTC/TSC members.\n", - "\n", - "Rather than delving into the details of this complaint, I will simply say that I was unaware at the time that the actions I had taken were inappropriate and had caused hurt to some CTC/TSC members involved in this matter. Having had this belatedly explained to me (again, something I have had to coax out, not offered freely to me), I issued a private statement to the TSC and CTC via email at the beginning of this month offering my sincere apologies. (I did this without knowing whether it was part of the list of complaints against me.) The most relevant part of my private statement is this:\n", - "\n", - "> In relation to my behaviour in the specific: I should not have weighed in so heavily, or at all, in this instance as I lacked so much of the context of what was obviously a very sensitive matter that was being already dealt with by some of you (in a very taxing way, as I understand it). I missed those signals entirely and weighed in without tact, took sides against some of you—apologising to [unnecessary details withheld] on behalf of some of you was an absurd thing for me to do without having being properly involved prior to this. And for this I unreservedly apologise!\n", - "\n", - "I don't know if this apology was acknowledged during the process of dealing with the complaints against me. This apology has neither been acknowledged in the publication of the complaints handling process, nor has it seemed to have any impact on the parties involved who continue to hold it against me. I can only assume that they either dismiss my sincerity or that apologies are not a sufficient means of rectifying these kinds of missteps.\n", - "\n", - "In this matter I accept responsibility and have already attempted to make amends and prevent a similar issue from recurring. It disappoints me that it is still used as an active smear against me. Again, had I been given clear feedback regarding my misstep earlier, I would have attempted to resolve this situation sooner. \n", - "\n", - "#### 2.\n", - "\n", - "> In nodejs/board#58 and nodejs/moderation#82 Rod did not moderate himself when asked by another foundation director and told them he would take it to the board. He also ignored the explicit requests to not name member companies and later did not moderate the names out of his comments when requested. Another TSC member needed to follow up later to actually clean up the comments. Additionally he discussed private information from the moderation repo in the public thread, which is explicitly against the moderation policy.\n", - "\n", - "My response to this complaint is as follows:\n", - "\n", - "1. This thread unfortunately involves a significant amount of background corporate politics, personal relationship difficulties and other matters which conspired to raise the temperature, for me at least. This is not an excuse, simply an explanation for what may have appeared to some to be a heated interjection on my part.\n", - "2. I _did_ edit my post very soon after—I was the first to edit my posts in there after the quick discussion that followed in the moderation repository and I realised I had made a poor judgement call with my choice of words. I both removed my reading of intent into the words of another poster and removed the disclosure of matters discussed in a private forum.\n", - "3. I do not recall being asked to _remove_ the names of the companies involved, I have only now seen that they have been edited out of my post. I cannot find any evidence that such a request was even made. This would have been a trivial matter on my part and I would have done it without argument if I had have seen such a request. To find this forming the basis of a complaint is rather troubling without additional evidence.\n", - "4. A board member asking another board member (me) to edit their postings seemed to me to be a board matter, hence my suggestion to take it to the board. I was subsequently corrected on this—as it is a TSC-owned repository it was therefore referred to the TSC for adjudication.\n", - "\n", - "I considered the remaining specifics of this issue to have been resolved and have not been informed otherwise since this event took place. Yet I now find that the matters are still active and I am the target of criticism rather than that criticism being aimed at the processes that apparently resolved the matter in the first place. Why was I never informed that my part in the resolution was unsatisfactory and why was I not provided a chance to rectify additional perceived misdeeds?\n", - "\n", - "### 3.\n", - "\n", - "> Most recently Rod tweeted in support of an inflammatory anti-Code-of-Conduct article. As a perceived leader in the project, it can be difficult for outsiders to separate Rod’s opinions from that of the project. Knowing the space he is participating in and the values of our community, Rod should have predicted the kind of response this tweet received. https://twitter.com/rvagg/status/887652116524707841\n", - "\n", - "> His tweeting of screen captures of immature responses suggests pleasure at having upset members of the JavaScript community and others. As a perceived leader, such behavior reflects poorly on the project. https://twitter.com/rvagg/status/887790865766268928\n", - "\n", - "> Rod’s public comments on these sorts of issues is a reason for some to avoid project participation. https://twitter.com/captainsafia/status/887782785221615618\n", - "\n", - "> It is evidence to others that Node.js may not be serious about its commitment to community and inclusivity. https://twitter.com/nodebotanist/status/887724138516951049\n", - "\n", - "\n", - "1. The post I linked to was absolutely **not** an anti-Code-of-Conduct article. It was an article written by an Associate Professor of Evolutionary Psychology at the University of New Mexico, discussing free speech in general and suggesting a case against speech codes _in American university campuses_. In sharing this, I hoped to encourage meaningful discussion regarding the possible shortcomings of some standard Code of Conduct language. My intent was not to suggest that the Node.js project should not have a Code of Conduct in place.\n", - "2. \"Rod should have predicted the kind of response this tweet received\" is a deeply normative statement. I did not predict the storm generated, and assumed that open discussion on matters of speech policing was still possible, and that my personal views would not be misconstrued as the views of the broader Node.js leadership group or community. I obviously chose the wrong forum. If TSC/CTC members are going to be held responsible for attempting to share or discuss personal views on personal channels, then that level of accountability should be applied equally across technical and Foundation leadership.\n", - "3. \"His tweeting of screen captures of immature responses suggests pleasure\" is an assumption of my feelings at the time. I find this ironic especially in the context of complaint number 2 (above); I was criticised for reading the intention of another individual into their words yet that’s precisely what is being done here. This claim is absolutely untrue, I do not take pleasure in upsetting people. I will refrain from justifying my actions further on this matter but this accusation is baseless and disingenuous.\n", - "4. To re-state for further clarity, I **have not made a case against Codes of Conduct in general**, but rather, would like to see ongoing discussion about how such social guidelines could be improved upon, as they clearly have impact on open source project health.\n", - "5. I have never made a case against the Node.js Code of Conduct.\n", - "6. I have a clear voting record for adopting the Node.js project's Code of Conduct and for various changes made to it. Codes of Conduct have been adopted by a number of my own projects which have been moved from my own GitHub account to that of the Node.js Foundation.\n", - "\n", - "I will refrain from further justifying a tweet. As with all of you, I bring my own set of opinions and values to our diverse mix and we work to find an acceptable common space for us all to operate within. I don’t ask that you agree with me, but within reason I hope that mutual respect is stronger than a single disagreement. I cannot accept that my opinions on these matters form a valid reason for my removal. I have submitted myself to our Code of Conduct as a participant in this project. I have been involved in the application of our Code of Conduct. But I do not accept it as a sacred text that is above critique or even _discussion_.\n", - "\n", - "\n", - "While not a matter for the TSC or CTC, a Board member on the Foundation who (by their own admission), has repeatedly discussed sensitive and private Board matters publicly on Twitter, causing ongoing consternation and legal concern for the Board. As far as I know, this individual has not been asked to resign. I consider this type of behaviour to be considerably more problematic for the Foundation than my tweeting of a link to an article completely unrelated to Node.js.\n", - "\n", - "Taking action against me on the basis of this tweet, while ignoring the many tweets and other social media posts that stand in direct conflict to the goals of the Foundation by other members of our technical team, its leadership and other members of the Foundation and its various bodies, strikes me as a deeply unequal (and, it must be said, un-inclusive) application of the rules. \n", - "\n", - "If it is the case that the TSC/CTC is setting limits on personal discussion held outside the context of the project repo, then these limits should be applied to all members of both groups without prejudice.\n", - "\n", - "#### Board accusations\n", - "\n", - "In addition to the above list, we now have [new claims](https://github.com/nodejs/board/issues/67) from the Node.js Foundation board. It appears to suggest that I have and/or do engage in _“antagonistic, aggressive or derogatory behavior”_, with no supporting evidence provided. Presumably the supporting evidence is the list in [nodejs/TSC#310](https://github.com/nodejs/TSC/issues/310) to which I have responded with above.\n", - "\n", - "I can’t respond to an unsupported claim such as this, it’s presented entirely without merit and I cannot consider it anything other than malicious, self-serving, and an obvious attempt to emotionally manipulate the TSC and CTC by charging the existing claims with a completely new level of seriousness by the sprinkling of an assortment of stigmatic _evil person_ descriptors.\n", - "\n", - "To say that I am disappointed that a majority of the Board would agree to conduct themselves in such an unprofessional and immature manner is an understatement. However this is neither the time nor place for me to attempt to address their attempts to smear, defame and _unperson_ me. After requesting of me directly that I “fall on my sword” and not receiving the answer it wanted, the Board has chosen to make it clear to where it collectively thinks the high moral ground is in this matter. As I have already expressed to them, I believe they have made a poor assessment of the facts, and have not made the correct choice on their moral stance, and have now stood by and encouraged additional smears against me.\n", - "\n", - "I will have more to say on the Board’s role and our relationship to it below, however.\n", - "\n", - "### That I am a barrier to inclusivity efforts\n", - "\n", - "This is a refrain that is often repeated on social media about me and it's never been made clear, to me at least, how this is justified.\n", - "\n", - "By most objective measures, the Node.js project has been healthier and more open to outsiders during my 2-year tenure in leadership than at any time in its history. One of the great pleasures I've had during this time has been in showing and celebrating this on the conference circuit. We have record numbers of contributors overall, per month overall and unique per month. Our issue tracker is so busy with activity that very few of us can stay subscribed to the firehose any more. We span the globe such that our core and working group meetings are very difficult to schedule and usually have to end up leaving people out. We regularly have to work to overcome language and cultural barriers as we continue to expand.\n", - "\n", - "When I survey the contributor base, the collaborator list, the CTC membership, I see true diversity across many dimensions. Claims that I am a barrier to inclusivity and the building of a diverse contributor base are at odds with the prominent role I've had in the project during its explosive growth.\n", - "\n", - "My assessment of the claim that I am a hindrance to inclusivity efforts is that it hinges on the singular matter of moderation and control of discourse that occurs amongst the technical team. From the beginning I have strongly maintained that the technical team should retain authority over its own space. That its independence also involves its ability to enforce the rules of social interaction and discussion as it sees fit. This has lead to disagreements with individuals that would rather insert external arbiters into the moderation process; arbiters who have not earned the right to stand in judgement of technical team members, and have not been held to the same standards by which technical team members are judged to earn their place in the project.\n", - "\n", - "On this matter I remain staunchly opposed to the dilution of independence of the technical team and will continue to advocate for its ability to make such critical decisions for itself. This is not only a question of moral (earned) authority, but of the risk of subversion of our organisational structures by individuals who are attracted to the project by the possibility of pursuing a personal agenda, regardless of the impact this has on the project itself. I see current moves in this direction, as in this week’s moderation policy proposal at [nodejs/TSC#276](https://github.com/nodejs/TSC/pull/276), as presenting such a risk. I don't expect everyone to agree with me on this, but I have just as much right as everyone else to make my case and not be vilified in my attempts to convince enough of the TSC to prevent such changes.\n", - "\n", - "Further, regarding other smears against my character that now circulate regularly on social media and GitHub. I would ask that if you are using any of these as the basis of your judgement against me, please ask for supporting evidence of those making or repeating such smears. It's been an educational experience to watch a caricatured narrative about my character grow into the monster that it is today, and it saddens me when people I respect take this narrative at face value without bothering to scratch the surface to see if there is any basis in fact.\n", - "\n", - "The use of language such as “systematic” and “pattern” to avoid having to outline specifics should be seen for what they are: baseless smears. I have a large body of text involving many hundreds of social interactions scattered through the Node.js project and its various repositories on GitHub. If any such “systematic” behavioural problems exist then it should not be difficult to provide clear documentation of them.\n", - "\n", - "### Threats to the independence of the technical group\n", - "\n", - "We now face the unprecedented move by the Node.js Foundation Board to [inject itself](https://github.com/nodejs/board/issues/67) directly in our decision-making process. The message being: the TSC voted the wrong way, they should do it again until you get the “right” outcome. \n", - "\n", - "This echoes the sentiment being [expressed in the Community Committee](https://github.com/nodejs/community-committee/issues/111) and elsewhere, that since there were accusations, there must be guilt and the fault lies in the inability of the TSC to deal with that guilt. With no credence paid to the possibility that _perhaps_ the TSC evaluated the facts and reached a consensus that no further action was necessary. \n", - "\n", - "I have some sympathy for the position of the Node.js Foundation board. These are tough times in the Silicon Valley environment, particularly with the existing concerns surrounding diversity, inclusivity, and tolerance. I can understand how _rumors_ of similarly unacceptable behavior can pose a threat, even absent any evidence of such behavior. That said, I do not believe that it is in the long-term interests of Node.js or its Foundation to pander to angry mobs, as they represent a small fraction of our stakeholders and their demands are rarely rational. In this case, I believe that a majority of outsiders will be viewing this situation with bemusement at best. It saddens me that there is no recognition of the fact that appeasing angry and unverified demands by activists only leads to greater demands and less logical discussion of these issues. If we accept this precedent then we place the future health of this project in jeopardy, as we will have demonstrated that we allow outsiders to adjust our course to suit personal or private agendas, as long as they can concoct a story to create outrage and dispense mob justice without reproach.\n", - "\n", - "While difficult, I believe that it is important for the technical team to continue to assert its independence, to the board and to other outside influences. We are not children who need adult supervision; treating us as such undermines so much of what we have built over these last few years and erodes the feelings of ownership of the project that we have instilled in our team of collaborators.\n", - "\n", - "### The threat to future leadership of the project\n", - "\n", - "Finally, I want to address a critical problem which has been overlooked, but now poses a big problem for our future: how to grow, enable and support leadership in such a difficult environment.\n", - "\n", - "My tenure in leadership easily represents the most difficult years of my life. The challenges I have had to face have forced me to grow in ways I never expected. I'm thankful for the chance to meet these challenges, however, and even though it's taken a toll on my health, I'll be glad to have had the experience when I look back.\n", - "\n", - "One of my tasks as a leader, particularly serving in the role of bridge between the Board and the technical team, has involved maintaining that separation and independence but also shielding the technical team from the intense corporate and personal politics that constantly exists and is being exercised within, and around the Foundation. This role forced me to take strong positions on many issues and to stand up to pressure applied from many different directions. In doing what I felt was best to support my technical team members I’m sure I’ve put people off-side—that's an unfortunate consequence of good intentions, but not an uncommon one. I wouldn't say I've made enemies so much as had to engage in _very_ difficult conversations and involve myself in the surfacing of many disagreements that are difficult and sometimes impossible to resolve.\n", - "\n", - "Having to involve yourself in a wide variety of decision-making processes inevitably requires that you make tough calls or connect yourself in some way to controversial discussions. I'm sure our current leadership can attest to the awkward positions they have found themselves in, and the difficult conversations they have had to navigate, including this one!\n", - "\n", - "I'll never pretend I don't have limitations in the skills, both intellectually and emotionally, required to navigate through these tough waters. But when I consider the sheer number of dramas, controversies, and difficult conversations I've had to be involved in—and when I consider the thousands of pages of text I have left littered across GitHub and the other forums we use to get things done—I come to this conclusion: If the best reason you can find force my resignation is the above list of infractions, **given the weight of content you could dredge through, then you're either not trying very hard or I should be pretty proud of myself for keeping a more level head than I had imagined**.\n", - "\n", - "That aside, my greatest concern for the role of leadership coming as a consequence of the actions currently being pursued, is that we've painted ourselves into a corner regarding the leaders we're going to have available. The message that the Board has chosen to send today can be rightly interpreted as this: if the mob comes calling, if the narrative of evil is strong enough, regardless of the objective facts, the Foundation does not have your back. As developers and leaders, the Foundation is signalling that they will not stand up for us when things get tough. Combine this with a difficult and thankless job, where the result of exercising your duties could be career-killing, the only path forward for leadership is that we will likely only have:\n", - "\n", - "* Individuals who are comfortable giving in to the whims of the outside activists, whatever the demands, slowly transforming this project into something entirely different and focused on matters not associated with making Node.js a success\n", - "* Individuals who are capable but shrewd enough to avoid responsibility\n", - "* Individuals who are capable and take on responsibility, exercise backbone when standing against pressure groups and mob tactics but get taken down because the support structures either abandon them or turn against them\n", - "\n", - "This kind of pattern is being evidenced across the professionalised open source sphere, with Node.js about to set a new low bar. Do not be surprised as quality leaders become more difficult to find or become unconvinced that the exercise of leadership duties is at all in their personal interest.\n", - "\n", - "This is a great challenge for modern open source and I'm so sad that I am being forced to be involved in the setting of our current trajectory. I hope we can find space in the future to have the necessary dialog to find a way out of the hole being dug.\n", - "\n", - "### In summary\n", - "\n", - "Obviously I hope that you agree that (a) this action against me is unwarranted, is based on flawed and/or irrelevant claims of “misbehaviour” and is based in malicious intent, and that (b) allowing this course of action to be an acceptable part of our governance procedures will have detrimental consequences for the future health of the project.\n", - "\n", - "I ask the CTC to reject this motion, for the TSC to reject the demand by the Board for my suspension, and that we as a technical team send a signal that our independence is critical to the success of the project, despite the accusations of an angry mob.\n", - "\n", - "Thank you if you dignified my words by reading this far!\"\"\"" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": { - "scrolled": false - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "-0.006453296703296698\n" - ] - } - ], - "source": [ - "sentences = tokenizer.tokenize(message_text)\n", - "compound = parts = 0\n", - "sentiment = \"Positive\"\n", - "for sentence in sentences:\n", - " scores = sid.polarity_scores(sentence)\n", - " print\n", - " compound+= scores['compound']\n", - " parts+=1\n", - "avg_score = compound/parts\n", - "print(avg_score)\n", - "#print(message_text)" + " #print(fin_dates)\n", + " slope, intercept, r_value, p_value, std_err = stats.linregress(fin_dates,fin_values)\n", + " line = slope*fin_dates+intercept\n", + " plot.plot(fin_dates,fin_values,'o', fin_dates, line)\n", + " #plot.savefig('foo' + str(x) + '.png')\n", + " #x+=1\n", + " plot.show()" ] } ], diff --git a/notebooks/github-issues.ipynb b/notebooks/github-issues.ipynb index 5cc79900bf..01ba4f80be 100644 --- a/notebooks/github-issues.ipynb +++ b/notebooks/github-issues.ipynb @@ -24,6 +24,15 @@ "from time import gmtime, strftime" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Load\n", + "\n", + "First loads the users data from 'augur.config.json' so will take the Database information (e.g. name of database, port of database). Then connects to the database using augur.App.github_issues() and takes the details of the database and connects to to the database using charset 'utf8'. It also makes a connection to piper_reader" + ] + }, { "cell_type": "code", "execution_count": 2, @@ -45,6 +54,15 @@ "Piper, path= augurApp.piper()" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Connect:\n", + "\n", + "Queries what tables are in the database and determines if 'github_issues_2' is there if it is then 'git_repos' is set as 'True', if it isn't there 'git_repos' is set as 'False'. Then we determine what git repositories are in 'github_issues_repo_jobs' and determine how many rows are in it. If 'github_issues_repo_jobs' is not in the database it is created and the column 'augurlistID' is set as the primary key. We then add a connection to 'github_issues_repo_jobs' so that we can change the column 'last_run' if new messages were downloaded for a git repository." + ] + }, { "cell_type": "code", "execution_count": 3, @@ -110,6 +128,15 @@ "res = session.query(table).all()" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Write to file:\n", + "\n", + "Determines if the file with the git repositories were created, if not it writes a set of default git repositories (to show how the program would work)." + ] + }, { "cell_type": "code", "execution_count": 4, @@ -152,24 +179,20 @@ " count+=1\n", " if(count == 2):\n", " break\n", - "file.close()" + "file.close()\n", + "\n", + "print(df1['project'].values)" ] }, { - "cell_type": "code", - "execution_count": 5, + "cell_type": "markdown", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[]\n" - ] - } - ], "source": [ - "print(df1['project'].values)" + "## Iteration through github repositories\n", + "\n", + "This first reads the git repositories stored in 'path' and we also get the current date 'today'. We then create a dataframe 'github_issues_2' that will store all the comments under an issue and the issue itself. Grouping the issues by owner we iterate through the different repositories and then iterate over the messages for a particular issue. We then pull the data from GitHub and we determine if the repository is stored in 'github_issues_repo_jobs', if it is we set 'new' to 'True' and store that repository so it can be added to the table 'github_issues_repo_jobs and 'froms' is set as 'None'. If it is in 'github_issues_repo_jobs' we set today's date to 'last_run' for the repository in 'github_issues_repo_jobs' and 'froms' is set as today's date.\n", + "\n", + "We then go about downloading the github issues for a particular repository, the 'from_date' is set as 'froms'. We then convert issues to a format that can be uploaded to the datebase. If the git repository is stored in 'github_issues_repo_jobs' then only the issues that occur after the date stored in 'last_run' is uploaded. If the git repository isn't in the database all the issues are uploaded. We finally upload the git repositories information to the table 'github_issues_repo_jobs'. Since github has a limit as to how much data can be downloaded, if a large repository with a number of issues is being downloaded the program will run for hours, since the Rate limit must be reset which takes around an hour each time." ] }, { @@ -6623,20 +6646,6 @@ } ], "source": [ - "# Url for the git repo to analyze\n", - "#repo_url = 'https://github.com/chaoss/grimoirelab-perceval'\n", - "#repo_url = 'CTC'\n", - "# Directory for letting Perceval clone the git repo\n", - "#repo_dir = 'CTC'\n", - "#own = 'nodejs'\n", - "# ElasticSearch instance (url)\n", - "#repo = 'grimoirelab-perceval'\n", - "# Create the 'commits' index in ElasticSearch\n", - "# Create a Git object, pointing to repo_url, using repo_dir for cloning\n", - "\n", - "#32\n", - "#date = datetime.datetime(2017, 8, 7, 0, 0, 0,\n", - "# tzinfo=dateutil.tz.tzutc())\n", "'''\n", "owner,repo_url\n", "torvalds,\"linux\"\n", diff --git a/notebooks/github_issues_scores.ipynb b/notebooks/github_issues_scores.ipynb index ac6dfe9076..32c62ee708 100644 --- a/notebooks/github_issues_scores.ipynb +++ b/notebooks/github_issues_scores.ipynb @@ -61,9 +61,18 @@ "%matplotlib inline" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Load\n", + "\n", + "First loads the users data from 'augur.config.json' so will take the Database information (e.g. name of database, port of database). Then connects to the database using augur.App.github_issues() and takes the details of the database and connects to to the database using charset 'utf8'. It also makes a connection to piper_reader, it then determines if 'github_issues_2' is in the Database if so it stores the git repositories into 'df1'. It then loads the SentimentIntensityAnalyzer from NLTK (Natural Language Tool Kit) and stores the table 'github_issues_2' which has all the github issues into 'df_users'." + ] + }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": { "collapsed": true }, @@ -77,123 +86,38 @@ " list1[0], list1[1], list1[2],\\\n", " list1[3], list1[4]\n", " )\n", - "db = s.create_engine(DB_STR)" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "['github_issues', 'github_issues_2', 'github_issues_repo_jobs', 'github_issues_sentiment_scores', 'github_pull_request_repo_jobs', 'github_pull_requests', 'github_pull_requests_2', 'github_pull_requests_sentiment_scores', 'issue_response_time', 'mail_lists', 'mail_lists_sentiment_scores', 'mailing_list_jobs']\n" - ] - } - ], - "source": [ + "db = s.create_engine(DB_STR)\n", + "\n", "table_names = s.inspect(db).get_table_names()\n", - "print(table_names)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ + "print(table_names)\n", + "\n", "if(\"github_issues_2\" in table_names):\n", " lists_createdSQL = s.sql.text(\"\"\"SELECT repo FROM github_issues_2\"\"\")\n", " df1 = pd.read_sql(lists_createdSQL, db)\n", " #print(df1)\n", - " val = True" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ + " val = True\n", + "\n", + " \n", + "\n", "tokenizer = nltk.data.load('tokenizers/punkt/english.pickle')\n", "sid = SentimentIntensityAnalyzer()\n", - "col = 'score','sentiment'" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": { - "scrolled": false - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " augurmsgID backend_name repo_link owner repo \\\n", - "0 1 GitHub https://github.com/nodejs/CTC nodejs CTC \n", - "1 2 GitHub https://github.com/nodejs/CTC nodejs CTC \n", - "2 3 GitHub https://github.com/nodejs/CTC nodejs CTC \n", - "3 4 GitHub https://github.com/nodejs/CTC nodejs CTC \n", - "4 5 GitHub https://github.com/nodejs/CTC nodejs CTC \n", - "\n", - " subject status category issue_number timestamp \\\n", - "0 Purpose of nodejs/CTC closed issue 1 2016-06-09 12:43:54 \n", - "1 Purpose of nodejs/CTC closed issue 1 2016-06-09 12:53:53 \n", - "2 Purpose of nodejs/CTC closed issue 1 2016-06-09 13:34:16 \n", - "3 Purpose of nodejs/CTC closed issue 1 2016-06-09 13:57:58 \n", - "4 Purpose of nodejs/CTC closed issue 1 2016-06-09 13:59:05 \n", - "\n", - " issue_id user body \n", - "0 159398443 rvagg @nodejs/collaborators I'm not sure if this is ... \n", - "1 159398443 vkurchatkin > Core Technical Team (CTC)\\n\\nTypo?\\n \n", - "2 159398443 rvagg blerh, yes, fixing, thanks\\n \n", - "3 159398443 benjamingr If I want to being an issue to the CTC's atten... \n", - "4 159398443 benjamingr > Issues that Node.js needs to begin consideri... \n", - " augurmsgID backend_name repo_link owner repo \\\n", - "6707 6708 GitHub https://github.com/nodejs/TSC nodejs TSC \n", - "6708 6709 GitHub https://github.com/nodejs/TSC nodejs TSC \n", - "6709 6710 GitHub https://github.com/nodejs/TSC nodejs TSC \n", - "6710 6711 GitHub https://github.com/nodejs/TSC nodejs TSC \n", - "6711 6712 GitHub https://github.com/nodejs/TSC nodejs TSC \n", - "\n", - " subject status category \\\n", - "6707 Proposal: add all new core modules under a sco... open issue \n", - "6708 Proposal: add all new core modules under a sco... open issue \n", - "6709 Proposal: add all new core modules under a sco... open issue \n", - "6710 Proposal: add all new core modules under a sco... open issue \n", - "6711 Proposal: add all new core modules under a sco... open issue \n", - "\n", - " issue_number timestamp issue_id user \\\n", - "6707 389 2018-08-01 14:41:02 266702892 mhdawson \n", - "6708 389 2018-08-01 15:10:37 266702892 ljharb \n", - "6709 389 2018-08-02 14:44:17 266702892 benjamingr \n", - "6710 389 2018-08-02 17:20:02 266702892 ljharb \n", - "6711 389 2018-08-02 22:25:45 266702892 mhdawson \n", - "\n", - " body \n", - "6707 In the last TSC meeting we discussed again, th... \n", - "6708 @mhdawson i think the list would either be “em... \n", - "6709 I'm +1 on moving existing modules with new API... \n", - "6710 I think creating new APIs while moving existin... \n", - "6711 @ljharb I think the key point was that we shou... \n" - ] - } - ], - "source": [ + "col = 'score','sentiment'\n", + "\n", "SQL = \"\"\"SELECT * FROM github_issues_2\"\"\"\n", "df_users = pd.read_sql(SQL, db)\n", "print(df_users.head())\n", "print(df_users.tail())" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Sentiment Scores:\n", + "\n", + "Groups all the messages by subject and then iterates through the subjects, it then iterates through the different messages in the subject and feeds this to the tokenizer which breaks the message into different parts and gives the sentiment for them and then finds the average of the parts. This is then added to df3." + ] + }, { "cell_type": "code", "execution_count": 8, @@ -261,6 +185,15 @@ "print(num)" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Combine\n", + "\n", + "Combines the dataframe with all the messages and joins that with the scores for the messages. Then uploads this to the database as 'github_issues_sentiment_scores_2'." + ] + }, { "cell_type": "code", "execution_count": 9, @@ -274,67 +207,26 @@ "df3 = df3.reset_index(drop=True)\n", "#print(df3.head())\n", "df_list = df_list.reset_index(drop=True)\n", - "combine = (df_list.join(df3))" + "combine = (df_list.join(df3))\n", + "\n", + "print(combine.head())\n", + "\n", + "combine.to_sql(name='github_issues_sentiment_scores_2',\\\n", + " con=db,if_exists='replace',index=False)" ] }, { - "cell_type": "code", - "execution_count": 10, + "cell_type": "markdown", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " augurmsgID backend_name repo_link owner repo \\\n", - "0 1 GitHub https://github.com/nodejs/CTC nodejs CTC \n", - "1 2 GitHub https://github.com/nodejs/CTC nodejs CTC \n", - "2 3 GitHub https://github.com/nodejs/CTC nodejs CTC \n", - "3 4 GitHub https://github.com/nodejs/CTC nodejs CTC \n", - "4 5 GitHub https://github.com/nodejs/CTC nodejs CTC \n", - "\n", - " subject status category issue_number timestamp \\\n", - "0 Purpose of nodejs/CTC closed issue 1 2016-06-09 12:43:54 \n", - "1 Purpose of nodejs/CTC closed issue 1 2016-06-09 12:53:53 \n", - "2 Purpose of nodejs/CTC closed issue 1 2016-06-09 13:34:16 \n", - "3 Purpose of nodejs/CTC closed issue 1 2016-06-09 13:57:58 \n", - "4 Purpose of nodejs/CTC closed issue 1 2016-06-09 13:59:05 \n", - "\n", - " issue_id user body \\\n", - "0 159398443 rvagg @nodejs/collaborators I'm not sure if this is ... \n", - "1 159398443 vkurchatkin > Core Technical Team (CTC)\\n\\nTypo?\\n \n", - "2 159398443 rvagg blerh, yes, fixing, thanks\\n \n", - "3 159398443 benjamingr If I want to being an issue to the CTC's atten... \n", - "4 159398443 benjamingr > Issues that Node.js needs to begin consideri... \n", - "\n", - " score sentiment \n", - "0 -0.008 Negative \n", - "1 0.087 Positive \n", - "2 -0.043 Negative \n", - "3 0.034 Positive \n", - "4 0.140 Positive \n" - ] - } - ], - "source": [ - "print(combine.head())" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": { - "collapsed": true - }, - "outputs": [], "source": [ - "#combine.to_sql(name='github_issues_sentiment_scores_2',\\\n", - "# con=db,if_exists='replace',index=False)" + "## Graphs\n", + "\n", + "Takes all the git repositories in 'combine' and groups by the column 'repo_link' and gets the dates and sentiment scores and plots a graph based on this." ] }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 15, "metadata": { "scrolled": false }, @@ -343,15 +235,37 @@ "name": "stdout", "output_type": "stream", "text": [ - "\n", - "['2016-11-08 04:32:36' '2016-11-08 06:10:25' '2016-11-08 12:32:31'\n", - " '2016-11-08 20:25:53' '2016-11-08 22:45:30' '2016-11-08 23:15:32'\n", - " '2016-11-09 17:21:55' '2016-11-09 18:14:55' '2016-11-09 18:49:23'\n", - " '2016-11-09 18:58:14' '2016-11-14 05:27:06' '2016-11-14 05:29:08'\n", - " '2016-11-14 10:49:40' '2016-11-14 21:45:59' '2016-11-17 22:55:45'\n", - " '2016-11-17 23:21:35' '2016-11-17 23:33:32' '2016-11-21 06:34:40'\n", - " '2016-11-21 07:02:29']\n" + "(126,)\n", + "(126,)\n" ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(357,)\n", + "(357,)\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" } ], "source": [ @@ -373,9 +287,8 @@ " #print(\"Issue number: \",issue_num[0])\n", " x = np.array(dates)\n", " dates = np.unique(x)\n", - " print(type(x[0]))\n", - " print(dates)\n", - " break\n", + " #print(type(x[0]))\n", + " #print(dates)\n", " dates = [dt.datetime.strptime(d[:10],'%Y-%m-%d').date() for d in x]\n", " #print(dates)\n", " dates1 = [x for x in dates]\n", @@ -384,7 +297,6 @@ " fin_values.append(values)\n", " num+=1\n", " j+=1\n", - " break\n", " fin_dates = mdates.date2num(fin_dates)\n", " fin_values = np.asarray(fin_values)\n", " print(fin_dates.shape)\n", diff --git a/notebooks/github_pull_requests.ipynb b/notebooks/github_pull_requests.ipynb index fc241dc939..8bc4fef6ec 100644 --- a/notebooks/github_pull_requests.ipynb +++ b/notebooks/github_pull_requests.ipynb @@ -24,6 +24,15 @@ "from time import gmtime, strftime" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Load\n", + "\n", + "First loads the users data from 'augur.config.json' so will take the Database information (e.g. name of database, port of database). Then connects to the database using augur.App.github_issues() and takes the details of the database and connects to to the database using charset 'utf8'. It also makes a connection to piper_reader" + ] + }, { "cell_type": "code", "execution_count": 2, @@ -45,6 +54,15 @@ "Piper, path= augurApp.piper()" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Connect:\n", + "\n", + "Queries what tables are in the database and determines if 'github_pull_requests_2' is there if it is then 'git_repos' is set as 'True', if it isn't there 'git_repos' is set as 'False'. Then we determine what git repositories are in 'github_issues_repo_jobs' and determine how many rows are in it. If 'github_pull_request_repo_jobs' is not in the database it is created and the column 'augurlistID' is set as the primary key. We then add a connection to 'github_pull_request_repo_jobs' so that we can change the column 'last_run' if new messages were downloaded for a git repository." + ] + }, { "cell_type": "code", "execution_count": 3, @@ -110,6 +128,15 @@ "res = session.query(table).all()" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Write to file:\n", + "\n", + "Determines if the file with the git repositories were created, if not it writes a set of default git repositories (to show how the program would work)." + ] + }, { "cell_type": "code", "execution_count": 4, @@ -152,6 +179,17 @@ "file.close()" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Iteration through github repositories\n", + "\n", + "This first reads the git repositories stored in 'path' and we also get the current date 'today'. We then create a dataframe 'github_pull_requests_2' that will store all the comments under a pull request and the pull requrest itself. Grouping the pull request by owner we iterate through the different repositories and then iterate over the messages for a particular pull request. We then pull the data from GitHub and we determine if the repository is stored in 'github_pull_request_repo_jobs', if it is we set 'new' to 'True' and store that repository so it can be added to the table 'github_pull_request_repo_jobs and 'froms' is set as 'None'. If it is in 'github_pull_request_repo_jobs' we set today's date to 'last_run' for the repository in 'github_pull_request_repo_jobs' and 'froms' is set as today's date.\n", + "\n", + "We then go about downloading the github pull requests for a particular repository, the 'from_date' is set as 'froms'. We then convert pull requests to a format that can be uploaded to the datebase. If the git repository is stored in 'github_pull_request_repo_jobs' then only the pull requests that occur after the date stored in 'last_run' is uploaded. If the git repository isn't in the database all the issues are uploaded. We finally upload the git repositories information to the table 'github_pull_request_repo_jobs'. Since github has a limit as to how much data can be downloaded, if a large repository with a number of pull requests is being downloaded the program will run for hours, since the Rate limit must be reset which takes around an hour each time." + ] + }, { "cell_type": "code", "execution_count": 5, @@ -212,22 +250,6 @@ } ], "source": [ - "# Url for the git repo to analyze\n", - "#repo_url = 'https://github.com/chaoss/grimoirelab-perceval'\n", - "#repo_url = 'CTC'\n", - "# Directory for letting Perceval clone the git repo\n", - "#repo_dir = 'CTC'\n", - "#own = 'nodejs'\n", - "# ElasticSearch instance (url)\n", - "#repo = 'grimoirelab-perceval'\n", - "\n", - "# Create the 'commits' index in ElasticSearch\n", - "# Create a Git object, pointing to repo_url, using repo_dir for cloning\n", - "\n", - "#32\n", - "#date = datetime.datetime(2017, 8, 7, 0, 0, 0,\n", - "# tzinfo=dateutil.tz.tzutc())\n", - "\n", "'''\n", "owner,repo_url\n", "torvalds,\"linux\"\n", diff --git a/notebooks/github_pull_requests_scores.ipynb b/notebooks/github_pull_requests_scores.ipynb index e69075e631..cd4d0e8488 100644 --- a/notebooks/github_pull_requests_scores.ipynb +++ b/notebooks/github_pull_requests_scores.ipynb @@ -61,6 +61,15 @@ "%matplotlib inline" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Load\n", + "\n", + "First loads the users data from 'augur.config.json' so will take the Database information (e.g. name of database, port of database). Then connects to the database using augur.App.github_issues() and takes the details of the database and connects to to the database using charset 'utf8'. It also makes a connection to piper_reader, it then determines if 'github_pull_requests_2' is in the Database if so it stores the git repositories into 'df1'. It then loads the SentimentIntensityAnalyzer from NLTK (Natural Language Tool Kit) and stores the table 'github_pull_requests_2' which has all the github pull requests into 'df_users'." + ] + }, { "cell_type": "code", "execution_count": 3, @@ -77,133 +86,34 @@ " list1[0], list1[1], list1[2],\\\n", " list1[3], list1[4]\n", " )\n", - "db = s.create_engine(DB_STR)" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "['github_issues', 'github_issues_2', 'github_issues_repo_jobs', 'github_issues_sentiment_scores', 'github_pull_request_repo_jobs', 'github_pull_requests', 'github_pull_requests_2', 'github_pull_requests_sentiment_scores', 'issue_response_time', 'mail_lists', 'mail_lists_sentiment_scores', 'mailing_list_jobs']\n" - ] - } - ], - "source": [ + "db = s.create_engine(DB_STR)\n", + "\n", "table_names = s.inspect(db).get_table_names()\n", - "print(table_names)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ + "print(table_names)\n", + "\n", "if(\"github_pull_requests_2\" in table_names):\n", " lists_createdSQL = s.sql.text(\"\"\"SELECT repo FROM github_pull_requests_2\"\"\")\n", " df1 = pd.read_sql(lists_createdSQL, db)\n", " #print(df1)\n", - " val = True" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ + " val = True\n", + "\n", "tokenizer = nltk.data.load('tokenizers/punkt/english.pickle')\n", "sid = SentimentIntensityAnalyzer()\n", - "col = 'score','sentiment'" + "col = 'score','sentiment'\n", + "\n", + "SQL = \"\"\"SELECT * FROM github_pull_requests_2\"\"\"\n", + "df_users = pd.read_sql(SQL, db)\n", + "print(df_users.head())\n", + "print(df_users.tail())" ] }, { - "cell_type": "code", - "execution_count": 7, + "cell_type": "markdown", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " augurmsgID backend_name repo_link \\\n", - "0 1 GitHub https://github.com/OSSHealth/ResearchProject \n", - "1 2 GitHub https://github.com/OSSHealth/ResearchProject \n", - "2 3 GitHub https://github.com/OSSHealth/ResearchProject \n", - "3 4 GitHub https://github.com/OSSHealth/ResearchProject \n", - "4 5 GitHub https://github.com/OSSHealth/ResearchProject \n", - "\n", - " owner repo \\\n", - "0 OSSHealth ResearchProject \n", - "1 OSSHealth ResearchProject \n", - "2 OSSHealth ResearchProject \n", - "3 OSSHealth ResearchProject \n", - "4 OSSHealth ResearchProject \n", - "\n", - " subject status category \\\n", - "0 Consolidated Indicators closed pull_request \n", - "1 Added broad categories, bolded indicators that... closed pull_request \n", - "2 added indicators and ideas from LFOSLS closed pull_request \n", - "3 added indicators and ideas from LFOSLS closed pull_request \n", - "4 Added use cases close #23 closed pull_request \n", - "\n", - " pull_request_number date pull_request_id user \\\n", - "0 4 2017-02-01 20:14:18 204692448 GeorgLink \n", - "1 8 2017-02-04 23:46:53 205387286 GeorgLink \n", - "2 18 2017-02-17 19:29:23 208533954 GeorgLink \n", - "3 18 2017-02-20 22:15:41 208533954 GeorgLink \n", - "4 24 2017-03-18 15:42:06 215202044 GeorgLink \n", - "\n", - " body \n", - "0 I pulled together different files, included in... \n", - "1 The edits respond to the conversation with @ho... \n", - "2 close #15 \n", - "3 Since no one seems to object, I'll merge my ow... \n", - "4 Responds to #23 \\r\\n\\r\\nI created a new branch... \n", - " augurmsgID backend_name repo_link owner \\\n", - "14 15 GitHub https://github.com/chaoss/whitepaper chaoss \n", - "15 16 GitHub https://github.com/chaoss/whitepaper chaoss \n", - "16 17 GitHub https://github.com/chaoss/whitepaper chaoss \n", - "17 18 GitHub https://github.com/chaoss/whitepaper chaoss \n", - "18 19 GitHub https://github.com/chaoss/whitepaper chaoss \n", - "\n", - " repo subject status \\\n", - "14 whitepaper How to contribute and more ideas for content. closed \n", - "15 whitepaper Add FAQ section closed \n", - "16 whitepaper Add FAQ section closed \n", - "17 whitepaper Update whitepaper.md closed \n", - "18 whitepaper Update whitepaper.md closed \n", - "\n", - " category pull_request_number date pull_request_id \\\n", - "14 pull_request 2 2018-01-22 20:55:50 290611948 \n", - "15 pull_request 3 2018-02-04 17:14:26 294213130 \n", - "16 pull_request 3 2018-02-04 17:39:41 294213130 \n", - "17 pull_request 6 2018-03-04 06:52:42 302062739 \n", - "18 pull_request 6 2018-03-04 13:01:39 302062739 \n", - "\n", - " user body \n", - "14 GeorgLink I'll leave it up for a day before I merge it. \n", - "15 GeorgLink We certainly have more FAQ, but these are a fe... \n", - "16 germonprez Those are a good set of questions. The WP woul... \n", - "17 rpaik Sorry, I haven't done this earlier.\\r\\n\\r\\nI s... \n", - "18 GeorgLink Thanks @rpaik, I will merge it to keep the ide... \n" - ] - } - ], "source": [ - "SQL = \"\"\"SELECT * FROM github_pull_requests_2\"\"\"\n", - "df_users = pd.read_sql(SQL, db)\n", - "print(df_users.head())\n", - "print(df_users.tail())" + "## Sentiment Scores:\n", + "\n", + "Groups all the messages by subject and then iterates through the subjects, it then iterates through the different messages in the subject and feeds this to the tokenizer which breaks the message into different parts and gives the sentiment for them and then finds the average of the parts. This is then added to df3." ] }, { @@ -274,6 +184,15 @@ "print(num)" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Combine\n", + "\n", + "Combines the dataframe with all the messages and joins that with the scores for the messages. Then uploads this to the database as 'github_pull_requests_sentiment_scores_2'." + ] + }, { "cell_type": "code", "execution_count": 9, @@ -287,69 +206,21 @@ "df3 = df3.reset_index(drop=True)\n", "#print(df3.head())\n", "df_list = df_list.reset_index(drop=True)\n", - "combine = (df_list.join(df3))" + "combine = (df_list.join(df3))\n", + "\n", + "print(combine.head())\n", + "\n", + "combine.to_sql(name='github_pull_requests_sentiment_scores_2',\\\n", + " con=db,if_exists='replace',index=False)" ] }, { - "cell_type": "code", - "execution_count": 10, + "cell_type": "markdown", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " augurmsgID backend_name repo_link \\\n", - "0 1 GitHub https://github.com/OSSHealth/ResearchProject \n", - "1 2 GitHub https://github.com/OSSHealth/ResearchProject \n", - "2 3 GitHub https://github.com/OSSHealth/ResearchProject \n", - "3 4 GitHub https://github.com/OSSHealth/ResearchProject \n", - "4 5 GitHub https://github.com/OSSHealth/ResearchProject \n", - "\n", - " owner repo \\\n", - "0 OSSHealth ResearchProject \n", - "1 OSSHealth ResearchProject \n", - "2 OSSHealth ResearchProject \n", - "3 OSSHealth ResearchProject \n", - "4 OSSHealth ResearchProject \n", - "\n", - " subject status category \\\n", - "0 Consolidated Indicators closed pull_request \n", - "1 Added broad categories, bolded indicators that... closed pull_request \n", - "2 added indicators and ideas from LFOSLS closed pull_request \n", - "3 added indicators and ideas from LFOSLS closed pull_request \n", - "4 Added use cases close #23 closed pull_request \n", - "\n", - " pull_request_number date pull_request_id user \\\n", - "0 4 2017-02-01 20:14:18 204692448 GeorgLink \n", - "1 8 2017-02-04 23:46:53 205387286 GeorgLink \n", - "2 18 2017-02-17 19:29:23 208533954 GeorgLink \n", - "3 18 2017-02-20 22:15:41 208533954 GeorgLink \n", - "4 24 2017-03-18 15:42:06 215202044 GeorgLink \n", - "\n", - " body score sentiment \n", - "0 I pulled together different files, included in... 0.319 Positive \n", - "1 The edits respond to the conversation with @ho... 0.583 Positive \n", - "2 close #15 0.827 Positive \n", - "3 Since no one seems to object, I'll merge my ow... 0.081 Positive \n", - "4 Responds to #23 \\r\\n\\r\\nI created a new branch... 0.125 Positive \n" - ] - } - ], - "source": [ - "print(combine.head())" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": { - "collapsed": true - }, - "outputs": [], "source": [ - "combine.to_sql(name='github_pull_requests_sentiment_scores_2',\\\n", - " con=db,if_exists='replace',index=False)" + "## Graphs\n", + "\n", + "Takes all the git repositories in 'combine' and groups by the column 'repo_link' and gets the dates and sentiment scores and plots a graph based on this." ] }, {