{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Citation Usage Event Data" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "# basic defaults, including study dates, common SQL exclusions and parquet files for anonymized data\n", "%run -i 'data-defaults.py'\n", "\n", "def get_stats(df,groupby):\n", " all_events_count = df['count'].sum()\n", " stats = df.groupby(groupby).agg(\n", " [('days','count'),\n", " ('total_events','sum'),\n", " 'mean', \n", " 'median', \n", " 'min', \n", " 'max', \n", " 'std', \n", " ('25%', lambda x: x.quantile(.25)), \n", " ('50%', lambda x: x.quantile(.5)), \n", " ('75%', lambda x: x.quantile(.75)),\n", " ('perc', lambda x: sum(x)/all_events_count)])\n", " stats.columns = stats.columns.droplevel()\n", " return stats.reset_index()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Overview" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Session count" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Distinct sessions: 72953065\n" ] } ], "source": [ "# citationusage sessions by date\n", "sessions_query = \"\"\"\n", "SELECT COUNT(DISTINCT session_id) AS distinct_sessions\n", "FROM citationusage\n", "WHERE wiki = 'enwiki'\n", "{}\n", "AND to_date(event_time) >= '{}'\n", "AND to_date(event_time) <= '{}'\n", "AND useragent_is_bot = FALSE\n", "\"\"\"\n", "sessions = spark.sql(sessions_query.format(event_exclusion_sql,start_date_string, end_date_string))\n", "print('Distinct sessions: ', sessions.toPandas()['distinct_sessions'].sum())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Events by date and type" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "# show citationusage events by date and type\n", "events_query = \"\"\"\n", "SELECT to_date(event_time) date, action AS eventType, COUNT(*) count\n", "FROM citationusage\n", "WHERE wiki = 'enwiki'\n", "{}\n", "AND to_date(event_time) >= '{}'\n", "AND to_date(event_time) <= '{}'\n", "AND useragent_is_bot = FALSE\n", "GROUP BY to_date(event_time), eventType\n", "ORDER BY to_date(event_time)\n", "\"\"\"\n", "\n", "events = spark.sql(events_query.format(event_exclusion_sql,start_date_string, end_date_string))\n", "events_rdd = events.rdd\n", "events_df = sqlContext.createDataFrame(events_rdd)\n", "events_pandas = events_df.toPandas()" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Total events: 113520376\n" ] }, { "data": { "text/html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
eventTypedaystotal_eventsmeanmedianminmaxstd25%50%75%perc
0extClick32506828871.583840e+06160188413360321782721128559.4187021498160.50160188416952990.446465
1fnClick32240745817.523307e+0575119264930086137849202.443384727962.257511927857710.212073
2fnHover32375904781.174702e+0612192578659281539108193622.4517381006661.75121925713409650.331134
3upClick3211724303.663844e+04270461993414962225622.25969723866.7527046373080.010328
\n", "
" ], "text/plain": [ " eventType days total_events mean median min max \\\n", "0 extClick 32 50682887 1.583840e+06 1601884 1336032 1782721 \n", "1 fnClick 32 24074581 7.523307e+05 751192 649300 861378 \n", "2 fnHover 32 37590478 1.174702e+06 1219257 865928 1539108 \n", "3 upClick 32 1172430 3.663844e+04 27046 19934 149622 \n", "\n", " std 25% 50% 75% perc \n", "0 128559.418702 1498160.50 1601884 1695299 0.446465 \n", "1 49202.443384 727962.25 751192 785771 0.212073 \n", "2 193622.451738 1006661.75 1219257 1340965 0.331134 \n", "3 25622.259697 23866.75 27046 37308 0.010328 " ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "print('Total events: ', events_pandas['count'].sum())\n", "get_stats(events_pandas,['eventType'])" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
eventTypeextClickfnClickfnHoverupClick
date
2019-03-2215642767253771131859149622
2019-03-23136939766772488314720342
2019-03-241509326750329101841123969
2019-03-251744801782508136552482990
2019-03-261701660737057134228528909
2019-03-271666356728824132189827761
2019-03-281611850705904126778725736
2019-03-291498888666005112257223467
2019-03-30133603264930086592819934
2019-03-31145875373636799908723209
2019-04-011696205786290134791764128
2019-04-021682662747037134773740231
2019-04-031670454738633138828227035
2019-04-041646892729689129596525781
2019-04-051569885698560116759823560
2019-04-06138460268649488407620321
2019-04-071509870774512101716425706
2019-04-081782721806068138170928268
2019-04-091737629785598135435727683
2019-04-101694997815365133079726776
2019-04-111652196769221132249625945
2019-04-121562013731778117452524225
2019-04-13137196171383988094621390
2019-04-141495978807770100084123310
2019-04-151715777818613134052527057
2019-04-161696712789199153910827887
2019-04-171668298775790126398937014
2019-04-181591918760815115998860986
2019-04-191502334762657100860261486
2019-04-20140235775205686956636189
2019-04-21145317181382492649538190
2019-04-221732916861378126929753323
\n", "
" ], "text/plain": [ "eventType extClick fnClick fnHover upClick\n", "date \n", "2019-03-22 1564276 725377 1131859 149622\n", "2019-03-23 1369397 667724 883147 20342\n", "2019-03-24 1509326 750329 1018411 23969\n", "2019-03-25 1744801 782508 1365524 82990\n", "2019-03-26 1701660 737057 1342285 28909\n", "2019-03-27 1666356 728824 1321898 27761\n", "2019-03-28 1611850 705904 1267787 25736\n", "2019-03-29 1498888 666005 1122572 23467\n", "2019-03-30 1336032 649300 865928 19934\n", "2019-03-31 1458753 736367 999087 23209\n", "2019-04-01 1696205 786290 1347917 64128\n", "2019-04-02 1682662 747037 1347737 40231\n", "2019-04-03 1670454 738633 1388282 27035\n", "2019-04-04 1646892 729689 1295965 25781\n", "2019-04-05 1569885 698560 1167598 23560\n", "2019-04-06 1384602 686494 884076 20321\n", "2019-04-07 1509870 774512 1017164 25706\n", "2019-04-08 1782721 806068 1381709 28268\n", "2019-04-09 1737629 785598 1354357 27683\n", "2019-04-10 1694997 815365 1330797 26776\n", "2019-04-11 1652196 769221 1322496 25945\n", "2019-04-12 1562013 731778 1174525 24225\n", "2019-04-13 1371961 713839 880946 21390\n", "2019-04-14 1495978 807770 1000841 23310\n", "2019-04-15 1715777 818613 1340525 27057\n", "2019-04-16 1696712 789199 1539108 27887\n", "2019-04-17 1668298 775790 1263989 37014\n", "2019-04-18 1591918 760815 1159988 60986\n", "2019-04-19 1502334 762657 1008602 61486\n", "2019-04-20 1402357 752056 869566 36189\n", "2019-04-21 1453171 813824 926495 38190\n", "2019-04-22 1732916 861378 1269297 53323" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "events_pandas.pivot(index='date', columns='eventType', values='count')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Events for WP:M pages with external links" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "# daily count of events for WP:M pages with external links over study period\n", "wpm_events_query = \"\"\"\n", "SELECT to_date(event_time) date, action AS eventType, COUNT(*) count\n", "FROM citationusage\n", "WHERE wiki = 'enwiki'\n", "AND page_id IN (SELECT page_id FROM ryanmax.population_wpm_pages_with_extlinks)\n", "{}\n", "AND day = {}\n", "AND month = {}\n", "AND year = {}\n", "AND useragent_is_bot = FALSE\n", "GROUP BY to_date(event_time), eventType\n", "ORDER BY to_date(event_time)\n", "\"\"\"\n", "\n", "wpm_events_rdd = sc.emptyRDD()\n", "for d in daterange(start_date, end_date):\n", " dt = date_to_dt(d)\n", " daily_wpm_events = spark.sql(\n", " wpm_events_query.format(event_exclusion_sql, d.day, d.month, d.year))\n", " wpm_events_rdd = wpm_events_rdd.union(daily_wpm_events.rdd)\n", "\n", "wpm_events_merged = sqlContext.createDataFrame(wpm_events_rdd)\n", "wpm_events = wpm_events_merged.toPandas()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### WP:M event summary" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Total events: 3322871\n" ] }, { "data": { "text/html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
eventTypedaystotal_eventsmeanmedianminmaxstd25%50%75%perc
0extClick3282598125811.9062527276.518382305934193.17803121741.5027276.529271.750.248575
1fnClick3288766227739.4375028612.022608311222626.22333425830.7528612.029741.750.267137
2fnHover32155996548748.9062548772.532894602698621.97344041783.5048772.556687.500.469463
3upClick32492631539.46875913.5621125802227.803402820.00913.51132.250.014825
\n", "
" ], "text/plain": [ " eventType days total_events mean median min max \\\n", "0 extClick 32 825981 25811.90625 27276.5 18382 30593 \n", "1 fnClick 32 887662 27739.43750 28612.0 22608 31122 \n", "2 fnHover 32 1559965 48748.90625 48772.5 32894 60269 \n", "3 upClick 32 49263 1539.46875 913.5 621 12580 \n", "\n", " std 25% 50% 75% perc \n", "0 4193.178031 21741.50 27276.5 29271.75 0.248575 \n", "1 2626.223334 25830.75 28612.0 29741.75 0.267137 \n", "2 8621.973440 41783.50 48772.5 56687.50 0.469463 \n", "3 2227.803402 820.00 913.5 1132.25 0.014825 " ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# summary of events for WP:M pages with external links\n", "print('Total events: ', wpm_events['count'].sum())\n", "get_stats(wpm_events,['eventType'])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### WP:M daily events" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
eventTypeextClickfnClickfnHoverupClick
date
2019-03-222713027753473755851
2019-03-23204712385237786683
2019-03-24233752698744589896
2019-03-253039829599593351235
2019-03-263056830422602691051
2019-03-27297073074159600971
2019-03-28296822929856639929
2019-03-29245272575246813830
2019-03-30186472260836714659
2019-03-31216742527542956799
2019-04-012913529591568331391
2019-04-023033030050585451442
2019-04-03289042910357382865
2019-04-04284972804154026860
2019-04-05252182585747214730
2019-04-06193732351035657700
2019-04-07217642629942046916
2019-04-082988530308582231098
2019-04-093059331122583661077
2019-04-10298143088355613911
2019-04-11285812939553284880
2019-04-12252862692546673762
2019-04-13188062265435298705
2019-04-14214492615640996827
2019-04-15287712963954695969
2019-04-162843830080547991014
2019-04-17282182900652183886
2019-04-182626228218471421872
2019-04-1925757294883972712580
2019-04-20183822349432894621
2019-04-211891625155361231435
2019-04-222742330401501702818
\n", "
" ], "text/plain": [ "eventType extClick fnClick fnHover upClick\n", "date \n", "2019-03-22 27130 27753 47375 5851\n", "2019-03-23 20471 23852 37786 683\n", "2019-03-24 23375 26987 44589 896\n", "2019-03-25 30398 29599 59335 1235\n", "2019-03-26 30568 30422 60269 1051\n", "2019-03-27 29707 30741 59600 971\n", "2019-03-28 29682 29298 56639 929\n", "2019-03-29 24527 25752 46813 830\n", "2019-03-30 18647 22608 36714 659\n", "2019-03-31 21674 25275 42956 799\n", "2019-04-01 29135 29591 56833 1391\n", "2019-04-02 30330 30050 58545 1442\n", "2019-04-03 28904 29103 57382 865\n", "2019-04-04 28497 28041 54026 860\n", "2019-04-05 25218 25857 47214 730\n", "2019-04-06 19373 23510 35657 700\n", "2019-04-07 21764 26299 42046 916\n", "2019-04-08 29885 30308 58223 1098\n", "2019-04-09 30593 31122 58366 1077\n", "2019-04-10 29814 30883 55613 911\n", "2019-04-11 28581 29395 53284 880\n", "2019-04-12 25286 26925 46673 762\n", "2019-04-13 18806 22654 35298 705\n", "2019-04-14 21449 26156 40996 827\n", "2019-04-15 28771 29639 54695 969\n", "2019-04-16 28438 30080 54799 1014\n", "2019-04-17 28218 29006 52183 886\n", "2019-04-18 26262 28218 47142 1872\n", "2019-04-19 25757 29488 39727 12580\n", "2019-04-20 18382 23494 32894 621\n", "2019-04-21 18916 25155 36123 1435\n", "2019-04-22 27423 30401 50170 2818" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# daily event counts for WP:M pages with external links\n", "wpm_events.pivot(index='date', columns='eventType', values='count')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Events for W pages with external links" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "# daily count of events for W pages with ext links over study period\n", "w_events_query = \"\"\"\n", "SELECT to_date(event_time) date, action AS eventType, COUNT(*) count\n", "FROM citationusage\n", "WHERE wiki = 'enwiki'\n", "AND page_id IN (SELECT page_id FROM ryanmax.population_w_pages_with_extlinks)\n", "{}\n", "AND day = {}\n", "AND month = {}\n", "AND year = {}\n", "AND useragent_is_bot = FALSE\n", "GROUP BY to_date(event_time), eventType\n", "ORDER BY to_date(event_time)\n", "\"\"\"\n", "\n", "w_events_rdd = sc.emptyRDD()\n", "for d in daterange(start_date, end_date):\n", " dt = date_to_dt(d)\n", " daily_w_events = spark.sql(\n", " w_events_query.format(event_exclusion_sql, d.day, d.month, d.year))\n", " w_events_rdd = w_events_rdd.union(daily_w_events.rdd)\n", "\n", "w_events_merged = sqlContext.createDataFrame(w_events_rdd)\n", "w_events = w_events_merged.toPandas()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### W event summary" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Total events: 109974252\n" ] }, { "data": { "text/html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
eventTypedaystotal_eventsmeanmedianminmaxstd25%50%75%perc
0extClick32498278891557121157327613165821752162124483.8895921474046.75157327616648840.453087
1fnClick322310821272213172389562492882099846869.018210695899.757238957528150.210124
2fnHover3235926529112270411654698269761481295185086.791800964512.25116546912797610.326681
3upClick32111162234738257241902614345824483.35024122709.5025724358970.010108
\n", "
" ], "text/plain": [ " eventType days total_events mean median min max \\\n", "0 extClick 32 49827889 1557121 1573276 1316582 1752162 \n", "1 fnClick 32 23108212 722131 723895 624928 820998 \n", "2 fnHover 32 35926529 1122704 1165469 826976 1481295 \n", "3 upClick 32 1111622 34738 25724 19026 143458 \n", "\n", " std 25% 50% 75% perc \n", "0 124483.889592 1474046.75 1573276 1664884 0.453087 \n", "1 46869.018210 695899.75 723895 752815 0.210124 \n", "2 185086.791800 964512.25 1165469 1279761 0.326681 \n", "3 24483.350241 22709.50 25724 35897 0.010108 " ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# summary of events for W pages with external links\n", "print('Total events: ', w_events['count'].sum())\n", "get_stats(w_events,['eventType'])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### W daily events" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
eventTypeextClickfnClickfnHoverupClick
date
2019-03-2215359056955991081404143458
2019-03-23134788564189584314719347
2019-03-24148492972099797108122756
2019-03-251713271750599130241581252
2019-03-261669983704416127872227362
2019-03-271635725696000125903526375
2019-03-281581173674494120812924435
2019-03-291473530638280107301522314
2019-03-30131658262492882697619026
2019-03-31143593470911095377522086
2019-04-011666036754475128799662344
2019-04-021650965714823128584338363
2019-04-031640269707290132776525749
2019-04-041617364699627123894224518
2019-04-051543810670946111782922570
2019-04-06136436866084984632719360
2019-04-07148745474630197274224484
2019-04-081752162773643132031126744
2019-04-091706339752262129285426244
2019-04-101664500782356127211425440
2019-04-111623127737892126633024670
2019-04-121536334703104112537023128
2019-04-13135282568953284375020411
2019-04-14147421977963595751722208
2019-04-151686583786904128287925699
2019-04-161667787757042148129526469
2019-04-171639804744860120906535731
2019-04-181565379730809111038958707
2019-04-19147639673142996684448635
2019-04-20138380472679483489235315
2019-04-21143209978032388220736395
2019-04-221701348820998120556950027
\n", "
" ], "text/plain": [ "eventType extClick fnClick fnHover upClick\n", "date \n", "2019-03-22 1535905 695599 1081404 143458\n", "2019-03-23 1347885 641895 843147 19347\n", "2019-03-24 1484929 720997 971081 22756\n", "2019-03-25 1713271 750599 1302415 81252\n", "2019-03-26 1669983 704416 1278722 27362\n", "2019-03-27 1635725 696000 1259035 26375\n", "2019-03-28 1581173 674494 1208129 24435\n", "2019-03-29 1473530 638280 1073015 22314\n", "2019-03-30 1316582 624928 826976 19026\n", "2019-03-31 1435934 709110 953775 22086\n", "2019-04-01 1666036 754475 1287996 62344\n", "2019-04-02 1650965 714823 1285843 38363\n", "2019-04-03 1640269 707290 1327765 25749\n", "2019-04-04 1617364 699627 1238942 24518\n", "2019-04-05 1543810 670946 1117829 22570\n", "2019-04-06 1364368 660849 846327 19360\n", "2019-04-07 1487454 746301 972742 24484\n", "2019-04-08 1752162 773643 1320311 26744\n", "2019-04-09 1706339 752262 1292854 26244\n", "2019-04-10 1664500 782356 1272114 25440\n", "2019-04-11 1623127 737892 1266330 24670\n", "2019-04-12 1536334 703104 1125370 23128\n", "2019-04-13 1352825 689532 843750 20411\n", "2019-04-14 1474219 779635 957517 22208\n", "2019-04-15 1686583 786904 1282879 25699\n", "2019-04-16 1667787 757042 1481295 26469\n", "2019-04-17 1639804 744860 1209065 35731\n", "2019-04-18 1565379 730809 1110389 58707\n", "2019-04-19 1476396 731429 966844 48635\n", "2019-04-20 1383804 726794 834892 35315\n", "2019-04-21 1432099 780323 882207 36395\n", "2019-04-22 1701348 820998 1205569 50027" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# daily event counts for W pages with external links\n", "w_events.pivot(index='date', columns='eventType', values='count')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Mobile vs Desktop" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### mobile vs desktop events for W pages with external links" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
modeeventTypedaystotal_eventsmeanmedianminmaxstd25%50%75%perc
0desktopextClick32292942439.154451e+05974150.56611951102793160436.363245749929.00974150.51049703.000.266374
1desktopfnClick3275278392.352450e+05255253.516205230901043789.385081195226.00255253.5267710.250.068451
2desktopfnHover32338554251.057982e+061097533.07666851416905185721.887148897499.251097533.01215819.500.307849
3desktopupClick329993633.123009e+0422426.51555414014524533.60912819123.7522426.532551.500.009087
4mobileextClick32205336466.416764e+05626029.556126575710956887.431496591392.75626029.5687168.250.186713
5mobilefnClick32155803734.868867e+05480579.041648159541547949.474529442803.75480579.0519503.250.141673
6mobilefnHover3220711046.472200e+0464384.057461726503955.89261662148.7564384.067267.250.018833
7mobileupClick321122593.508094e+033466.529874127258.4081993315.253466.53713.750.001021
\n", "
" ], "text/plain": [ " mode eventType days total_events mean median min \\\n", "0 desktop extClick 32 29294243 9.154451e+05 974150.5 661195 \n", "1 desktop fnClick 32 7527839 2.352450e+05 255253.5 162052 \n", "2 desktop fnHover 32 33855425 1.057982e+06 1097533.0 766685 \n", "3 desktop upClick 32 999363 3.123009e+04 22426.5 15554 \n", "4 mobile extClick 32 20533646 6.416764e+05 626029.5 561265 \n", "5 mobile fnClick 32 15580373 4.868867e+05 480579.0 416481 \n", "6 mobile fnHover 32 2071104 6.472200e+04 64384.0 57461 \n", "7 mobile upClick 32 112259 3.508094e+03 3466.5 2987 \n", "\n", " max std 25% 50% 75% perc \n", "0 1102793 160436.363245 749929.00 974150.5 1049703.00 0.266374 \n", "1 309010 43789.385081 195226.00 255253.5 267710.25 0.068451 \n", "2 1416905 185721.887148 897499.25 1097533.0 1215819.50 0.307849 \n", "3 140145 24533.609128 19123.75 22426.5 32551.50 0.009087 \n", "4 757109 56887.431496 591392.75 626029.5 687168.25 0.186713 \n", "5 595415 47949.474529 442803.75 480579.0 519503.25 0.141673 \n", "6 72650 3955.892616 62148.75 64384.0 67267.25 0.018833 \n", "7 4127 258.408199 3315.25 3466.5 3713.75 0.001021 " ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# mobile vs desktop events for W pages with external links\n", "w_mode_events_query = \"\"\"\n", "SELECT to_date(event_time) AS date, mode, action AS eventType, COUNT(*) count\n", "FROM citationusage\n", "WHERE wiki = 'enwiki'\n", "AND page_id IN (SELECT page_id FROM ryanmax.population_w_pages_with_extlinks)\n", "{}\n", "AND to_date(event_time) >= '{}'\n", "AND to_date(event_time) <= '{}'\n", "AND useragent_is_bot = FALSE\n", "GROUP BY date, mode, eventType\n", "ORDER BY date, mode, eventType\n", "\"\"\"\n", "\n", "events = spark.sql(w_mode_events_query.format(event_exclusion_sql,start_date_string, end_date_string))\n", "events_rdd = events.rdd\n", "events_df = sqlContext.createDataFrame(events_rdd)\n", "w_events_pandas = events_df.toPandas()\n", "get_stats(w_events_pandas,['mode','eventType'])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### mobile vs desktop events for WP:M pages with external links" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
modeeventTypedaystotal_eventsmeanmedianminmaxstd25%50%75%perc
0desktopextClick3256935217792.2500019381.510839222573881.85953914054.7519381.521140.250.171343
1desktopfnClick3235036210948.8125011809.56992133872039.2498859359.2511809.512495.750.105440
2desktopfnHover32146607545814.8437545790.530290569448395.11493238803.5045790.553479.750.441207
3desktopupClick32455281422.75000787.5530124922232.108652711.00787.5982.000.013701
4mobileextClick322566298019.656258070.070168960438.1775767644.758070.08363.500.077231
5mobilefnClick3253730016790.6250016899.01486418461887.85376416156.0016899.017294.250.161698
6mobilefnHover32938902934.062502937.525423421265.3059022690.752937.53159.750.028256
7mobileupClick323735116.71875118.08815516.142979106.00118.0127.000.001124
\n", "
" ], "text/plain": [ " mode eventType days total_events mean median min max \\\n", "0 desktop extClick 32 569352 17792.25000 19381.5 10839 22257 \n", "1 desktop fnClick 32 350362 10948.81250 11809.5 6992 13387 \n", "2 desktop fnHover 32 1466075 45814.84375 45790.5 30290 56944 \n", "3 desktop upClick 32 45528 1422.75000 787.5 530 12492 \n", "4 mobile extClick 32 256629 8019.65625 8070.0 7016 8960 \n", "5 mobile fnClick 32 537300 16790.62500 16899.0 14864 18461 \n", "6 mobile fnHover 32 93890 2934.06250 2937.5 2542 3421 \n", "7 mobile upClick 32 3735 116.71875 118.0 88 155 \n", "\n", " std 25% 50% 75% perc \n", "0 3881.859539 14054.75 19381.5 21140.25 0.171343 \n", "1 2039.249885 9359.25 11809.5 12495.75 0.105440 \n", "2 8395.114932 38803.50 45790.5 53479.75 0.441207 \n", "3 2232.108652 711.00 787.5 982.00 0.013701 \n", "4 438.177576 7644.75 8070.0 8363.50 0.077231 \n", "5 887.853764 16156.00 16899.0 17294.25 0.161698 \n", "6 265.305902 2690.75 2937.5 3159.75 0.028256 \n", "7 16.142979 106.00 118.0 127.00 0.001124 " ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# mobile vs desktop events for WP:M pages with external links\n", "wpm_mode_events_query = \"\"\"\n", "SELECT to_date(event_time) AS date, mode, action AS eventType, COUNT(*) count\n", "FROM citationusage\n", "WHERE wiki = 'enwiki'\n", "AND page_id IN (SELECT page_id FROM ryanmax.population_wpm_pages_with_extlinks)\n", "{}\n", "AND to_date(event_time) >= '{}'\n", "AND to_date(event_time) <= '{}'\n", "AND useragent_is_bot = FALSE\n", "GROUP BY date, mode, eventType\n", "ORDER BY date, mode, eventType\n", "\"\"\"\n", "\n", "events = spark.sql(wpm_mode_events_query.format(event_exclusion_sql,start_date_string, end_date_string))\n", "events_rdd = events.rdd\n", "events_df = sqlContext.createDataFrame(events_rdd)\n", "wpm_events_pandas = events_df.toPandas()\n", "get_stats(wpm_events_pandas,['mode','eventType'])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Visualization" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "# Plots inline\n", "%matplotlib inline" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
modeeventTypedaystotal_eventsmeanmedianminmaxstd25%50%75%percgroup
0desktopextClick32292942439.154451e+05974150.56611951102793160436.363245749929.00974150.51049703.000.266374W
1desktopfnClick3275278392.352450e+05255253.516205230901043789.385081195226.00255253.5267710.250.068451W
2desktopfnHover32338554251.057982e+061097533.07666851416905185721.887148897499.251097533.01215819.500.307849W
3desktopupClick329993633.123009e+0422426.51555414014524533.60912819123.7522426.532551.500.009087W
4mobileextClick32205336466.416764e+05626029.556126575710956887.431496591392.75626029.5687168.250.186713W
\n", "
" ], "text/plain": [ " mode eventType days total_events mean median min \\\n", "0 desktop extClick 32 29294243 9.154451e+05 974150.5 661195 \n", "1 desktop fnClick 32 7527839 2.352450e+05 255253.5 162052 \n", "2 desktop fnHover 32 33855425 1.057982e+06 1097533.0 766685 \n", "3 desktop upClick 32 999363 3.123009e+04 22426.5 15554 \n", "4 mobile extClick 32 20533646 6.416764e+05 626029.5 561265 \n", "\n", " max std 25% 50% 75% perc group \n", "0 1102793 160436.363245 749929.00 974150.5 1049703.00 0.266374 W \n", "1 309010 43789.385081 195226.00 255253.5 267710.25 0.068451 W \n", "2 1416905 185721.887148 897499.25 1097533.0 1215819.50 0.307849 W \n", "3 140145 24533.609128 19123.75 22426.5 32551.50 0.009087 W \n", "4 757109 56887.431496 591392.75 626029.5 687168.25 0.186713 W " ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "w_events_info = get_stats(w_events_pandas,['mode', 'eventType'])\n", "w_events_info['group'] = \"W\"\n", "wm_events_info = get_stats(wpm_events_pandas,['mode', 'eventType'])\n", "wm_events_info['group'] = \"WPM\"\n", "\n", "all_stats = w_events_info.append(wm_events_info)\n", "all_stats.head()" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
eventTypegroupperctotal_eventsdaily_average
0extClickW0.453087498278891.557122e+06
1extClickWPM0.2485758259812.581191e+04
2fnClickW0.210124231082127.221316e+05
3fnClickWPM0.2671378876622.773944e+04
4fnHoverW0.326681359265291.122704e+06
\n", "
" ], "text/plain": [ " eventType group perc total_events daily_average\n", "0 extClick W 0.453087 49827889 1.557122e+06\n", "1 extClick WPM 0.248575 825981 2.581191e+04\n", "2 fnClick W 0.210124 23108212 7.221316e+05\n", "3 fnClick WPM 0.267137 887662 2.773944e+04\n", "4 fnHover W 0.326681 35926529 1.122704e+06" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "events_by_group = all_stats.groupby([\"eventType\", \"group\"]).agg(\"sum\")[[\"perc\", \"total_events\"]].reset_index()\n", "events_by_group[\"daily_average\"] = events_by_group[\"total_events\"]/32\n", "events_by_group.head()" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "image/png": "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\nWT3bt2/n+PHjZue791pdXFywtrYmISEh2xjfeOMNpkyZQrt27RgzZoxZl212atWqZfq3jY0N1atX\nN90fFxcXGjVqxIIFC4A793Tnzp28/PLLFtV9r0aNGmFvb2/6MrBs2TIcHBxMX0Duuvf/HdwZu3Y3\nnt27d5Oamkr9+vXN7uHy5csz3MN/XuPdn06dOmW5n6enJ0WLFmXr1q2kpKSwY8cOAgMDsbKywtfX\n16z8n92qcCdJq1Wrlmns66hRo6hcubLZPgUKFCAkJITIyEg2bNhAWlpahnuQldDQUH799VfT/4W7\nLbaVKlUC7iTeBw4coEmTJgwePJg1a9aYfRmyhIuLC5UrVzYl71u3bjW1ugUEBJiVq1tVsmOT1wGI\n5KVDhw7h4OCQZStW9+7dCQkJYePGjWzbto0pU6bwzjvv3Hc8jLW1dZYtKfdjNBpNiaWVVcbvWqmp\nqQ9UL2RMWO/tyrvL1tY2wzGZ7ZddvXfrzipBzkp6ejqdO3c2tXzc6+5EETc3N7y8vIiKisLT05Oo\nqChatWplarVJT0/Hzc0tQ5cxQMGCBc1e//Na7x6fnRdffJF69eqxadMmtm3bRufOnXn++ef5/PPP\nLb7Ou+69P+3bt6dz585cunSJBQsWUKtWrQzJiSVsbGx46aWXiIyMpEOHDkRGRtK2bVtsbLL/c3/v\n7ys9PR0HB4dMZxdnds/uurcV65/3+l7W1tb4+/vz22+/4eXlhb29velaAwIC2LhxI15eXty6dSvT\nLsXp06dTokQJihYtmuV7F+DVV18lNDSUM2fO0LZt22xjv1fdunVxcnJi+fLl/N///R8rV66kR48e\npu1Vq1Zl/fr1bNmyhW3btjFs2DC++uorFixYgL29vUXngDstk9HR0Zw8eZJz586ZvmgFBAQwZswY\nTp48yenTp5XISbbUIif/WefPn2f58uU0adIk04TprrJly/Laa68xfvx4evbsadY9Z2trS1pa2r+K\nY+fOnaZ/X7t2jaNHj+Lm5gbc6T5LS0szaxG72+10l52dHXD/BOTe7pq7YmJiKFiwIGXLln3g+J95\n5hkuX75s1vqWkpLC7t27zVrpLOHl5cWhQ4coX758hp97u2NDQ0NZuXIlcXFxxMfHm7pV79Zx8uRJ\n7O3tM9RRsmRJi2O5+6Gf2X0tUaIEL774IqNHj2bYsGEsX77cNNEiK/f+nm/fvs3u3btNLTyAafzW\n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\n+6w/sbG/c/bsGU6fPqVETkRERORx4+RUHDe3Z4iJ2caOHTH4+t5J2GrVepa4uD1s2hRNsWJOuLtX\nzuNIH4wdICqiAAAgAElEQVQSOREREXmi+fkFsGzZEqysrClfvgIARYsWpUKFSsydOwtfX38MBkPe\nBvmA9Bw5ERER+deSU1KJHNz+kZwnp/z8Apg373uaNQs2K3/2WT8iImbj6+v/sMJ75JTIiYiIyL+W\neDXZ4gf1Pmr+/oFs3hyboTwsrGe+ewDwP6lrVURERCSfUiInIiIikk8pkRMRERHJp5TIiYiIiORT\nSuREREQkBwwYjel5HUS+ZDQaH3qdSuRERETEYnZ2Bbly5SK3b6fmSmLypDIajVy/fg0bG7uHWq8e\nPyIiIiIWc3JyJSnpKpcunSc9PS2vw8lXbGzscHJyfbh1PtTaRERE5IlmMBhwcCiGg0OxvA5FUNeq\niIiISL6lRE5EREQkn1IiJyIiIpJPKZETERERyaeUyImIiIjkU0rkRERERPIpJXIiIiIi+ZQSORER\nEZF8SomciIiISD6VZ4lc9+7d8fDwYNu2baayLVu2EBISgre3N02bNmXVqlWmbUajkcGDB+Pv70+L\nFi3YuXOnadvt27dp27YtW7dufaTXICIiIpKX8iSRi4qK4ubNm2Zlp06dolu3bnTs2JGYmBj69+/P\ngAED+PPPPwFYt24d+/fvJzo6mh49ejB48GDTsVOnTsXLy4ugoKBHeh0iIiIieemRJ3Lnzp1j3Lhx\nDB061Kx8yZIlVK5cmXbt2mFnZ0fDhg1p2LAhP/zwAwDHjh3D39+fQoUK0bhxY44fPw7AgQMHWLp0\nKeHh4Y/6UkRERETylM2jPJnRaGTgwIF069aN0qVLm22Lj4+nevXqZmWenp6m7tUqVaowfvx4rl+/\nTnR0NFWrViUtLY2BAwcyePBg7O3tHzguZ+cHP1byH1dXh7wOQeQ/Qe81kdz3wInc9evXKVKkSI6O\niYiIwGg08sorr2TYlpSUhLu7u1mZo6MjSUlJANSrV489e/bQoUMHXFxcGDZsGNOmTaNatWpUrlyZ\n999/n4sXL1KjRg369OmDtbW1xXElJCSRnm7M0bU8yZ70P74XLiTmdQgigN5rImLuQf4mWNS1OmPG\nDLOJB+Hh4fj6+tKoUSMOHz5s0YlOnDjB119/naFL9S57e3sSE83f9NeuXTNraevWrRtLly7l22+/\n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\nRUREREq7+wa5y5cvM3LkSHr37k3FihXZsWMH//rXv7Czs3vgleXk5HDr1i2ysrIAuHXrFrdu3SI3\nN5cOHTqQk5PDkiVLyMzM5OeffyY6OppXXnmlwHJ27NhBeno6ffr0AaB69eocPHiQnJwcDhw4QLVq\n1R64NhERERFTc88g99FHH9GxY0fOnz9PVFQUCxcufKD7xv23rVu30rhxYwYPHgxA48aNady4MT/8\n8APly5cnMjKSr776Cm9vb95++22GDh2Kv79/vmUkJyczd+5cpkyZYmgLDg7m5MmT+Pj4cPr0aYYM\nGfLQNYqIiIiYinueIxcZGUnZsmWxsbFh0aJFd+1n7NMdevbsSc+ePe86vUGDBmzcuPGey7C3t2ff\nvn352hwcHFizZo1RNYiIiIg8Ke4Z5Lp37264zYiIiIiIlC73DHIzZswoqTpERERE5AEZfdWqiIiI\niJQuCnIiIiIiJkpBTkRERMREKciJiIiImCgFORERERETpSAnIiIiYqIU5ERERERMlIKciIiIiIlS\nkBMRERExUQpyIiIiIiZKQU5ERETERCnIiYiIiJgoBTkRERERE6UgJyIiImKiFORERERETJSCnIiI\niIiJUpATERERMVEKciIiIiImSkFORERExEQpyImIiIiYKAU5EREREROlICciIiJiohTkREREREyU\ngpyIiIiIiVKQExERETFRCnIiIiIiJkpBTkRERMREKciJiIiImCgFORERERETpSAnIiIiYqIU5ERE\nRERMlIKciIiIiIlSkBMRERExUQpyIiIiIiZKQU5ERETERCnIiYiIiJgoBTkRERERE2X5uAsQERGR\nR/fjj0f49NMoTp78jd9/v0JQUDCvvx50z3l69+7ClSuX87U1atSEJUtWGt4vXjyPnTu3YWlpSf/+\nr9OnzyuGaUlJf/DGG6+xaNEKXFyeKdoNEqMoyImIiDwBbt5Mp0aNWrRv35H582cbPV///q/lC2dW\nVlaG199++zW7du1g1qx5pKWlMm7cSLy9fahVqw4A4eHT6NdvoELcY6QgJyIi8gRo0cKPFi38AFiy\nZIHR8z311FPY2zsUOi0x8SxeXt64uzcEoHbtOiQkJFCrVh12795JamoqvXu//OjFy0NTkBMREfkH\ni4mJ5rPPPsHOzh5vbx8GDXqDSpWeBqBOnXps3vw5169f56+/0jh//hy1a9chJSWZZcsWMW/eEszN\n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\ndmbx4sUAREdH880337BgwYKHrrtv375s27aNW7duGdq+/vprkpOT6dGjh6Hthx9+4OjRo6xatYol\nS5bw448/8uGHHxqmf/LJJ0yfPp0333yTXbt2MW3aNA4cOFAgJIrIk0VBTkRMxvfff4+Hh0e+r+Dg\nYAAqVKjACy+8wJYtWwz9f/nlF06dOkW3bt2A22HHxcWFiRMn4urqSq1atXj//fepUKEC27ZtM8yX\nl5dHWFgY3t7e1K5dm7fffpuLFy9y7tw5LCwsqFSpEgB2dnZUrlyZp59++qG3qVOnTuTm5rJ7925D\nW3R0NC+++CJ2dnaGNnNzc6ZPn069evVo0aIF48ePZ9euXVy+fJm8vDwWLVrEmDFj6NKlC88++yy+\nvr6EhYWxadMmbt68+dD1iUjppnPkRMRkNG7cmJkzZ+Zr+/t5Zt27dyckJITk5GTs7e3ZunUrTZo0\noVatWsDtYHfs2DE8PDzyLSMjI4PExETDezMzM9zc3AzvHR0dAUhOTjYsq6g89dRTdOvWjejoaLp1\n60ZSUhIHDhxgxYoV+fq5urpSrlw5w3tPT0/y8vI4ffo0AElJSUycOJHJkycb+uTl5ZGXl8e5c+dw\ndXUt0rpFpHRQkBMRk1G2bFmqV69+1+l+fn7Y2tqyfft2Xn31VXbu3MmwYcMM03Nzc/H19eWDDz4o\nMG+FChUMr83NzbGwsDC8NzMzM8xfHPr27UuXLl04c+YM//73v3F2dqZFixb3nOfO0xXNzMwMdU2c\nOLFASAVwdnYu+qJFpFRQkBORJ4aFhQUvvfQS27Zt49lnnyU1NZXOnTsbpjds2JDNmzfj5OT0SFeM\nlilTBii6YFe3bl08PDyIjo5m3759BAQEGMLjHb/99hvp6enY2NgA8OOPP2JmZkatWrVwcnLC3t6e\ns2fP0r179yKpSURMg86RExGTkZWVRVJSUoGvO6NTcPvw6rFjx1iwYAFt27bNd/7aq6++Sk5ODkOH\nDiUuLo4LFy4QFxfH3LlzOXLkiNF1VK1aFXNzcw4ePEhycnKBq0cfxssvv8y6deu4ePEiPXv2LDA9\nJyeHcePG8dtvv/Hdd98xdepUOnbsiLOzM+bm5oSGhrJq1SqWL1/OqVOnOH36NHv37mXixImPXJuI\nlF4akRMRkxEXF4efn1+B9kOHDhkuDHBzc6N+/fr8+uuv+Q6rAjg4OLBx40bmzJnDsGHDSEtLo3Ll\nynh5eVG5cmWj63BwcODdd99l+fLlTJs2DW9vb9atW/dI2+bv78/UqVPx9fUttBYfHx/q16/P66+/\nzl9//UXbtm2ZNGmSYXqfPn2oWLEiK1euZOHChVhaWlK9enU6duz4SHWJSOlmlvf3f2VFROSxSEpK\nom3btixZsoRWrVrlmzZixAjS09NZtmzZY6pOREorjciJiDxGWVlZXL9+nTlz5lC9evVCRxxFRO5G\n58iJiDxGhw4dws/Pj8OHDzN9+vQCFzmIiNyLDq2KiIiImCiNyImIiIiYKAU5EREREROlICciIiJi\nohTkREREREyUgpyIiIiIifr/qSjjUrKI6DAAAAAASUVORK5CYII=\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "sns.set(font_scale=1.2)\n", "\n", "def show_values_on_bars(axs):\n", " def _show_on_single_plot(ax): \n", " for p in ax.patches:\n", " _x = p.get_x() + p.get_width() / 2\n", " _y = p.get_y() + p.get_height() + 0.005\n", " value = '{:,.1%}'.format(p.get_height())\n", " ax.text(_x, _y, value, ha=\"center\") \n", " if isinstance(axs, np.ndarray):\n", " for idx, ax in np.ndenumerate(axs):\n", " _show_on_single_plot(ax)\n", " else:\n", " _show_on_single_plot(axs)\n", "\n", "\n", "my_pal = {\"WPM\": \"darkorange\", \"W\": \"steelblue\"}\n", "fig = sns.catplot(y='perc', x='eventType', hue='group', \n", " data=events_by_group, kind='bar', palette=my_pal, \n", " legend=False, hue_order=[\"WPM\", \"W\"])\n", "fig.ax.set(xlabel='Event Type', ylabel='Normalized number of events', \n", " title=\"Distribution of events by type - WPM vs. W\")\n", "fig.ax.ticklabel_format(style='plain', axis='y')\n", "vals = plt.gca().get_yticks()\n", "plt.gca().set_yticklabels(['{:,.0%}'.format(x) for x in vals])\n", "plt.gcf().set_size_inches(10, 6)\n", "plt.legend(loc='upper right')\n", "\n", "show_values_on_bars(fig.ax)\n", "plt.savefig(\"events_distribution.pdf\")\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "------\n", "\n", "# Statistical significance of the difference\n", "\n", "## Get events count" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "DataFrame[mode: string, eventType: string, pageloads_with_event: bigint, group: string]" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "w_events_query = \"\"\"\n", "SELECT mode, action AS eventType, COUNT(*) count\n", "FROM citationusage\n", "WHERE wiki = 'enwiki'\n", "AND page_id IN (SELECT page_id FROM ryanmax.population_w_pages_with_extlinks)\n", "{}\n", "AND day = {}\n", "AND month = {}\n", "AND year = {}\n", "AND useragent_is_bot = FALSE\n", "GROUP BY mode, action\n", "\"\"\"\n", "\n", "w_events_rdd = sc.emptyRDD()\n", "for d in daterange(start_date, end_date):\n", " dt = date_to_dt(d)\n", " daily_w_events = spark.sql(\n", " w_events_query.format(event_exclusion_sql, d.day, d.month, d.year))\n", " w_events_rdd = w_events_rdd.union(daily_w_events.rdd)\n", " \n", "w_events_merged = sqlContext.createDataFrame(w_events_rdd)\n", "\n", "w_events_merged.registerTempTable(\"w_events_merged\")\n", "merge_events_query = \"\"\"\n", "SELECT mode, eventType, SUM(count) as pageloads_with_event, 'W' as group\n", "FROM w_events_merged\n", "GROUP BY mode, eventType\n", "\"\"\"\n", "\n", "w_events = spark.sql(merge_events_query)\n", "w_events" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "DataFrame[mode: string, eventType: string, pageloads_with_event: bigint, group: string]" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "wpm_events_query = \"\"\"\n", "SELECT mode, action AS eventType, COUNT(*) count\n", "FROM citationusage\n", "WHERE wiki = 'enwiki'\n", "AND page_id IN (SELECT page_id FROM ryanmax.population_wpm_pages_with_extlinks)\n", "{}\n", "AND day = {}\n", "AND month = {}\n", "AND year = {}\n", "AND useragent_is_bot = FALSE\n", "GROUP BY mode, action\n", "\"\"\"\n", "\n", "wpm_events_rdd = sc.emptyRDD()\n", "for d in daterange(start_date, end_date):\n", " dt = date_to_dt(d)\n", " daily_wpm_events = spark.sql(\n", " wpm_events_query.format(event_exclusion_sql, d.day, d.month, d.year))\n", " wpm_events_rdd = wpm_events_rdd.union(daily_wpm_events.rdd)\n", " \n", "wpm_events_merged = sqlContext.createDataFrame(wpm_events_rdd)\n", "\n", "wpm_events_merged.registerTempTable(\"wpm_events_merged\")\n", "merge_events_query = \"\"\"\n", "SELECT mode, eventType, SUM(count) as pageloads_with_event, 'WPM' as group\n", "FROM wpm_events_merged\n", "GROUP BY mode, eventType\n", "\"\"\"\n", "\n", "wpm_events = spark.sql(merge_events_query)\n", "wpm_events" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
modeeventTypepageloads_with_eventgroup
0desktopfnClick350362WPM
1mobileextClick256629WPM
2mobilefnHover93890WPM
3mobilefnClick537300WPM
4desktopextClick569352WPM
5desktopfnHover1466075WPM
6desktopupClick45528WPM
7mobileupClick3735WPM
8desktopfnClick7527839W
9mobileextClick20533646W
10mobilefnHover2071104W
11mobilefnClick15580373W
12desktopextClick29294243W
13desktopfnHover33855425W
14desktopupClick999363W
15mobileupClick112259W
\n", "
" ], "text/plain": [ " mode eventType pageloads_with_event group\n", "0 desktop fnClick 350362 WPM\n", "1 mobile extClick 256629 WPM\n", "2 mobile fnHover 93890 WPM\n", "3 mobile fnClick 537300 WPM\n", "4 desktop extClick 569352 WPM\n", "5 desktop fnHover 1466075 WPM\n", "6 desktop upClick 45528 WPM\n", "7 mobile upClick 3735 WPM\n", "8 desktop fnClick 7527839 W\n", "9 mobile extClick 20533646 W\n", "10 mobile fnHover 2071104 W\n", "11 mobile fnClick 15580373 W\n", "12 desktop extClick 29294243 W\n", "13 desktop fnHover 33855425 W\n", "14 desktop upClick 999363 W\n", "15 mobile upClick 112259 W" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "all_events = wpm_events.union(w_events).toPandas()\n", "all_events" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [], "source": [ "from pyspark.sql import functions as fn\n", "\n", "w_query = \"\"\"\n", "SELECT CASE WHEN access_method = 'desktop' THEN 'desktop' ELSE 'mobile' END as mode,\n", " SUM(view_count) AS total_pageviews, 'W' as group\n", "FROM wmf.pageview_hourly\n", "WHERE project = 'en.wikipedia'\n", "AND page_id IN\n", " (SELECT DISTINCT page_id \n", " FROM ryanmax.population_w_pages_with_extlinks)\n", "AND agent_type = 'user'\n", "AND to_date(CONCAT(year,'-',month,'-',day)) >= '{}'\n", "AND to_date(CONCAT(year,'-',month,'-',day)) <= '{}'\n", "GROUP BY access_method\n", "\"\"\"\n", "\n", "\n", "w_pageviews = spark.sql(w_query.format(start_date_string, end_date_string))\\\n", " .groupBy(\"mode\", \"group\").agg(fn.sum(\"total_pageviews\").alias(\"total_pageviews\"))" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [], "source": [ "wpm_query = \"\"\"\n", "SELECT CASE WHEN access_method = 'desktop' THEN 'desktop' ELSE 'mobile' END as mode,\n", " SUM(view_count) AS total_pageviews, 'WPM' as group\n", "FROM wmf.pageview_hourly\n", "WHERE project = 'en.wikipedia'\n", "AND page_id IN\n", " (SELECT DISTINCT page_id \n", " FROM ryanmax.population_wpm_pages_with_extlinks)\n", "AND agent_type = 'user'\n", "AND to_date(CONCAT(year,'-',month,'-',day)) >= '{}'\n", "AND to_date(CONCAT(year,'-',month,'-',day)) <= '{}'\n", "GROUP BY access_method\n", "\"\"\"\n", "wpm_pageviews = spark.sql(wpm_query.format(start_date_string, end_date_string))\\\n", " .groupBy(\"mode\", \"group\").agg(fn.sum(\"total_pageviews\").alias(\"total_pageviews\"))" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
modegrouptotal_pageviews
0mobileWPM125364759
1desktopWPM62650292
2mobileW4175643369
3desktopW3134600739
\n", "
" ], "text/plain": [ " mode group total_pageviews\n", "0 mobile WPM 125364759\n", "1 desktop WPM 62650292\n", "2 mobile W 4175643369\n", "3 desktop W 3134600739" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "all_pageviews = wpm_pageviews.union(w_pageviews).toPandas()\n", "all_pageviews" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
modeeventTypepageloads_with_eventgrouptotal_pageviewspageloads_without_eventevent_ratiopages_per_event
0desktopfnClick350362WPM62650292622999300.005592178.815888
1desktopextClick569352WPM62650292620809400.009088110.037889
2desktopfnHover1466075WPM62650292611842170.02340142.733347
3desktopupClick45528WPM62650292626047640.0007271376.082674
4mobileextClick256629WPM1253647591251081300.002047488.505816
5mobilefnHover93890WPM1253647591252708690.0007491335.230152
6mobilefnClick537300WPM1253647591248274590.004286233.323579
7mobileupClick3735WPM1253647591253610240.00003033564.861847
8desktopfnClick7527839W313460073931270729000.002402416.401140
9desktopextClick29294243W313460073931053064960.009345107.003985
10desktopfnHover33855425W313460073931007453140.01080192.587842
11desktopupClick999363W313460073931336013760.0003193136.598752
12mobileextClick20533646W417564336941551097230.004917203.356158
13mobilefnHover2071104W417564336941735722650.0004962016.143742
14mobilefnClick15580373W417564336941600629960.003731268.006637
15mobileupClick112259W417564336941755311100.00002737196.513144
\n", "
" ], "text/plain": [ " mode eventType pageloads_with_event group total_pageviews \\\n", "0 desktop fnClick 350362 WPM 62650292 \n", "1 desktop extClick 569352 WPM 62650292 \n", "2 desktop fnHover 1466075 WPM 62650292 \n", "3 desktop upClick 45528 WPM 62650292 \n", "4 mobile extClick 256629 WPM 125364759 \n", "5 mobile fnHover 93890 WPM 125364759 \n", "6 mobile fnClick 537300 WPM 125364759 \n", "7 mobile upClick 3735 WPM 125364759 \n", "8 desktop fnClick 7527839 W 3134600739 \n", "9 desktop extClick 29294243 W 3134600739 \n", "10 desktop fnHover 33855425 W 3134600739 \n", "11 desktop upClick 999363 W 3134600739 \n", "12 mobile extClick 20533646 W 4175643369 \n", "13 mobile fnHover 2071104 W 4175643369 \n", "14 mobile fnClick 15580373 W 4175643369 \n", "15 mobile upClick 112259 W 4175643369 \n", "\n", " pageloads_without_event event_ratio pages_per_event \n", "0 62299930 0.005592 178.815888 \n", "1 62080940 0.009088 110.037889 \n", "2 61184217 0.023401 42.733347 \n", "3 62604764 0.000727 1376.082674 \n", "4 125108130 0.002047 488.505816 \n", "5 125270869 0.000749 1335.230152 \n", "6 124827459 0.004286 233.323579 \n", "7 125361024 0.000030 33564.861847 \n", "8 3127072900 0.002402 416.401140 \n", "9 3105306496 0.009345 107.003985 \n", "10 3100745314 0.010801 92.587842 \n", "11 3133601376 0.000319 3136.598752 \n", "12 4155109723 0.004917 203.356158 \n", "13 4173572265 0.000496 2016.143742 \n", "14 4160062996 0.003731 268.006637 \n", "15 4175531110 0.000027 37196.513144 " ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "events_summary = all_events.merge(all_pageviews, on=['mode', 'group'])\n", "events_summary['pageloads_without_event'] = events_summary['total_pageviews']-events_summary['pageloads_with_event']\n", "events_summary['event_ratio'] = events_summary['pageloads_with_event']/events_summary['total_pageviews']\n", "events_summary['pages_per_event'] = events_summary['total_pageviews']/events_summary['pageloads_with_event']\n", "\n", "events_summary" ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "scrolled": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "-------------\n" ] }, { "data": { "text/html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
modeeventTypepageloads_with_eventgrouptotal_pageviewspageloads_without_eventevent_ratiopages_per_event
0desktopfnClick350362WPM62650292622999300.005592178.815888
8desktopfnClick7527839W313460073931270729000.002402416.401140
\n", "
" ], "text/plain": [ " mode eventType pageloads_with_event group total_pageviews \\\n", "0 desktop fnClick 350362 WPM 62650292 \n", "8 desktop fnClick 7527839 W 3134600739 \n", "\n", " pageloads_without_event event_ratio pages_per_event \n", "0 62299930 0.005592 178.815888 \n", "8 3127072900 0.002402 416.401140 " ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "Contingency table:\n", "[[ 350362 62299930]\n", " [ 7527839 3127072900]]\n", "\n", "OddsRatio: 2.3361306201136354, p-value < 0.001\n", "\n", "-------------\n" ] }, { "data": { "text/html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
modeeventTypepageloads_with_eventgrouptotal_pageviewspageloads_without_eventevent_ratiopages_per_event
1desktopextClick569352WPM62650292620809400.009088110.037889
9desktopextClick29294243W313460073931053064960.009345107.003985
\n", "
" ], "text/plain": [ " mode eventType pageloads_with_event group total_pageviews \\\n", "1 desktop extClick 569352 WPM 62650292 \n", "9 desktop extClick 29294243 W 3134600739 \n", "\n", " pageloads_without_event event_ratio pages_per_event \n", "1 62080940 0.009088 110.037889 \n", "9 3105306496 0.009345 107.003985 " ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "Contingency table:\n", "[[ 569352 62080940]\n", " [ 29294243 3105306496]]\n", "\n", "OddsRatio: 0.9721756931564446, p-value < 0.001\n", "\n", "-------------\n" ] }, { "data": { "text/html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
modeeventTypepageloads_with_eventgrouptotal_pageviewspageloads_without_eventevent_ratiopages_per_event
2desktopfnHover1466075WPM62650292611842170.02340142.733347
10desktopfnHover33855425W313460073931007453140.01080192.587842
\n", "
" ], "text/plain": [ " mode eventType pageloads_with_event group total_pageviews \\\n", "2 desktop fnHover 1466075 WPM 62650292 \n", "10 desktop fnHover 33855425 W 3134600739 \n", "\n", " pageloads_without_event event_ratio pages_per_event \n", "2 61184217 0.023401 42.733347 \n", "10 3100745314 0.010801 92.587842 " ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "Contingency table:\n", "[[ 1466075 61184217]\n", " [ 33855425 3100745314]]\n", "\n", "OddsRatio: 2.194596122471873, p-value < 0.001\n", "\n", "-------------\n" ] }, { "data": { "text/html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
modeeventTypepageloads_with_eventgrouptotal_pageviewspageloads_without_eventevent_ratiopages_per_event
3desktopupClick45528WPM62650292626047640.0007271376.082674
11desktopupClick999363W313460073931336013760.0003193136.598752
\n", "
" ], "text/plain": [ " mode eventType pageloads_with_event group total_pageviews \\\n", "3 desktop upClick 45528 WPM 62650292 \n", "11 desktop upClick 999363 W 3134600739 \n", "\n", " pageloads_without_event event_ratio pages_per_event \n", "3 62604764 0.000727 1376.082674 \n", "11 3133601376 0.000319 3136.598752 " ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "Contingency table:\n", "[[ 45528 62604764]\n", " [ 999363 3133601376]]\n", "\n", "OddsRatio: 2.2802983491720803, p-value < 0.001\n", "\n", "-------------\n" ] }, { "data": { "text/html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
modeeventTypepageloads_with_eventgrouptotal_pageviewspageloads_without_eventevent_ratiopages_per_event
6mobilefnClick537300WPM1253647591248274590.004286233.323579
14mobilefnClick15580373W417564336941600629960.003731268.006637
\n", "
" ], "text/plain": [ " mode eventType pageloads_with_event group total_pageviews \\\n", "6 mobile fnClick 537300 WPM 125364759 \n", "14 mobile fnClick 15580373 W 4175643369 \n", "\n", " pageloads_without_event event_ratio pages_per_event \n", "6 124827459 0.004286 233.323579 \n", "14 4160062996 0.003731 268.006637 " ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "Contingency table:\n", "[[ 537300 124827459]\n", " [ 15580373 4160062996]]\n", "\n", "OddsRatio: 1.1492877219694864, p-value < 0.001\n", "\n", "-------------\n" ] }, { "data": { "text/html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
modeeventTypepageloads_with_eventgrouptotal_pageviewspageloads_without_eventevent_ratiopages_per_event
4mobileextClick256629WPM1253647591251081300.002047488.505816
12mobileextClick20533646W417564336941551097230.004917203.356158
\n", "
" ], "text/plain": [ " mode eventType pageloads_with_event group total_pageviews \\\n", "4 mobile extClick 256629 WPM 125364759 \n", "12 mobile extClick 20533646 W 4175643369 \n", "\n", " pageloads_without_event event_ratio pages_per_event \n", "4 125108130 0.002047 488.505816 \n", "12 4155109723 0.004917 203.356158 " ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "Contingency table:\n", "[[ 256629 125108130]\n", " [ 20533646 4155109723]]\n", "\n", "OddsRatio: 0.41508460385598855, p-value < 0.001\n", "\n", "-------------\n" ] }, { "data": { "text/html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
modeeventTypepageloads_with_eventgrouptotal_pageviewspageloads_without_eventevent_ratiopages_per_event
5mobilefnHover93890WPM1253647591252708690.0007491335.230152
13mobilefnHover2071104W417564336941735722650.0004962016.143742
\n", "
" ], "text/plain": [ " mode eventType pageloads_with_event group total_pageviews \\\n", "5 mobile fnHover 93890 WPM 125364759 \n", "13 mobile fnHover 2071104 W 4175643369 \n", "\n", " pageloads_without_event event_ratio pages_per_event \n", "5 125270869 0.000749 1335.230152 \n", "13 4173572265 0.000496 2016.143742 " ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "Contingency table:\n", "[[ 93890 125270869]\n", " [ 2071104 4173572265]]\n", "\n", "OddsRatio: 1.5103419291607243, p-value < 0.001\n", "\n", "-------------\n" ] }, { "data": { "text/html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
modeeventTypepageloads_with_eventgrouptotal_pageviewspageloads_without_eventevent_ratiopages_per_event
7mobileupClick3735WPM1253647591253610240.00003033564.861847
15mobileupClick112259W417564336941755311100.00002737196.513144
\n", "
" ], "text/plain": [ " mode eventType pageloads_with_event group total_pageviews \\\n", "7 mobile upClick 3735 WPM 125364759 \n", "15 mobile upClick 112259 W 4175643369 \n", "\n", " pageloads_without_event event_ratio pages_per_event \n", "7 125361024 0.000030 33564.861847 \n", "15 4175531110 0.000027 37196.513144 " ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "Contingency table:\n", "[[ 3735 125361024]\n", " [ 112259 4175531110]]\n", "\n", "OddsRatio: 1.1082012347934034, p-value < 0.001\n" ] } ], "source": [ "from IPython.core import display as ICD\n", "import scipy\n", "\n", "for mode in events_summary['mode'].unique():\n", " for eventType in events_summary['eventType'].unique():\n", " print(\"\\n-------------\")\n", " df = events_summary[(events_summary['mode']==mode)\n", " & (events_summary['group'].isin([\"WPM\", \"W\"]))\n", " & (events_summary['eventType']==eventType)]\n", " ICD.display(df)\n", " print(\"Contingency table:\")\n", " cm = df[['pageloads_with_event', 'pageloads_without_event']].as_matrix()\n", " print(cm)\n", " oddsratio, pvalue = scipy.stats.fisher_exact(cm)\n", " if pvalue < 0.001:\n", " print(\"\\nOddsRatio: {}, p-value < 0.001\".format(oddsratio))\n", " else:\n", " print(\"\\nOddsRatio: {}, p-value = {}\".format(oddsratio, pvalue))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "PySpark - YARN (large)", "language": "python", "name": "spark_yarn_pyspark_large" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.5.3" } }, "nbformat": 4, "nbformat_minor": 2 }