<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><generator uri="https://jekyllrb.com/" version="4.3.4">Jekyll</generator><link href="https://amit-sharma.github.io/feed.xml" rel="self" type="application/atom+xml"/><link href="https://amit-sharma.github.io/" rel="alternate" type="text/html" hreflang="en"/><updated>2025-08-16T06:48:18+00:00</updated><id>https://amit-sharma.github.io/feed.xml</id><title type="html">Amit Sharma</title><subtitle>Amit Sharma, Principal Researcher at Microsoft Research. Working on causal machine learning and AI reasoning. </subtitle><entry><title type="html">Trip report from ACM COMPASS: 2nd Conference on Computing and Sustainable Societies</title><link href="https://amit-sharma.github.io/blog/2019/trip-report-acm-compass/" rel="alternate" type="text/html" title="Trip report from ACM COMPASS: 2nd Conference on Computing and Sustainable Societies"/><published>2019-07-05T00:00:00+00:00</published><updated>2019-07-05T00:00:00+00:00</updated><id>https://amit-sharma.github.io/blog/2019/trip-report-acm-compass</id><content type="html" xml:base="https://amit-sharma.github.io/blog/2019/trip-report-acm-compass/"><![CDATA[<p>Last year, I attended the inaugural ACM conference on Computing and Sustainable Societies (<a href="http://www.acmcompass.org">COMPASS</a>) and was immediately sold on the vision: a conference on the <em>societal impact of computing systems</em>. In the backdrop of increasing concerns on the use of artificial intelligence in decision-making, threats to environmental sustainability, and the long-standing challenges we face in global development, it only makes sense to think how computing technologies can be applied for social good. What I also liked was the inclusive nature of the conference: whether you work in HCI, systems, data science, machine learning or any other field of computing, all such work is welcome. From the outset, it looked like a grand experiment in creating a computing research community focused on societal impact (rather than methods), almost too good to be true.</p> <p>The second edition of the conference just concluded and I’m glad to report that the experiment is thriving. There were a number of exciting talks across systems, HCI and data science. There is also a considerable presence from both industry and academia, including NGOs and social enterprises. The full list of talks is available <a href="https://acmcompass.org/accepted-papers">here</a> (<a href="https://www.youtube.com/watch?v=46gIqhB24KU">Day 1</a>, <a href="https://www.youtube.com/watch?v=hzjqvB97B8k">Day 2</a>, <a href="https://www.youtube.com/watch?v=6IuBX3CJn9o">Day 3</a>). Below I touch upon a few highlights.</p> <h2 id="low-cost-sensing">Low-cost sensing</h2> <p>There is a lot of promise around sensors to enable informed decision-making using real-time data and help in monitoring cities, traffic, infrastructure, agricultural fields and even the environment. Often, however, the high cost of sensors make them impractical for deployment in the Global South. <a href="http://ibaino.net/index.html">Engineer Bainomugisha</a> from Makerere University gave an impressive talk on using low-cost sensors for tracking air pollution. They have even <a href="https://www.airqo.net">deployed hundreds</a> of them in Kampala, Uganda! Data from these pollution sensors enable a more granular view of the problem (e.g., by different parts of a city) and has the potential to transform how local governments tackle pollution.</p> <figure> <picture> <source class="responsive-img-srcset" srcset="/assets/img/airqo.png" sizes="95vw"/> <img src="/assets/img/airqo.png" class="img-fluid rounded z-depth-1" width="100%" height="auto" title="A live map report from Kampala, Uganda [Source: The AirQo project.]" loading="eager" onerror="this.onerror=null; $('.responsive-img-srcset').remove();"/> </picture> </figure> <div class="caption"> A live map report from Kampala, Uganda [Source: The AirQo project.] </div> <p>Aerial imagery can be another way for sensing in low-resource contexts. Using satellite data, one of the papers developed an algorithm to determine road quality in Kenya. Another paper from my colleagues in MSR India developed a low-cost alternative to drones for monitoring agricultural fields using a helium ballon and a smartphone (Best Paper Award). These papers utilized machine learning models for computer vision and I think there is a lot to explore in applying machine learning methods on these datasets.</p> <h2 id="interactive-voice-response-ivr-systems">Interactive Voice Response (IVR) systems</h2> <p>IVR? Many in the Global North may associate IVR phone systems with frustrating customer service experiences. But due to low penetration of smartphones and data access in many parts of the Global South, IVR systems are one of the biggest successes as platforms for information sharing. Over the past few years, the ICTD community has developed IVR solutions for applications such as <a href="http://cgnetswara.org">citizen journalism</a>, <a href="http://www.cse.iitd.ernet.in/~aseth/genderNtechICTD19-1909-01.pdf">maternal and child health</a>, <a href="https://gramvaani.org">agricultural and health practices</a>, and more. This year we saw an impressive study on using IVR systems to augment school lessons for children in low-resource communities (Best Paper Award). The authors created a set of questions that complement school lessons for French language in a rural community in Côte d’Ivoire and found how the family plays a key role in helping children interact with the system. I also got a chance to present two of our projects on IVR: one on models of spreading mass awareness through IVR, and another on evaluating a social network for people with disability (in collaboration with an NGO, <a href="http://www.enableindia.org">Enable India</a>).</p> <h2 id="mechanism-design">Mechanism design</h2> <p>Another theme that came out throughout the conference was on designing incentives and efficient markets for social good. One of the talks was on setting incentives for encouraging people to collect images of birds in under-represented areas, another optimized incentives for spreading awareness by sharing with peers. More generally, these problems fall under the broad definition of mechanism design. <a href="https://scholar.google.com/citations?user=5Bou78sAAAAJ&amp;hl=en">Daniel Mutembesa</a> gave a great tutorial on mechanism design and talked about a project on encouraging field workers to <a href="http://air.ug/mcrops/">collect images</a> of the cassava crop, one of the staples in Africa. Given the ubiquity of field workers in agriculture, health and finance in the Global South, I look forward to more work on incentive design.</p> <figure> <picture> <source class="responsive-img-srcset" srcset="/assets/img/mcrop.png" sizes="95vw"/> <img src="/assets/img/mcrop.png" width="100%" height="auto" title="Mcrop system for crowdsourcing images of diseased cassava crop [Source: Mutembesa et al. 2018]" loading="eager" onerror="this.onerror=null; $('.responsive-img-srcset').remove();"/> </picture> </figure> <div class="caption"> Mcrop system for crowdsourcing images of diseased cassava crop [Source: Mutembesa et al. 2018] </div> <h2 id="data-science-and-machine-learning">Data science and machine learning</h2> <p>Finally, there were a number of papers that used available data to ask interesting questions. One of the studies looked at the Indian census to analyze development of districts over the past ten years, leading to questions on progress of different kinds of infrastructure and geographical clustering in economic development. There was also work on building models to help people make better decisions. As a call to action, one of the papers listed <a href="https://arxiv.org/abs/1810.11383">potential problems</a> where machine learning can be used for societal impact, based on interviews with stakeholders in East Africa. It was also good to see discussions on the ethics of using machine learning in societally critical domains. For instance, one <a href="https://dssg.uchicago.edu/project/proactive-outreach-to-reduce-harassment-of-nyc-rental-housing-tenants/">study</a> developed a machine learning model to predict which buildings in New York are more likely to have tenants vulnerable to forceful eviction and guide city officials to visit those buildings. One of the concerns acknowledged by the authors was fairness in the selection of buildings for such visits, since the training data excluded any buildings that were not visited in the past. Questions of fairness, explainability and ethics also came up during the panel discussion on AI in Global Health.</p> <h2 id="deployment-experiences-and-challenges">Deployment experiences and challenges</h2> <p>All said and done, the real impact of the above research projects is when they are deployed. And as people working in global development know well, translation from research to practice can be very tricky. That’s why it was heartening to see work on deployment experiences being presented as full papers in the main conference. My favorite was on the <a href="https://noahklugman.com/papers/hardware_compass2019.pdf">large-scale deployment of electricity sensors</a> in Ghana for providing citizens accurate data on where and how often power cuts occur. The authors faced many challenges from scaling up a small pilot to large-scale deployment, especially in incorporating local knowledge in their design (and grappling with laws around individual registration of SIM cards). Qualitative studies on deployed systems for social good also highlighted many of the challenges that go unseen when designing these systems. One paper highlighted the <a href="http://www.nixdell.com/papers/2019-refugee-COMPASS.pdf">difficulties that refugees face</a> due to the identity systems used by UNHCR that did not consider refugees themselves as participative agents for the system, and another highlighted the difficulties that an internet-based monitoring system created for home health aides in the United States.</p> <h2 id="summary">Summary</h2> <p>There were many more interesting projects especially at the poster session. It also helped that this year the conference was held in Accra, Ghana, keeping in with the inclusive nature of the conference (last year COMPASS was in the US). It was exciting to meet researchers from different African universities and see the work that they are doing. I hope that there are many more such conferences that provide opportunities for students in different parts of the world to engage with the latest research. Closer home, MSR India continues to contribute to this research direction; we presented four papers and a couple of posters this year. <a href="https://in.linkedin.com/in/rahulap">Rahul Panicker</a> from Wadhwani AI in India gave an exciting talk on AI applications in enhancing global health delivery systems, and it was great to see research from <a href="http://www.cse.iitd.ernet.in/~aseth/">Aaditeshwar Seth</a> on agricultural pricing and district development models.</p> <p>If you would like to know more details, you can find the talks here: <a href="https://www.youtube.com/watch?v=46gIqhB24KU">Day 1</a>, <a href="https://www.youtube.com/watch?v=hzjqvB97B8k">Day 2</a>, <a href="https://www.youtube.com/watch?v=6IuBX3CJn9o">Day 3</a>. The full list of papers is available <a href="https://acmcompass.org/accepted-papers">here</a> and the proceedings should be online soon.</p>]]></content><author><name></name></author><category term="societal-impact"/><category term="societal-impact"/><category term="trip-report"/><summary type="html"><![CDATA[highlights from the conference]]></summary></entry><entry><title type="html">A gentle introduction to causal inference</title><link href="https://amit-sharma.github.io/blog/2016/gentle-intro-causal-inference/" rel="alternate" type="text/html" title="A gentle introduction to causal inference"/><published>2016-06-28T00:00:00+00:00</published><updated>2016-06-28T00:00:00+00:00</updated><id>https://amit-sharma.github.io/blog/2016/gentle-intro-causal-inference</id><content type="html" xml:base="https://amit-sharma.github.io/blog/2016/gentle-intro-causal-inference/"><![CDATA[<blockquote> <p>That we find out the cause of this effect,<br/> Or rather say, the cause of this defect,<br/> For this effect defective comes by cause.<br/></p> </blockquote> <p>-<em>Hamlet</em> by William Shakespeare</p> <p>A few years back I stumbled upon the <a href="https://aeon.co/essays/could-we-explain-the-world-without-cause-and-effect">world of causality</a>. Two things became immediately clear. First, it is a fascinating topic spanning some of the greatest scholars in <a href="http://plato.stanford.edu/entries/leibniz-causation/">philosophy</a>, <a href="http://www.hist-analytic.com/Russellcause.pdf">logic</a> and <a href="https://projecteuclid.org/euclid.ssu/1255440554">statistics</a>. Second, and most unfortunately, the literature on it tends to be a dense, uninviting tome.</p> <p>The more I read, the more I realized that the central concepts are actually very simple. And beneath all the heated arguments about definitions of causality and frameworks for inferring it, the goals and principles of causal inference are one and the same. I wondered, and still wonder, why different disciplines choose to passionately accept one way of thinking about causality versus another. Especially as a computer scientist, I wondered why causal inference is not taught at all even in a graduate program, at a time when computers are affecting all walks of life.</p> <p>As an outsider, I wished there was an easier way to describe the fundamentals of causal inference.</p> <p>Last week I got an opportunity do just that. I gave a tutorial on causal inference at the International Conference on Computational Social Science (<a href="http://www.kellogg.northwestern.edu/news-events/conference/ic2s2/2016.aspx">IC2S2</a>). Here’s my attempt at describing causal inference in an intuitive way, the way I have learnt it and the way I still understand it.</p> <p>Hope this is useful. If it piques your interest, I also prepared sample code to play with recommender system data and methods for causal inference. Find it here: <a href="https://github.com/amit-sharma/causal-inference-tutorial">Github</a>.</p> <iframe src="//www.slideshare.net/slideshow/embed_code/key/nwdSAxsuidSS3X" width="595" height="485" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen=""> </iframe> <div style="margin-bottom:5px"> <strong> <a href="//www.slideshare.net/AmitSharma315/from-prediction-to-causation-causal-inference-in-online-systems" title="From prediction to causation: Causal inference in online systems" target="_blank">From prediction to causation: Causal inference in online systems</a> </strong> from <strong><a href="//www.slideshare.net/AmitSharma315" target="_blank">Amit Sharma</a></strong> </div>]]></content><author><name></name></author><category term="causal-inference"/><category term="causal-inference"/><summary type="html"><![CDATA[slides for a beginner's tutorial]]></summary></entry><entry><title type="html">A simple guide to doubly robust estimation</title><link href="https://amit-sharma.github.io/blog/2016/doubly-robust-estimation-simple-guide/" rel="alternate" type="text/html" title="A simple guide to doubly robust estimation"/><published>2016-04-18T00:00:00+00:00</published><updated>2016-04-18T00:00:00+00:00</updated><id>https://amit-sharma.github.io/blog/2016/doubly-robust-estimation-simple-guide</id><content type="html" xml:base="https://amit-sharma.github.io/blog/2016/doubly-robust-estimation-simple-guide/"><![CDATA[<blockquote> <p><a href="http://www.poetryfoundation.org/poems-and-poets/poems/detail/44272">Two roads diverged in a wood</a>, and I—<br/> I took the one less traveled by,<br/> But if I could go back, I will try<br/> To take both: why one, then another.<br/></p> </blockquote> <p>When I first heard about doubly robust estimation, it sounded like magic, almost too good to be true. When working with messy data, we are used to making tradeoffs. From statistics, there is the bias-variance tradeoff: you can’t improve one without impacting the other. From computer science, there are time and space complexity tradeoffs: an algorithm can take up less time or less space, but devising one that reduces both is always hard.</p> <p>Thus, in a world with <a href="http://www.no-free-lunch.org/">no free lunches</a>, the doubly robust promise stood out. Given two possibly faulty ways of estimating a quantity, a doubly robust estimator guarantees an <strong>unbiased estimate</strong>, whenever one of them is correct. This can be a boon when working with data with unknown distributions and sampling strategies.</p> <p>How does it work? The math is non-intuitive, so it is best to start with an example.</p> <h2 id="finding-the-average-height-of-students">Finding the average height of students</h2> <p>Let us suppose we want to find the average height of people in a class. We could ask all the students to measure their height and then compute the mean of those observations. \(\hat{H}_{mean}=\frac{\sum_{i=1}^n h_i}{n}\)</p> <p>If all the students in the class were in attendance, the above formula will give us the correct answer. If not, and if some students were absent because of independent reasons, the mean estimate will still be an unbiased estimate of the average height in the class.</p> <p>But what if some students were missing systematically? Say there was a basketball game and so many of the taller students were missing that day. Then the computed mean will be lower than the true average height of the class. One way to solve this problem is to know what kind of students are expected to be missing. Suppose we know that there are 5 students taller than 6” in the class, out of which 3 are missing. This means that any student taller than 6” has a 40% chance of being present in the class. To make matters simple, let us assume that all other students are present and therefore have a 100% chance of being in the class.</p> <p>To account for absence of taller students, we could give more importance to observations from taller students. \(\hat{H}_{IPS}=\frac{\sum_{i=1}^n h_i/p_i}{n}\)</p> <p>where \(p_i\) is the probability that a student of height \(h_i\) is present in the class. In our example, \(p_i\) is 1 for everyone except tall students.</p> \[p_i = \begin{cases} 1 &amp; \text{if } h_i&lt;6 \\\\ 0.4 &amp; \text{if } h_i&gt;=6 \end{cases}\] <p>Another way of writing the same formula is by summing over all students enrolled in the class, and using an indicator variable \(o_i\) to denote whether the student was present. \(\hat{H}_{IPS}=\frac{1}{n}\sum_{i=1}^N \frac{o_ih_i}{p_i}\) Using this formula, we can expect to account for the missing tall students and achieve an unbiased estimate for the average height.</p> <h2 id="using-a-doubly-robust-estimator">Using a doubly robust estimator</h2> <p>The problem though is that in many cases, we may not know which one of the above estimators to use. It could be that we do not have enough information about the missing students, and thus cannot accurately write down the probability of omission, \(p_i\) accurately. Or that the entire assumption about the missing basketball team is incorrect, and students across the height spectrum were absent at random.</p> <p>Fortunately, the doubly robust estimator allows us to estimate the average height even when we are not sure about which assumption is true. It is given by:</p> \[\hat{H}_{DR}=\frac{1}{n} \sum_{i=1}^N [\frac{o_i h_i}{p_i} - \frac{o_i-p_i}{p_i}\hat{h}_{i,mean}]\] <h2 id="resolving-the-mystery">Resolving the mystery</h2> <p>Let’s try to see why it works. First, let’s rearrange some terms. \(\hat{H}_{DR}=\frac{1}{n} \sum_{i=1}^N h_i + \frac{1}{n} \sum_{i=1}^N \frac{o_i-p_i}{p_i} (h_i-\hat{h}_{i,mean})\)</p> <p>The DR estimator will be unbiased whenever the right term is zero.</p> <ul> <li>Let us suppose that the students are missing at random. Then, \(\hat{H}_{mean}=\sum_{i=1}^N h_i\), so the right term is zero.</li> <li>Similarly, when we suspect that taller students are absent more than other students and we can estimate \(p_i\) accurately, then \(\sum_{i=1}^N o_i-p_i = 0\) and again, we find that right term evaluates to zero.</li> </ul> <p><em>Voila!</em> In both cases, we obtain the correct average height using the DR estimator.</p> <h2 id="generalizing-to-regression-and-propensity-scores">Generalizing to regression and propensity scores</h2> <p>The same principle can be generalized to more complex scenarios. \(\hat{H}_{mean}\) can be generalized as a regression, based on some observed multi-dimensional data about students \(X\).</p> \[\hat{h}_{i,REG}=\alpha\_0 + \sum_{j=1}^M \alpha_jx_j\] <p>Similarly, the calculation of propensity scores can be generalized, using observed data \(X\).</p> \[p_i = P(o_i=1|x_i) = Logit(\alpha_0 + \sum_{j=1}^M \alpha_jx_j)\] <p>Most generally, we require <em>some</em> way for estimating \(\hat{h}_{i,REG}\) and \(p_i\). Any functional form, such as a learned decision tree or a machine learning model, can be substituted in place of the regression or logit models.</p> <h2 id="okay-where-is-the-catch">Okay, where is the catch?</h2> <p>The catch, as you might imagine, is that in most practical cases, establishing even one of these assumptions is non-trivial. With messy data from the real-world, it is anybody’s guess whether the data is missing at random, or what the correct probabilities of omission are.</p> <p>Still, using a doubly robust estimator provides a useful check against modeling assumptions, as long as we do not err badly on both counts.</p>]]></content><author><name></name></author><category term="causal-inference"/><category term="causal-inference"/><summary type="html"><![CDATA[explained through a simple example on computing mean]]></summary></entry><entry><title type="html">Cumulative distribution plots for frequency data in R</title><link href="https://amit-sharma.github.io/blog/2015/cumulative-distribution-plot-frequency-data-R/" rel="alternate" type="text/html" title="Cumulative distribution plots for frequency data in R"/><published>2015-09-13T00:00:00+00:00</published><updated>2015-09-13T00:00:00+00:00</updated><id>https://amit-sharma.github.io/blog/2015/cumulative-distribution-plot-frequency-data-R</id><content type="html" xml:base="https://amit-sharma.github.io/blog/2015/cumulative-distribution-plot-frequency-data-R/"><![CDATA[<p>R has some great <a href="http://stackoverflow.com/questions/3544002/easier-way-to-plot-the-cumulative-frequency-distribution-in-ggplot">tools</a> for generating and plotting cumulative distribution functions. However, they are suited for raw data, not when the data is summarized in frequency counts. However, reducing to frequency counts is often necessary when processing data at the scale of tens of gigabytes or more. Here I describe a convenient two-liner in R to plot CDFs in R based on aggregated frequency data.</p> <p>For example, suppose you want to analyze the number of times people exercise in a month. One option would be to work with a data table consisting of the number of active days for each person.</p> <div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">library</span><span class="p">(</span><span class="n">dplyr</span><span class="p">)</span><span class="w">
</span><span class="n">library</span><span class="p">(</span><span class="n">ggplot2</span><span class="p">)</span><span class="w">
</span></code></pre></div></div> <div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">running_log</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="n">data.frame</span><span class="p">(</span><span class="n">person_id</span><span class="o">=</span><span class="m">1</span><span class="o">:</span><span class="m">10000</span><span class="p">,</span><span class="w">
                          </span><span class="n">num_active_days</span><span class="o">=</span><span class="n">rpois</span><span class="p">(</span><span class="m">10000</span><span class="p">,</span><span class="w"> </span><span class="n">lambda</span><span class="o">=</span><span class="m">15</span><span class="p">))</span><span class="w"> </span><span class="o">%&gt;%</span><span class="w">
  </span><span class="n">transmute</span><span class="p">(</span><span class="n">num_active_days</span><span class="o">=</span><span class="n">ifelse</span><span class="p">(</span><span class="n">num_active_days</span><span class="o">&lt;=</span><span class="m">30</span><span class="p">,</span><span class="w"> </span><span class="n">num_active_days</span><span class="p">,</span><span class="w"> </span><span class="m">30</span><span class="p">))</span><span class="w">
