Last active
August 29, 2015 14:10
-
-
Save jasonost/8bf5aad33df4d2917de1 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"worksheets": [ | |
{ | |
"cells": [ | |
{ | |
"metadata": {}, | |
"cell_type": "code", | |
"input": "import pandas as pd, numpy as np, datetime, random, cPickle as pickle\nfrom sklearn.cluster import KMeans, DBSCAN\nfrom sklearn.cluster.bicluster import SpectralBiclustering\nfrom sklearn.linear_model import LinearRegression\nfrom scipy import stats\nfrom collections import Counter\nfrom __future__ import division\npd.set_option('max_colwidth', 200)\npd.set_option('display.max_rows', 500)\n%matplotlib inline", | |
"prompt_number": 1, | |
"outputs": [], | |
"language": "python", | |
"trusted": true, | |
"collapsed": false | |
}, | |
{ | |
"metadata": {}, | |
"cell_type": "markdown", | |
"source": "### Read in data" | |
}, | |
{ | |
"metadata": {}, | |
"cell_type": "code", | |
"input": "base_path = '../data/'\nfile_2011 = 'stark_2011_events.csv'\ngrades_2011 = 'anonymized11.csv'", | |
"prompt_number": 2, | |
"outputs": [], | |
"language": "python", | |
"trusted": true, | |
"collapsed": false | |
}, | |
{ | |
"metadata": {}, | |
"cell_type": "code", | |
"input": "events = pd.read_csv('%s%s' % (base_path,file_2011),\n skiprows=1,\n names=['userId',\n 'updatedAt',\n 'eventType',\n 'activityType',\n 'activityTitle',\n 'topicTitle',\n 'timeMinutes',\n 'scorePercent',\n 'anchorValue',\n 'anchorSelection',\n 'topicId',\n 'activityId',\n 'activityEventId',\n 'updateCount'],\n parse_dates=[\"updatedAt\"],\n na_values=[\"\\N\"],\n delimiter=\"\\t\"\n )\n\ngrades = pd.read_csv('%s%s' % (base_path,grades_2011),\n skiprows=1,\n names=[\"dropcol\",\n \"userId\",\n \"Set0\",\n \"Set1\",\n \"Set2\",\n \"Set3\",\n \"Set4\",\n \"Set5\",\n \"Set6\",\n \"Set7\",\n \"Set8\",\n \"Set9\",\n \"Set10\",\n \"Set11\",\n \"Set12\",\n \"Set13\",\n \"Set14\",\n \"Set15\",\n \"Set16\",\n \"Set17\",\n \"Set18\",\n \"Set19\",\n \"Set20\",\n \"Set21\",\n \"Set22\",\n \"Set23\",\n \"Set24\",\n \"Set25\",\n \"Set26\",\n \"Set27\",\n \"Set28\",\n \"demerit\",\n \"s0\",\n \"s1\",\n \"s2\",\n \"s3\",\n \"s4\",\n \"s5\",\n \"s6\",\n \"s7\",\n \"s8\",\n \"s9\",\n \"s10\",\n \"s11\",\n \"s12\",\n \"s13\",\n \"s14\",\n \"s15\",\n \"s16\",\n \"s17\",\n \"s18\",\n \"s19\",\n \"s20\",\n \"s21\",\n \"s22\",\n \"s23\",\n \"s24\",\n \"s25\",\n \"s26\",\n \"s27\",\n \"s28\",\n \"set2Adj\",\n \"set3Adj\",\n \"set4Adj\",\n \"set5Adj\",\n \"set9Adj\",\n \"set13Adj\",\n \"set23Adj\",\n \"Cred.Code\",\n \"hw\",\n \"final\",\n \"course\",\n \"letter\",\n \"Comment\"])\n\ngrades = grades[grades.course.apply(lambda x: pd.notnull(x))]\ndel grades['dropcol']", | |
"prompt_number": 3, | |
"outputs": [], | |
"language": "python", | |
"trusted": true, | |
"collapsed": false | |
}, | |
{ | |
"metadata": {}, | |
"cell_type": "markdown", | |
"source": "### Feature engineering" | |
}, | |
{ | |
"metadata": {}, | |
"cell_type": "code", | |
"input": "# limit dataframe to \"good\" rows\ngraded = set(grades.userId.values)\nevents = events[(events.activityType != 'DISCUSS') & \n (events.eventType != 'OPENED') &\n (events.timeMinutes.apply(lambda x: pd.notnull(x))) &\n (events.userId.apply(lambda x: x in graded))]", | |
"prompt_number": 4, | |
"outputs": [], | |
"language": "python", | |
"trusted": true, | |
"collapsed": false | |
}, | |
{ | |
"metadata": {}, | |
"cell_type": "code", | |
"input": "# day of week lookup dict\nday_of_week = {0: 'Monday',\n 1: 'Tuesday',\n 2: 'Wednesday',\n 3: 'Thursday',\n 4: 'Friday',\n 5: 'Saturday',\n 6: 'Sunday'}\nalt_dow = {i: 'day_%d' % i for i in range(7)}\n\n# calculate time features\ntotal_time = events.groupby('userId').timeMinutes.sum()\nday_time = events.groupby(['userId',events.updatedAt.apply(lambda x: alt_dow[x.dayofweek])]).timeMinutes.sum().unstack()\nevent_time = events.groupby(['userId','eventType']).timeMinutes.sum().unstack()\nactivity_time = events.groupby(['userId',events.activityType.apply(lambda x: 'WATCH' if x == 'LISTEN' else x)]).timeMinutes.sum().unstack()\n\n# create full dataframe\ntrain_features = pd.DataFrame(total_time).join([day_time,event_time,activity_time]).fillna(0)\n\n# calculate percents\nfor feat in train_features.keys():\n if feat != 'timeMinutes':\n train_features[feat] = train_features[feat] / train_features.timeMinutes\n\ndel train_features['timeMinutes']", | |
"prompt_number": 5, | |
"outputs": [], | |
"language": "python", | |
"trusted": true, | |
"collapsed": false | |
}, | |
{ | |
"metadata": {}, | |
"cell_type": "code", | |
"input": "# assignment behavior features\nsubmits = events[(events.activityType == 'ASSIGNMENT') & \n (events.eventType == 'CLOSED') & \n (events.anchorValue.apply(lambda x: pd.isnull(x))) &\n (events.scorePercent.apply(lambda x: pd.notnull(x))) &\n ((events.scorePercent + events.timeMinutes).apply(lambda x: x > 0))][['userId','updatedAt','topicTitle','timeMinutes','scorePercent']]\n\navg_submit = pd.DataFrame(submits.groupby('userId').topicTitle.count() / submits.groupby('userId').topicTitle.nunique())\navg_submit.columns = ['submits']\n\ntrain_features = train_features.join(avg_submit)", | |
"prompt_number": 6, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stderr", | |
"text": "/Users/jost/courses/mlined/env/lib/python2.7/site-packages/numexpr/necompiler.py:742: DeprecationWarning: using `oa_ndim == 0` when `op_axes` is NULL is deprecated. Use `oa_ndim == -1` or the MultiNew iterator for NumPy <1.8 compatibility\n return compiled_ex(*arguments, **kwargs)\n" | |
} | |
], | |
"language": "python", | |
"trusted": true, | |
"collapsed": false | |
}, | |
{ | |
"metadata": {}, | |
"cell_type": "code", | |
"input": "# Yu's video features\nyu_events = events[(events.activityType == 'WATCH') | (events.activityType == 'LISTEN')]\n \n# Counting the number of video accessed by each user\nvideo_map = yu_events.groupby(['userId', 'topicId']).size().unstack().fillna(value=0)\nuser_video = video_map.applymap((lambda x: 1 if x > 0 else 0)).sum(axis=\"columns\")\nuser_video = pd.DataFrame(user_video, columns=['VideoAccessed'])\n \n# Counting the number of suspension\nuser_eventType = yu_events.groupby(['userId', 'eventType']).size().unstack()\nuser_suspended = user_eventType[['SUSPENDED']].fillna(value=0)\n \n# Merge VideoAccessed and NumSuspension, then calculate the average number of suspension per video\nuser_data = user_video.join(user_suspended)\nuser_data = user_data[user_data.VideoAccessed > 0]\nuser_data['SuspensionPerVideo'] = user_data['SUSPENDED'] / user_data['VideoAccessed']\n \n# Merge grades\nuser_data = user_data.sort(columns='VideoAccessed')\n \n# Merge stuff\ntrain_features = train_features.join(user_data[['SuspensionPerVideo', 'VideoAccessed']]).fillna(value=0)", | |
"prompt_number": 7, | |
"outputs": [], | |
"language": "python", | |
"trusted": true, | |
"collapsed": false | |
}, | |
{ | |
"metadata": {}, | |
"cell_type": "code", | |
"input": "# z-score columns\nfor feat in train_features.keys():\n train_features[feat] = stats.mstats.zscore(train_features[feat])", | |
"prompt_number": 8, | |
"outputs": [], | |
"language": "python", | |
"trusted": true, | |
"collapsed": false | |
}, | |
{ | |
"metadata": {}, | |
"cell_type": "markdown", | |
"source": "### Clustering" | |
}, | |
{ | |
"metadata": {}, | |
"cell_type": "code", | |
"input": "numclus = 3\nmodel = SpectralBiclustering(n_clusters=numclus, method='log', random_state=0)\nmodel.fit(train_features)", | |
"prompt_number": 9, | |
"outputs": [], | |
"language": "python", | |
"trusted": true, | |
"collapsed": false | |
}, | |
{ | |
"metadata": {}, | |
"cell_type": "code", | |
"input": "c = Counter(model.row_labels_)\nprint c", | |
"prompt_number": 10, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": "Counter({0: 153, 1: 50, 2: 48})\n" | |
} | |
], | |
"language": "python", | |
"trusted": true, | |
"collapsed": false | |
}, | |
{ | |
"metadata": {}, | |
"cell_type": "code", | |
"input": "zip(train_features.keys(),model.column_labels_)", | |
"prompt_number": 11, | |
"outputs": [ | |
{ | |
"output_type": "pyout", | |
"prompt_number": 11, | |
"metadata": {}, | |
"text": "[('day_0', 0),\n ('day_1', 1),\n ('day_2', 0),\n ('day_3', 0),\n ('day_4', 1),\n ('day_5', 1),\n ('day_6', 1),\n ('CLOSED', 0),\n ('SUSPENDED', 2),\n ('WORKED', 2),\n ('ASSIGNMENT', 0),\n ('PRACTICE', 2),\n ('READ', 2),\n ('WATCH', 2),\n ('submits', 1),\n ('SuspensionPerVideo', 2),\n ('VideoAccessed', 2)]" | |
} | |
], | |
"language": "python", | |
"trusted": true, | |
"collapsed": false | |
}, | |
{ | |
"metadata": {}, | |
"cell_type": "code", | |
"input": "clus_df = pd.concat([train_features,pd.DataFrame({'clus': model.row_labels_}, index=train_features.index)],axis=1)\n\nprint \"Average course grade by cluster\"\nprint clus_df.reset_index().merge(grades[['userId','course','letter']], on=['userId']).groupby(['clus']).course.mean()\na = clus_df.groupby('clus').mean().T.plot(figsize=(15,numclus*3), ylim=(-3,3), subplots=True, kind='bar')", | |
"prompt_number": 12, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": "Average course grade by cluster\nclus\n0 67.004311\n1 79.724263\n2 74.836960\nName: course, dtype: float64\n" | |
}, | |
{ | |
"output_type": "display_data", | |
"metadata": {}, | |
"png": "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\nAAAASUVORK5CYII=\n", | |
"text": "<matplotlib.figure.Figure at 0x11ec75510>" | |
} | |
], | |
"language": "python", | |
"trusted": true, | |
"collapsed": false | |
}, | |
{ | |
"metadata": {}, | |
"cell_type": "markdown", | |
"source": "### Regression for top resources while working on assignment\nLooking only at each student's max grade on the assignment" | |
}, | |
{ | |
"metadata": {}, | |
"cell_type": "code", | |
"input": "# limit events to listening/watching, practice, and reading activities\ndef retitle(df):\n newTitle = df.activityType + ': '\n if df.topicTitle != df.activityTitle:\n if df.activityTitle[:8] == 'Exercise' or 'Example' in df.activityTitle:\n newTitle += df.activityTitle + ': ' + df.topicTitle\n else:\n newTitle += df.topicTitle + ': ' + df.activityTitle\n else:\n newTitle += df.topicTitle\n return newTitle\n\nevents_j = events[events.activityType.apply(lambda x: x in ['LISTEN','PRACTICE','READ','WATCH'])]\nevents_j['resource'] = events_j.apply(retitle, axis=1)\nevents_j['startedAt'] = events_j.apply(lambda df: df.updatedAt - np.timedelta64(int(df.timeMinutes),'m'), axis=1)\nevents_j = events_j[['userId',\n 'updatedAt',\n 'startedAt',\n 'activityType',\n 'timeMinutes',\n 'anchorValue',\n 'resource']]", | |
"prompt_number": 13, | |
"outputs": [], | |
"language": "python", | |
"trusted": true, | |
"collapsed": false | |
}, | |
{ | |
"metadata": {}, | |
"cell_type": "code", | |
"input": "# cartesian join in all resource events to submits data\nsubmits['startedAt'] = submits.apply(lambda df: df.updatedAt - np.timedelta64(int(df.timeMinutes),'m'), axis=1)\n\nsubmits_j = pd.merge(submits, events_j, on=['userId'])\nsubmits_j.rename(columns={'updatedAt_x':'updatedAt'}, inplace=True)\nprint submits_j.shape", | |
"prompt_number": 14, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": "(16092690, 12)\n" | |
} | |
], | |
"language": "python", | |
"trusted": true, | |
"collapsed": false | |
}, | |
{ | |
"metadata": {}, | |
"cell_type": "code", | |
"input": "# select \"good\" resource usage events and create user/assignment vs resource usage matrix\ngood_idx = ((submits_j.startedAt_y < submits_j.updatedAt) & \\\n (submits_j.startedAt_x < submits_j.updatedAt_y))\nresources = submits_j[good_idx].groupby(['userId','topicTitle','resource']).timeMinutes_y.sum().unstack().fillna(0)\nresource_list = resources.columns", | |
"prompt_number": 15, | |
"outputs": [], | |
"language": "python", | |
"trusted": true, | |
"collapsed": false | |
}, | |
{ | |
"metadata": {}, | |
"cell_type": "code", | |
"input": "# get assignment grades to join in\nsubmits_g = pd.DataFrame(submits.groupby(['userId','topicTitle']).scorePercent.max())", | |
"prompt_number": 16, | |
"outputs": [], | |
"language": "python", | |
"trusted": true, | |
"collapsed": false | |
}, | |
{ | |
"metadata": {}, | |
"cell_type": "code", | |
"input": "resources = resources.join(submits_g).join(clus_df[['clus']], how='inner').reset_index()\nresources[resources.topicTitle.apply(lambda x: 'Assignment' in x)].groupby('topicTitle').size()", | |
"prompt_number": 17, | |
"outputs": [ | |
{ | |
"output_type": "pyout", | |
"prompt_number": 17, | |
"metadata": {}, | |
"text": "topicTitle\nCHAPTER 0 Assignment: Introduction 131\nCHAPTER 1 Assignment: Preface 41\nCHAPTER 10 Assignment: The Meaning of Probability: Theories of Probability 78\nCHAPTER 11 Assignment: Set Theory: The Language of Probability 72\nCHAPTER 12 Assignment: Categorical Logic 13\nCHAPTER 13 Assignment: Propositional Logic 70\nCHAPTER 14 Assignment: Probability: Axioms and Fundament 57\nCHAPTER 15 Assignment: The \"Let's Make a Deal\" (Monty Hall) Problem 55\nCHAPTER 16 Assignment: Probability Meets Data 67\nCHAPTER 17 Assignment: Random Variables and Discrete Distributions 55\nCHAPTER 18 Assignment: The Long Run and the Expected Value 56\nCHAPTER 19 Assignment: Standard Error 58\nCHAPTER 2 Assignment: Reasoning and Fallacies 121\nCHAPTER 20 Assignment: The Normal Curve, The Central Limit Theorem, and Markov's and Chebychev's Inequalities for Random Variables 58\nCHAPTER 21 Assignment: Sampling 59\nCHAPTER 22 Assignment: Estimating Parameters from Simple Random Samples 55\nCHAPTER 23 Assignment: Confidence Intervals 44\nCHAPTER 24 Assignment: Hypothesis Testing - Does Chance Explain the Results? 45\nCHAPTER 25 Assignment: Does Treatment Have an Effect? 37\nCHAPTER 26 Assignment: Testing Equality of Two Percentages 8\nCHAPTER 27 Assignment: Approximate Hypothesis Tests: the z Test and the t Test 4\nCHAPTER 28 Assignment: The Multinomial Distribution and the Chi-Squared Test for Goodness of Fit 2\nCHAPTER 3 Assignment: Statistics 112\nCHAPTER 4 Assignment: Measures of Location and Spread 117\nCHAPTER 5 Assignment: Multivariate Data and Scatterplots 100\nCHAPTER 6 Assignment: Correlation and Association 96\nCHAPTER 7 Assignment: Regression 86\nCHAPTER 8 Assignment: Errors in Regression 98\nCHAPTER 9 Assignment: Counting 83\ndtype: int64" | |
} | |
], | |
"language": "python", | |
"trusted": true, | |
"collapsed": false | |
}, | |
{ | |
"metadata": {}, | |
"cell_type": "code", | |
"input": "assign_name = 'CHAPTER 11 Assignment: Set Theory: The Language of Probability'\nregmodel = LinearRegression()\n\nfor i in range(3):\n regmodel.fit(resources[(resources.topicTitle == assign_name) &\n (resources.clus == i)][resource_list],\n resources[(resources.topicTitle == assign_name) &\n (resources.clus == i)][['scorePercent']])\n print 'CLUSTER %d' % i\n for n, c in sorted(zip(resource_list,regmodel.coef_.flatten()), key=lambda x: x[1], reverse=True)[:10]:\n n = n.replace(': Set Theory: The Language of Probability Introduction','')\n print '%s (%g)' % (n, c)\n print\n print", | |
"prompt_number": 21, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": "CLUSTER 0\nWATCH: CHAPTER 11 Introduction: Set Theory: The Language of Probability (13.9623)\nWATCH: CHAPTER 13 Introduction: Propositional Logic: CHAPTER 13: Propositional Logic Introduction (0.662417)\nREAD: CHAPTER 14 Summary: Probability: Axioms and Fundaments: Probability: Axioms and Fundaments Summary (0.216791)\nREAD: Naive Set Theory (0.123823)\nREAD: Logical Operations (0.0993626)\nREAD: The Multiplication Rule (0.0993626)\nREAD: CHAPTER 11 Summary: Set Theory: The Language of Probability: Summary (0.0042435)\nLISTEN: An Example of Exercise 15-4: The \"Let's Make a Deal\" (Monty Hall) Problem Conclusions (1.12459e-13)\nLISTEN: Affine transformations: Affine Transformations (7.9492e-14)\nLISTEN: An Example of Exercise 18-7: Expected Values of Some Common Distributions (9.65894e-15)\n\n\nCLUSTER 1\nWATCH: CHAPTER 13 Introduction: Propositional Logic: CHAPTER 13: Propositional Logic Introduction (146.349)\nWATCH: CHAPTER 11 Introduction: Set Theory: The Language of Probability (19.6839)\nWATCH: Valid Arguments Versus Sound Arguments (4.29493)\nREAD: Logical Operations (3.83504)\nWATCH: CHAPTER 10 Summary: The Meaning of Probability: Theories of Probability: Summary (2.94337)\nWATCH: Example 10-1: Probability of winning the Lotto Jackpot: Theories of Probability Exercises (1.71696)\nPRACTICE: Exercise 10-6: Theories of Probability Exercises (1.47168)\nREAD: CHAPTER 13 Introduction: Propositional Logic: Propositional Logic Introduction (1.4434)\nREAD: CHAPTER 11 Introduction: Set Theory: The Language of Probability (0.428089)\nREAD: Conditional Probability (0.377932)\n\n\nCLUSTER 2\nWATCH: CHAPTER 11 Introduction: Set Theory: The Language of Probability (1.96433)\nREAD: CHAPTER 19 Introduction: Standard Error (1.51381)\nPRACTICE: Exercise 11-6: Connecting Probability to Set Theory (0.851519)\nREAD: CHAPTER 13 Introduction: Propositional Logic: Propositional Logic Introduction (0.720175)\nPRACTICE: Exercise 11-8: Connecting Probability to Set Theory (0.412858)\nPRACTICE: Exercise 11-7: Connecting Probability to Set Theory (0.3323)\nREAD: Naive Set Theory (0.0692065)\nREAD: CHAPTER 11 Introduction: Set Theory: The Language of Probability (0.0452696)\nREAD: CHAPTER 15 Introduction: \"The Let's Make a Deal\" (Monty Hall) Problem (0.041926)\nREAD: CHAPTER 14 Summary: Probability: Axioms and Fundaments: Probability: Axioms and Fundaments Summary (0.000295461)\n\n\n" | |
} | |
], | |
"language": "python", | |
"trusted": true, | |
"collapsed": false | |
}, | |
{ | |
"metadata": {}, | |
"cell_type": "code", | |
"input": "", | |
"outputs": [], | |
"language": "python", | |
"trusted": true, | |
"collapsed": false | |
} | |
], | |
"metadata": {} | |
} | |
], | |
"metadata": { | |
"gist_id": "8bf5aad33df4d2917de1", | |
"name": "", | |
"signature": "sha256:7685599b7c67e75906115444bf821c788d56e0362b2baef955e7b96d2df7e51a" | |
}, | |
"nbformat": 3 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment