Skip to content

Instantly share code, notes, and snippets.

@jasonost
Last active August 29, 2015 14:10
Show Gist options
  • Save jasonost/8bf5aad33df4d2917de1 to your computer and use it in GitHub Desktop.
Save jasonost/8bf5aad33df4d2917de1 to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"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