</span><span class="n">tbl_df</span><span class="p">(</span><span class="n">running_log</span><span class="p">)</span><span class="w">
</span></code></pre></div></div> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>## Source: local data frame [10,000 x 1]
##
##    num_active_days
## 1               14
## 2               12
## 3               13
## 4               12
## 5               17
## 6               18
## 7               16
## 8               18
## 9               16
## 10              11
## ..             ...
</code></pre></div></div> <h2 id="cdfs-from-raw-data">CDFs from raw data</h2> <p>Using built-in function <code class="language-plaintext highlighter-rouge">ecdf</code>, it is <a href="http://www.r-bloggers.com/exploratory-data-analysis-2-ways-of-plotting-empirical-cumulative-distribution-functions-in-r/">easy</a> to generate the cumulative distribution function for such data.</p> <div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">cdf_fun</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="n">ecdf</span><span class="p">(</span><span class="n">running_log</span><span class="o">$</span><span class="n">num_active_days</span><span class="p">)</span><span class="w">
</span><span class="n">plot</span><span class="p">(</span><span class="n">cdf_fun</span><span class="p">,</span><span class="w"> </span><span class="n">xlab</span><span class="o">=</span><span class="s2">"Number of active days"</span><span class="p">,</span><span class="w">
     </span><span class="n">ylab</span><span class="o">=</span><span class="s2">"Number of people"</span><span class="p">,</span><span class="n">main</span><span class="o">=</span><span class="s2">""</span><span class="p">)</span><span class="w">
