<?xml version="1.0" encoding="utf-8"?>
<!-- generator="Kirby" -->
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom">

  <channel>
    <title>Tag: python &#183; Blog &#183; Liip</title>
    <link>https://www.liip.ch/en/blog/tags/python</link>
    <generator>Kirby</generator>
    <lastBuildDate>Thu, 16 Jun 2016 00:00:00 +0200</lastBuildDate>
    <atom:link href="https://www.liip.ch" rel="self" type="application/rss+xml" />

        <description>Liip blog articles tagged &#8220;python&#8221;</description>
    
        <language>en</language>
    
        <item>
      <title>A recommender system for Slack with Pandas &#38; Flask</title>
      <link>https://www.liip.ch/en/blog/recommender-system-slack-pandas-flask</link>
      <guid>https://www.liip.ch/en/blog/recommender-system-slack-pandas-flask</guid>
      <pubDate>Thu, 16 Jun 2016 00:00:00 +0200</pubDate>
      <description><![CDATA[<p>Recommender systems have been a pet peeve of me for a long time, and recently I thought why not use these things to make my life easier at liip. We have a great community within the company, where most of our communication takes place on <a href="https://slack.com/">Slack</a>. To the people born before 1990: Slack is something like irc channels only that you use it for your company and try to replace Email communication with it. (It is a quite debated topic if it is a good idea to <a href="https://m.signalvnoise.com/is-group-chat-making-you-sweat-744659addf7d">replace Email with Slack</a>)</p>
<p>So at liip we have a slack channel for everything, for #machine-learning (for topics related to machine learning), for #zh-staff (where Zürich staff announcments are made), for #lambda (my team slack channel) and so on. Everybody can create a Slack channel, invite people, and discuss interactively there. What I always found a little bit hard was «How do I know which channels to join?», since we have over 700 of those nowadays.</p>
<figure><a href="https://www.liip.ch/content/4-blog/20160616-recommender-system-slack-pandas-flask/Bildschirmfoto-2016-06-16-um-11.34.12.png"><img src="https://liip.rokka.io/www_inarticle/6dada2560e94c26d174c1cf51c3974492ad6b29a/bildschirmfoto-2016-06-16-um-11-34-12.jpg" alt="Bildschirmfoto 2016-06-16 um 11.34.12"></a></figure>
<p>Wouldn't it be cool if I had a tool that tells me, well if you like machine-learning why don't you join our #bi (Business Intelligence) channel? Since Slack does not have this built in, I thought lets build it and show you guys how to integrate the Slack-API, <a href="http://pandas.pydata.org/">Pandas</a> (a multipurpose data scientist tool), Flask (a tiny python web server) and Heroku (a place to host your apps).</p>
<p>These days there are myriads of <a href="https://www.amazon.de/Recommender-Systems-Handbook-Francesco-Ricci/dp/1489976361/ref=sr_1_1?ie=UTF8&amp;qid=1466066658&amp;sr=8-1&amp;keywords=recommender+systems+handbook">ways to build a recommender system</a> and there are lots of <a href="https://prediction.io">commercial</a> and <a href="https://github.com/amznlabs/amazon-dsstne">open source</a> <a href="http://mahout.apache.org/">solutions</a> out there already. There are recommenders that recommend based on contents of items (e.g. read this book because it is about snakes and planes) or there are solutions that recommend based purely on user behavior data (e.g. people who have bought this book have also bought this book). The latest ones are called collaborative filtering recommenders (fancy name) and we will build one of these since they are easy to build and work reasonably well.</p>
<p>Collaborative Filtering approaches can be divided into two main approaches: user-item filtering and item-item filtering. A user-item filtering will take a particular user, find users that are similar to that user, based on similarity of ratings, and recommend items that those similar users liked. In contrast, item-item filtering will take an item, find users who liked that item and find other items that those users or similar users also liked. It takes items and outputs other items as recommendations.</p>
<p>What does this mean for Slack for us? Well in an item-item approach we might say give me “channels that are similar to machine-learning”. The algorithm will then look who joined this channel and look if there are channels that have been joined by exactly the same people. If that is the case then those channels might be somewhat related. In a user-user approach, we try to recommend a channel to a particular user. So we look through all users and look for the ones that have joined the same channels as our user joined. Then look if there are some channels among those that our user has not joined yet. These ones might be interesting for him.</p>
<p>There are myriads or better blog articles that do a great job explaining in detail on «How to build a recommender in Python» – I think I should at least list a couple of those ( <a href="http://spectrum.ieee.org/computing/software/deconstructing-recommender-systems">Deconstructing Recommender Systems</a> by Spectrum, <a href="http://online.cambridgecoding.com/notebooks/eWReNYcAfB/implementing-your-own-recommender-systems-in-python-2">Implementing your own recommender in Python</a> by online Cambridge coding, <a href="http://www.salemmarafi.com/code/collaborative-filtering-with-python/">Collaborative Filtering with python</a> by Salem Marafi). There are also a couple of nice Ipython notebooks that you can download and play along ( <a href="http://nbviewer.jupyter.org/github/marcelcaraciolo/big-data-tutorial/blob/master/tutorial/1-Playing-with-Recommender-Systems.ipynb">Playing with recommender systems</a>). If you want to know what the people are doing and who is creating state-of-the-art recommender systems you should visit the <a href="https://recsys.acm.org/recsys15/">Recsys conference</a>. You can also download tons of academic papers on <a href="http://yifanhu.net/PUB/cf.pdf">how different recommender systems perform</a> and why some are better than others in different scenarios. There is even a great <a href="https://www.coursera.org/learn/recommender-systems">coursera</a> course on recommenders by Joseph Konstan that I highly recommend. But for the sake of brevity, we can not go into all the details here, we just want to get you started. Right?</p>
<p>What it boils down to is that in our case for Slack you need to construct a matrix of users x channels. If you have a matrix that has users x items, you have a setup that is called “item-item collaborative filtering”, if you rotate this matrix 90 degrees and have a matrix that has items x users you have an user-user collaborative filtering. It is as easy as that. I apologize for stealing those two great images from this <a href="http://online.cambridgecoding.com/notebooks/eWReNYcAfB/implementing-your-own-recommender-systems-in-python-2">great blog post of online Cambridge coding</a>, but they show nicely how things work.</p>
<figure><a href="https://www.liip.ch/content/4-blog/20160616-recommender-system-slack-pandas-flask/BLOG_CCA_10-2.png"><img src="https://liip.rokka.io/www_inarticle/5462069c208b569aa45bf9ea384369a8e8872f77/blog-cca-10-2.jpg" alt="BLOG_CCA_10-2"></a></figure>
<figure><a href="https://www.liip.ch/content/4-blog/20160616-recommender-system-slack-pandas-flask/BLOG_CCA_11-2.png"><img src="https://liip.rokka.io/www_inarticle/0e575a55ff1076359ddde8fdcd5f806fb7da6d94/blog-cca-11-2.jpg" alt="BLOG_CCA_11-2"></a></figure>
<h3>Step 1: Getting the data</h3>
<p>So in order to generate the needed data, just create a <a href="https://github.com/dblock/slack-ruby-client">Slack-client</a> give it some key that you will get from Slack and let it go through all the channels and note down which person is in which channel. Furthermore write down a 1 if a person is in a channel, write down a 0 when not.</p>
<p>Once we have our data we can start working. We will first read in the data into pandas and display it. It is basically two lines of code and you will see the nice matrix unfolding. Notice that we are really working on a tiny dataset here, that's why it is perfectly ok to do everything in memory. But once you have a matrix consisting of millions of row things start to become interesting.</p>
<figure><a href="https://www.liip.ch/content/4-blog/20160616-recommender-system-slack-pandas-flask/Bildschirmfoto-2016-06-16-um-10.51.32.png"><img src="https://liip.rokka.io/www_inarticle/b0b1e8f028143e9973974951deae5310829473f3/bildschirmfoto-2016-06-16-um-10-51-32-1024x363.jpg" alt="Bildschirmfoto 2016-06-16 um 10.51.32"></a></figure>
<h3>Step2: Computing the distances</h3>
<p>In order to know which channels are similar to which other channels, we have to look at those user vectors for each channel, and see if there is another channel for which the same kind of users have also joined. Those channels must have something in common. Now there are myriads of different metrics on «how to compute a similarity between two vectors?», like <a href="https://en.wikipedia.org/wiki/Pearson_product-moment_correlation_coefficient">pearson-correlation</a>, <a href="https://en.wikipedia.org/wiki/Jaccard_index">jaccard-distance</a>, <a href="https://de.wikipedia.org/wiki/Manhattan-Metrik">manhattan-metric</a>, or <a href="https://en.wikipedia.org/wiki/Cosine_similarity">cosine similarity</a>. Just pick one. They all have their strengths and weaknesses. For this experiment I went for cosine-similarity. Doing this in Pandas is really easy. Only 4 lines of code and you will have this:</p>
<figure><a href="https://www.liip.ch/content/4-blog/20160616-recommender-system-slack-pandas-flask/Bildschirmfoto-2016-06-16-um-09.21.37.png"><img src="https://liip.rokka.io/www_inarticle/9101a0406196ca7cd59976a4088a4d24c81e45c0/bildschirmfoto-2016-06-16-um-09-21-37-1024x492.jpg" alt="Bildschirmfoto 2016-06-16 um 09.21.37"></a></figure>
<p>Isn't that great?! We now have a matrix that shows how similar each channel is to the other ones. To make a recommendation we have to look up for a certain channel which other channels have the highest number in that row and we are done.</p>
<h3>Step3: Making a recommender</h3>
<p>So, to make a recommendation we look for the row matching the channel name and then sort the columns by value and remove one entry. Namely the channel itself, because we know it is similar to itself :). We then output, for example, the 5 highest numbers. Again, this can be done with 4 lines of code in Pandas. You just have to love this thing! See below:</p>
<figure><a href="https://www.liip.ch/content/4-blog/20160616-recommender-system-slack-pandas-flask/Bildschirmfoto-2016-06-16-um-09.24.28.png"><img src="https://liip.rokka.io/www_inarticle/57722ca55121d5cf37af231d5fb5f1dc2cf962a5/bildschirmfoto-2016-06-16-um-09-24-28-1024x433.jpg" alt="Bildschirmfoto 2016-06-16 um 09.24.28"></a></figure>
<p>Well, there we have it: apparently if I go to the channel #machine-learning I should also visit #bi and #beekeping. Our company has a weird humor when it comes to naming things. :) I would have never guessed a second, going simply by name. So what is next you ask? Well, it is time to take those results and make them work for the company. At this point we will skip the part where I show you «how to recommend channels for users» or «how to compute users that are similar to each other» or «how to evaluate the results» (In real life, problem evaluations of recommenders is a serious problem and should be definitely part of your approach).</p>
<h3>Step4: Build a service out of it</h3>
<p>What normally happens it that our precious models and results end up rotting away on our laptop, because we have no time, budget, or priority to turn them into actionable artifacts. But I think this is actually the most important step for a data scientist.</p>
<p>Make sure that your results are understandable and communicate them to people that might find them useful. Make sure you are actually going to act on those results, because that is where you actually helping people. So I thought we must turn this tiny recommender into a website in our company where everybody can get their own recommendations.</p>
<p>That's where <a href="http://flask.pocoo.org">F</a> <a href="http://flask.pocoo.org">lask</a> helps us. The good thing about Flask is that our recommender code is written in Python and the web server is in Python too, so we can simply cut the code from our notebook and paste it into our web server. This makes our life very easy because normally at this point data scientists struggle because other engineers have to implement their shiny and fancy solution in another programming language. That takes time, lots of swearing from the developers and creates lots of <a href="http://blog.yhat.com/posts/five-commandments.html">headaches</a> for the data scientist. So my approach uses the same programming language across the whole stack. Then you should be fine. Well, indeed you can create an endpoint in Flask that takes a channel_id and runs your recommender code with it and returns the results as a JSON back to the frontend. You should recognize the same code above in the ipython notebook and here below:</p>
<figure><a href="https://www.liip.ch/content/4-blog/20160616-recommender-system-slack-pandas-flask/Bildschirmfoto-2016-06-16-um-10.07.32.png"><img src="https://liip.rokka.io/www_inarticle/24a403e7b81d23f2e78dc53dfc989ca0316aae31/bildschirmfoto-2016-06-16-um-10-07-32-1024x319.jpg" alt="Bildschirmfoto 2016-06-16 um 10.07.32"></a></figure>
<h3>Step 5: Make it look fancy</h3>
<p>The last remaining step is to create a nice looking GUI for the recommender where the users can select either a channel or a username. I have also implemented a goofy friend finder, that lists persons that seem to have the similar interests on Slack, based on what channels they use. So given the sea of messages, data and communication it seems to be useful having a tool that can help us out a bit. Now without further ado: I present to you the Liip Slack channel recommender:</p>
<figure><a href="http://still-coast-20794.herokuapp.com"><img src="https://liip.rokka.io/www_inarticle/bd3d67344b9aae7b52cd810ece4a0d882e52a187/bildschirmfoto-2016-06-16-um-10-32-59-e1466067888763.jpg" alt="recommender"></a></figure>
<p>A screenshot of the tool</p>
<p>The only thing left is to push it to Heroku or Cloudfoundry or the provider of your choice. It really makes your life easier if you control the deployment process because this way you can iterate on your model easily without asking your sysops for permission. (Of course, if a big system depends on your algorithm you should get serious about testing, fault tolerance, SLAs and all of that grow up stuff).</p>
<p>If you feel like you have liked the solution drop me a line, and we can send you the code to create this solution for yourself or just talk to us and we will think of something on «how implement recommenders or similar for your slack channels or your people directory». After all, I think these days it is time to not only build good looking, stable, fast and easy to use – but also smart data-driven websites.</p>
<p>If you are a Liiper reading this: click here to login into the recommender. PW/Login are available on #announcements. :)</p>]]></description>
                  <enclosure url="http://liip.rokka.io/www_card_2/90b7ad/color-pencils-colored-pencils-colorful-50996.jpg" length="2037975" type="image/jpeg" />
          </item>
        <item>
      <title>Get started exploring Google Analytics data with Python Pandas</title>
      <link>https://www.liip.ch/en/blog/exploring-google-analytics-data-with-python-pandas</link>
      <guid>https://www.liip.ch/en/blog/exploring-google-analytics-data-with-python-pandas</guid>
      <pubDate>Mon, 01 Feb 2016 00:00:00 +0100</pubDate>
      <description><![CDATA[<p>The latest release of <a href="http://pandas.pydata.org/">Pandas</a> (v0.17.1) has brought the deprecation of the Google Analytics data reader submodule (pandas.io.ga). This deprecation decision is actually good news since this submodule had dependencies on packages that are not currently python 3 compatible and was, even under python 2.7, hard to get up and running.</p>
<p>After updating my system to the newest versions of pandas, I had to find a new connector to fetch Google Analytics data, and found an advantageous replacement in the <a href="https://github.com/panalysis/Google2Pandas">google2pandas</a> module from <a href="http://panalysis.com/">Panalysis</a>.</p>
<p>This blogpost walks you through the setup of Pandas and google2pandas, and breifly introduces you to fetching and getting Google Analytics data into Pandas <a href="http://pandas.pydata.org/pandas-docs/stable/dsintro.html#dataframe">dataframes</a>, for further exploration with Pandas.</p>
<h2>Installation</h2>
<p><em>The following instructions are aimed at OSX and Linux system users.</em></p>
<ol>
<li>
<p><strong>Download and install Anaconda</strong>  by following the <a href="https://www.continuum.io/downloads">official instructions</a>. Although your machine might already have a Python copy pre-installed, I recommend you install <a href="https://www.continuum.io/why-anaconda">Anaconda</a>, a bundle of 300+ data science tools that comes with its own package manager. When it comes to data analysis, one tool never fits all needs and with Anaconda, you get in the good company of so many of them. If you do not want to install the whole Anaconda, follow <a href="http://pandas.pydata.org/pandas-docs/version/stable/install.html">installation instructions for Pandas</a>.</p>
</li>
<li>
<p><strong>Install the connector module</strong>  and its dependencies:</p>
</li>
</ol>
<pre><code class="language-bash">pip install git+https://github.com/panalysis/Google2Pandas</code></pre>
<ol start="3">
<li><strong>Test both installations</strong>  on an interactive python environment, the following statement should run quietly and not throw any <code>ImportError</code>:</li>
</ol>
<pre><code class="language-python">import pandas
import google2pandas</code></pre>
<h2>Setting up the connection</h2>
<p>Now the tricky part: setting up the authorized connection to Google Analytics API.</p>
<ol>
<li><strong>Follow the step 1 in <a href="https://developers.google.com/analytics/devguides/reporting/core/v3/quickstart/installed-py#enable">the official instructions for installed apps</a></strong> .</li>
<li><strong>Create ‘ga-creds' directory</strong>  in your data analysis workspace/directory, and move in it the <code>client_secrets.json</code> you downloaded in the previous step. An alternative would bet to put those credentials in the <code>google2pandas</code> installation folder. I however recommend you save those credentials in a private project folder and always specify their path when establishing the connection (see how below). That will allow you to reinstall modules without loosing credentials and manage multiple credentials.</li>
<li><strong>Set correct permissions</strong> :</li>
</ol>
<pre><code class="language-bash">chmod 644 ga-creds/client_secrets.json</code></pre>
<ol start="4">
<li><strong>Save the following script in a file</strong>  (<code>ga-conn-init.py</code>):</li>
</ol>
<pre><code class="language-python">from google2pandas import *
conn = GoogleAnalyticsQuery(secrets='./ga-creds/client_secrets.json', token_file_name='./ga-creds/analytics.dat')</code></pre>
<ol start="5">
<li><strong>Run</strong> <code>python ga-conn-init.py</code>.</li>
</ol>
<p>A browser window should open, with a usual Google Account authentication process, plus asking permission to <em>View your Google Analytics data</em>. Please allow. Then the browser window redirected to a barebone page displaying: <em>The authentication flow has completed</em>. Were you to face a _no data received (ERR_EMPTY<em>RESPONSE)</em> page, try <code>python ga-conn-init.py --noauth_local_webserver</code>. If that also does not work, rerun the same command in another terminal window while the previous one is still running, this has worked for me.</p>
<ol start="6">
<li><strong>Check that it created the <code>ga-creds/analytics.dat</code> file</strong> .</li>
<li><strong>Adjust its permissions</strong> :</li>
</ol>
<pre><code class="language-bash">chmod 664 ga-creds/analytics.dat</code></pre>
<p>Take a deep breath. This authentication process done, you shouldn't need to do it again in a near future. Just remember to always point to both files when establishing connection.</p>
<h2>Fetching Google Analytics data</h2>
<h3>Basic query</h3>
<ol>
<li><strong>Go to Google Analytics</strong> , choose a view from which you want to import data, click on the admin tab <strong>and note down the view ID</strong> :</li>
<li><strong>Replace your VIEW-ID in the following lines and run them</strong> . That should print a tabular listing with 10 rows and data for the following columns: pageviews, data, pagePath.</li>
</ol>
<pre><code class="language-python">from google2pandas import *

conn = GoogleAnalyticsQuery(secrets='./ga-creds/client_secrets.json', token_file_name='./ga-creds/analytics.dat')

query = {\
  'ids' : 'VIEW-ID',
  'metrics' : 'pageviews',
  'dimensions' : ['date', 'pagePath'],
  'start_date' : '8daysAgo',
  'max_results' : 10
}

df, metadata = conn.execute_query(**query)
print(df)</code></pre>
<h3>Further queries</h3>
<p>Both the official Google Analytics Core Reporting API and the Google2Pandas module documentation and code can be useful ressources for expressing (complex) queries:</p>
<p>Google2pandas module:</p>
<ul>
<li><a href="https://github.com/panalysis/Google2Pandas/blob/master/google2pandas/_panalysis_ga.py#L119">module query parameters</a></li>
</ul>
<p>Google Analytics Core Reporting API Documentation:</p>
<ul>
<li><a href="https://developers.google.com/analytics/devguides/reporting/core/v3/reference#q_summary">API query parameters</a></li>
<li><a href="https://developers.google.com/analytics/devguides/reporting/core/dimsmets">Dimensions &amp; Metrics Explorer</a></li>
<li><a href="https://developers.google.com/analytics/devguides/reporting/core/v3/reference#filters">Using filter operators</a></li>
</ul>]]></description>
          </item>
        <item>
      <title>Good vibes at DjangoCon Europe 2015</title>
      <link>https://www.liip.ch/en/blog/good-vibes-at-djangocon-europe-2015</link>
      <guid>https://www.liip.ch/en/blog/good-vibes-at-djangocon-europe-2015</guid>
      <pubDate>Wed, 01 Jul 2015 00:00:00 +0200</pubDate>
      <description><![CDATA[<figure><img src="https://liip.rokka.io/www_inarticle/d9bd83e62de4da616c3be52203a9d6f279e42fce/18510465600-d9ebaecc2f-k-1024x252.jpg" alt="18510465600_d9ebaecc2f_k"></figure>
<p>Last year's DjangoCon Europe took place on its own island, and this time we were welcomed by the beautiful Cardiff University. One of the goals the organizers immediately set was to promote diversity and embrace minorities, encouraging them to participate to this event. I remember when I bought my ticket and I read “all dietary requirements can be met” and I thought “they're probably trying to set the bar too high”. This is a not so unusual statement, but when confronted to reality you usually end up with dishes not adapted to your dietary requirements, and, as a minority, having to ask for something special can really make you feel excluded. This time was different, as the organizers meticulously took care of that.</p>
<p>I talked about dietary requirements because it's an important topic for me, but they also made sure to have a <a href="http://2015.djangocon.eu/code-conduct/">code of conduct</a>, a financial assistance for people who want but can't afford to attend, a wellbeing service, a subscription system for meals to avoid wasting food, reusable aluminum bottles instead of plastic water bottles, live transcription of talks (for hard of hearing or non-english people), and even a crèche.</p>
<p>All of this was not just buzzwords but was carefully handled by the organizers. In the end, it made everyone feel welcome and put a very warm atmosphere to the event. Talking with people was very interesting and rewarding because of the incredible diversity of backgrounds. A few days after the conference the Django Software Foundation even released a <a href="https://www.djangoproject.com/diversity/">diversity statement</a> to make sure everyone feels welcome in the Django community.</p>
<p>The choice of talks was about 50/50 between technical talks and community talks. I found the community talks to be very inspiring such as Ola Sendecka's “ <a href="https://speakerdeck.com/asendecka/into-the-rabbit-hole">Into the rabbit hole</a>” which reminded me the benefits of the <a href="https://en.wikipedia.org/wiki/Pomodoro_Technique">Pomodoro technique</a> and pair programming. Also Adrienne Lowe's talk “Coding with knives” and Russell Keith-Magee's touching talk about burnout debunked the myth of the rock-star programmer, and how important it is to help people to get started on things they're not comfortable with.</p>
<p>I can't list all the talks I loved because there are way too many but among those I could find the slides for were Ana Balica's “ <a href="http://www.slideshare.net/AnaBalica/djangocon2015-demystifying-mixins-with-django">Demystifying mixins with Django</a>“, Erik Romijn's “ <a href="https://speakerdeck.com/erik/a-sincere-tale-of-django-developers-and-security">A sincere tale of Django, developers and security</a>“, Aaron Bassett's “ <a href="https://speakerdeck.com/aaronbassett/effortless-real-time-apps-in-django">Effortless real time apps in Django</a>“, James Bennett's “ <a href="https://s3.amazonaws.com/media.b-list.org/presentations/2015/djangoconeu/security.pdf">The net is dark and full of terrors</a>“, and of course Rae Knowler's “ <a href="https://speakerdeck.com/bellisk/hypothesis-randomised-testing-for-django">Randomised testing for Django with Hypothesis</a>“.</p>
<p>The 3 days of talks were followed by 2 days of sprints and this was a very good opportunity to dive into Django's code and start fixing things. The core developers did a good job at helping people setup a development environment and start hacking on the code. This was a very rewarding part of the conference as this allowed me to do my first pull requests on Django and Django CMS.</p>
<p>Thanks to the DjangoCon Europe team who did an amazing job at organizing this event. See you next year in Budapest!</p>]]></description>
          </item>
        <item>
      <title>EdX Open Source Platform</title>
      <link>https://www.liip.ch/en/blog/edx-open-source-platform</link>
      <guid>https://www.liip.ch/en/blog/edx-open-source-platform</guid>
      <pubDate>Mon, 05 May 2014 00:00:00 +0200</pubDate>
      <description><![CDATA[<h2>Why edX?</h2>
<p>Recently we decided to explore the edX platform. It's an open source Learning Management System (LMS) and authoring tool. EdX is one of the most popular MOOC platforms alongside Coursera and Udacity, but unlike the two others their code is open source and you can host your own MOOC platform. EdX has been created by MIT and Harvard and is listing other well known universities as contributors. Also, in September 2013, Google, who was previously experimenting its own LMS (Google Course Builder), decided to join the open edX platform as a contributor too. The platform is implemented mostly in Python and they created their own component architecture called XBlock (<a href="https://xblock.readthedocs.org/en/latest/">https://xblock.readthedocs.org/en/latest/</a>). On paper edX sounds great, but how does it compare to Moodle or Totara? Does it fulfill the criteria our clients are targeting?</p>
<h2>First steps</h2>
<p>Installing a local instance is fairly easy since they provide a vagrant box and the documentation is good. But on the other hand, you will need to run three different servers with three different port forwardings. One for the LMS, one for the CMS (authoring tool) and the last one for the forums (this one is written in Ruby). Moodle or Totara use the same tool for standard users and administrative users which can lead to a bad user experience. So having different tools can have advantages and disadvantages.</p>
<h2>Managing users</h2>
<p>One key feature Moodle and Totara are offering is the user management. This is also one of the first requests we usually receive when dealing with offers. With Moodle and Totara there are lots of ways to authenticate a user and also to enroll them to a course out of the box. You can also easily manage roles and create groups (even dynamic groups with Totara).</p>
<p>In edX a user can authenticate if he creates first an account on the platform but edX is built on Django so any authentication method from this framework should be available on edX too (e.g. LDAP authentication).</p>
<p>It was not so easy to find how you can restrict the access to a course, this seems to be feasible depending on different settings (they were not explained in the user documentation, but understandable from the code documentation). You can create groups but it's not clear yet if you can have groups platform-wide too.</p>
<p>Inside a course it's easy to manage your staff team, define your teaching assistants or other admin users. You can even add beta testers so that some students can test your course before its official public release. You can also have discussion moderators for your courses.</p>
<h2>Multilanguage</h2>
<p>Having the platform in several languages is possible, and courses in different languages too. But you cannot have the same course in different languages (which is the same for Moodle and Totara, you simply need to create a course for each language). A good and bad thing with the current state of internationalization is that it's a work in progress. It's bad because if you want a german edX platform, the translations are not finished yet. But it's good because there are working on it and plan to finish it for the end of second quarter 2014 and they have a translation tool where anyone can contribute (<a href="https://www.transifex.com/organization/open-edx">https://www.transifex.com/organization/open-edx</a>). By default, it would use the browser language, but if you're logged in you can also have a user language (at least it's configured that way on www.edx.org).</p>
<p>Hosting</p>
<p>Configuring manually your server to host an edX platform is really difficult, there are a lot of requirements and dependencies to install. For Debian some of them don't even have a package. But they provide a way to install it using Ansible requirements which seems quite easy to do. They also provide some script to execute update which is nice.</p>
<h2>Interaction between users</h2>
<p>Like on Moodle and Totara, you can have discussion forums for a course. There is a nice WYSIWYG editor with the possibility to preview your post first.</p>
<p>A nice feature of edX is the ability to comment any exercise or theory page and allowing others to upvote/report those. It's a pity though that the comments aren't ordered by upvotes by default.</p>
<p>Students can find study buddies using Meetup communities. EdX can also integrate Google Hangouts.</p>
<h2>Reporting</h2>
<p>EdX comes with basic reporting tools. One can generate for example the list of enrolled students and the grade reports. Compared with Totara's custom reports feature, edX has still plenty of room for improvement.</p>
<h2>User Interface</h2>
<p>Generally the interface looks very nice. The UX-UI concept is very strong and has a clear consistent interaction level. You can also implement custom themes as Stanford did for its own instance. Without going into details, it seems edX has a nice base theme and state-of-the-art Interaction Patterns but they don't have a responsive theme – only the home page is responsive.</p>
<h2>Learning experience</h2>
<p>The learning experience is appealing and has the same feel as new online platforms (team-treehouse, codeacadamy, …). Courses offer a lot of options out of the box: video integration (via Youtube), multiple question forms (radio buttons, checkboxes, dropdowns, text, maths inputs, …), Google Hangouts, discussions, text, announcements, integrating an Iframe, full-screen images, zoom images, imaged-mapped input, drag and drop answers, electrical schemas, LTI integration, … but there are bad things too.  For example, the grading system is not suitable for the usual Swiss grading system (grades from 1 to 6), it's apparently made for the American grading system (from F to A).</p>
<h2>Conclusion</h2>
<p>EdX does less things than Moodle but does them nicely. It's also better suited for open education which can be achieved in Moodle and Totara too but the user and learning experience seems to be better on edX. Sever configuration, user management, access restriction, internationalization and reporting, all those things are easier to set and ready to use out of the box with Moodle (reporting especially on Totara) and cannot be neglected. Some might say that Moodle does too many things but from a business point of view it's easier to adapt client's requests that way. Also the community around Moodle is bigger which is a great thing from a developer point of view. But to end on a positive note, edX provides a roadmap on what they are working or will work on, thus we will keep an eye on this innovative platform and check if their improvements could fit future client requests.</p>]]></description>
          </item>
    
  </channel>
</rss>