</span></code></pre></div></div> <figure> <picture> <source class="responsive-img-srcset" srcset="/assets/img/cum-distr-R/activedays_people_plot.png" sizes="95vw"/> <img src="/assets/img/cum-distr-R/activedays_people_plot.png" width="100%" height="auto" loading="eager" onerror="this.onerror=null; $('.responsive-img-srcset').remove();"/> </picture> </figure> <p>For those interested, ggplot provides a function <code class="language-plaintext highlighter-rouge">stat_ecdf</code>, which makes this process even simpler.</p> <div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">ggplot</span><span class="p">(</span><span class="n">running_log</span><span class="p">,</span><span class="w"> </span><span class="n">aes</span><span class="p">(</span><span class="n">x</span><span class="o">=</span><span class="n">num_active_days</span><span class="p">))</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">stat_ecdf</span><span class="p">()</span><span class="w">
</span></code></pre></div></div> <figure> <picture> <source class="responsive-img-srcset" srcset="/assets/img/cum-distr-R/activedays_y_plot.png" sizes="95vw"/> <img src="/assets/img/cum-distr-R/activedays_y_plot.png" width="100%" height="auto" loading="eager" onerror="this.onerror=null; $('.responsive-img-srcset').remove();"/> </picture> </figure> <h2 id="cdfs-with-processed-frequency-data">CDFs with processed, frequency data</h2> <p>Let us now compress our data by precomputing the frequency of people active on each day.</p> <div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">frequency_counts</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="n">running_log</span><span class="w"> </span><span class="o">%&gt;%</span><span class="w"> </span><span class="n">group_by</span><span class="p">(</span><span class="n">num_active_days</span><span class="p">)</span><span class="w"> </span><span class="o">%&gt;%</span><span class="w">
  </span><span class="n">summarize</span><span class="p">(</span><span class="n">num_people</span><span class="o">=</span><span class="n">n</span><span class="p">())</span><span class="w">
</span><span class="n">frequency_counts</span><span class="w">
</span></code></pre></div></div> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>## Source: local data frame [28 x 2]
##
##    num_active_days num_people
## 1                2          1
## 2                4          4
## 3                5         18
## 4                6         55
## 5                7        103
## 6                8        188
## 7                9        328
## 8               10        522
## 9               11        650
## 10              12        847
## ..             ...        ...
</code></pre></div></div> <p>Note how this is a 30x2 table at worst, instead of 10,000x2 entries that we started with. Calculating the empirical cumulative distribution involves sorting the data and using <code class="language-plaintext highlighter-rouge">cumsum</code> to calculate cumulative sums, then plot using the step function as before.</p> <div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">cumulative_frequencies</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="n">frequency_counts</span><span class="w"> </span><span class="o">%&gt;%</span><span class="w">
  </span><span class="n">arrange</span><span class="p">(</span><span class="n">num_active_days</span><span class="p">)</span><span class="w"> </span><span class="o">%&gt;%</span><span class="w">
  </span><span class="n">mutate</span><span class="p">(</span><span class="n">cum_frequency</span><span class="o">=</span><span class="nf">cumsum</span><span class="p">(</span><span class="n">num_people</span><span class="p">))</span><span class="w">
</span><span class="n">cumulative_frequencies</span><span class="w">
</span></code></pre></div></div> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>## Source: local data frame [28 x 3]
##
##    num_active_days num_people cum_frequency
## 1                2          1             1
## 2                4          4             5
## 3                5         18            23
## 4                6         55            78
## 5                7        103           181
## 6                8        188           369
## 7                9        328           697
## 8               10        522          1219
## 9               11        650          1869
## 10              12        847          2716
## ..             ...        ...           ...
</code></pre></div></div> <div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">ggplot</span><span class="p">(</span><span class="n">cumulative_frequencies</span><span class="p">,</span><span class="w"> </span><span class="n">aes</span><span class="p">(</span><span class="n">x</span><span class="o">=</span><span class="n">num_active_days</span><span class="p">,</span><span class="w"> </span><span class="n">y</span><span class="o">=</span><span class="n">cum_frequency</span><span class="p">))</span><span class="w"> </span><span class="o">+</span><span class="w">
 </span><span class="n">geom_step</span><span class="p">()</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">xlab</span><span class="p">(</span><span class="s2">"Number of active days"</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">ylab</span><span class="p">(</span><span class="s2">"Number of people"</span><span class="p">)</span><span class="w">
</span></code></pre></div></div> <figure> <picture> <source class="responsive-img-srcset" srcset="/assets/img/cum-distr-R/activedays_people_plot2.png" sizes="95vw"/> <img src="/assets/img/cum-distr-R/activedays_people_plot2.png" width="100%" height="auto" loading="eager" onerror="this.onerror=null; $('.responsive-img-srcset').remove();"/> </picture> </figure> <h2 id="bonus-plotting-multiple-cdfs-together">Bonus: plotting multiple CDFs together</h2> <p>Now, suppose you wanted to break down your analysis by the type of activity. Let us assume that there are two types of activities: running and cycling.</p> <div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">cycling_log</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="n">data.frame</span><span class="p">(</span><span class="n">person_id</span><span class="o">=</span><span class="m">1</span><span class="o">:</span><span class="m">10000</span><span class="p">,</span><span class="w">
                          </span><span class="n">num_active_days</span><span class="o">=</span><span class="n">rpois</span><span class="p">(</span><span class="m">10000</span><span class="p">,</span><span class="w"> </span><span class="n">lambda</span><span class="o">=</span><span class="m">15</span><span class="p">))</span><span class="w"> </span><span class="o">%&gt;%</span><span class="w">
  </span><span class="n">transmute</span><span class="p">(</span><span class="n">num_active_days</span><span class="o">=</span><span class="n">ifelse</span><span class="p">(</span><span class="n">num_active_days</span><span class="o">&lt;=</span><span class="m">30</span><span class="p">,</span><span class="w"> </span><span class="n">num_active_days</span><span class="p">,</span><span class="w"> </span><span class="m">30</span><span class="p">))</span><span class="w">
</span><span class="n">activity_log</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="n">rbind</span><span class="p">(</span><span class="n">running_log</span><span class="w"> </span><span class="o">%&gt;%</span><span class="w"> </span><span class="n">mutate</span><span class="p">(</span><span class="n">activity_type</span><span class="o">=</span><span class="s2">"running"</span><span class="p">),</span><span class="w">
                      </span><span class="n">cycling_log</span><span class="w"> </span><span class="o">%&gt;%</span><span class="w"> </span><span class="n">mutate</span><span class="p">(</span><span class="n">activity_type</span><span class="o">=</span><span class="s2">"cycling"</span><span class="p">))</span><span class="w">
</span><span class="n">frequency_counts</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">activity_log</span><span class="w"> </span><span class="o">%&gt;%</span><span class="w">
  </span><span class="n">group_by</span><span class="p">(</span><span class="n">num_active_days</span><span class="p">,</span><span class="w"> </span><span class="n">activity_type</span><span class="p">)</span><span class="w"> </span><span class="o">%&gt;%</span><span class="w">
  </span><span class="n">summarize</span><span class="p">(</span><span class="n">num_people</span><span class="o">=</span><span class="n">n</span><span class="p">())</span><span class="w">
</span><span class="n">frequency_counts</span><span class="w">
</span></code></pre></div></div> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>## Source: local data frame [56 x 3]
## Groups: num_active_days
##
##    num_active_days activity_type num_people
## 1                2       running          1
## 2                3       cycling          1
## 3                4       cycling          8
## 4                4       running          4
## 5                5       cycling         22
## 6                5       running         18
## 7                6       cycling         60
## 8                6       running         55
## 9                7       cycling        100
## 10               7       running        103
## ..             ...           ...        ...
</code></pre></div></div> <p>The same code can be used to generate the CDF, with an additional <code class="language-plaintext highlighter-rouge">group_by</code>.</p> <div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">cumulative_frequencies</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="n">frequency_counts</span><span class="w"> </span><span class="o">%&gt;%</span><span class="w"> </span><span class="n">group_by</span><span class="p">(</span><span class="n">activity_type</span><span class="p">)</span><span class="w"> </span><span class="o">%&gt;%</span><span class="w">
  </span><span class="n">mutate</span><span class="p">(</span><span class="n">cum_frequency</span><span class="o">=</span><span class="nf">cumsum</span><span class="p">(</span><span class="n">num_people</span><span class="p">))</span><span class="w">
</span><span class="n">cumulative_frequencies</span><span class="w">
</span></code></pre></div></div> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>## Source: local data frame [56 x 4]
## Groups: activity_type
##
##    num_active_days activity_type num_people cum_frequency
## 1                2       running          1             1
## 2                3       cycling          1             1
## 3                4       cycling          8             9
## 4                4       running          4             5
## 5                5       cycling         22            31
## 6                5       running         18            23
## 7                6       cycling         60            91
## 8                6       running         55            78
## 9                7       cycling        100           191
## 10               7       running        103           181
## ..             ...           ...        ...           ...
</code></pre></div></div> <div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">ggplot</span><span class="p">(</span><span class="n">cumulative_frequencies</span><span class="p">,</span><span class="w"> </span><span class="n">aes</span><span class="p">(</span><span class="n">x</span><span class="o">=</span><span class="n">num_active_days</span><span class="p">,</span><span class="w"> </span><span class="n">y</span><span class="o">=</span><span class="n">cum_frequency</span><span class="p">))</span><span class="w"> </span><span class="o">+</span><span class="w">
  </span><span class="n">geom_step</span><span class="p">()</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">facet_wrap</span><span class="p">(</span><span class="o">~</span><span class="n">activity_type</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w">
  </span><span class="n">xlab</span><span class="p">(</span><span class="s2">"Number of active days"</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">ylab</span><span class="p">(</span><span class="s2">"Number of people"</span><span class="p">)</span><span class="w">
</span></code></pre></div></div> <figure> <picture> <source class="responsive-img-srcset" srcset="/assets/img/cum-distr-R/activedays_people_twoplots.png" sizes="95vw"/> <img src="/assets/img/cum-distr-R/activedays_people_twoplots.png" width="100%" height="auto" loading="eager" onerror="this.onerror=null; $('.responsive-img-srcset').remove();"/> </picture> </figure>]]></content><author><name></name></author><category term="data-science"/><category term="R"/><category term="plotting"/><summary type="html"><![CDATA[a trick for plotting in R]]></summary></entry></feed>