<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Vinayak Mehta on Medium]]></title>
        <description><![CDATA[Stories by Vinayak Mehta on Medium]]></description>
        <link>https://medium.com/@vinayakmehta?source=rss-5c1aac1323f4------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*bQogU_YxSVJHDgKTIv3OKA.jpeg</url>
            <title>Stories by Vinayak Mehta on Medium</title>
            <link>https://medium.com/@vinayakmehta?source=rss-5c1aac1323f4------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 17 May 2026 19:16:09 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@vinayakmehta/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Community Update: Announcing Grofers Tech Talks!]]></title>
            <link>https://lambda.blinkit.com/community-update-announcing-grofers-tech-talks-1d9ecde244e0?source=rss-5c1aac1323f4------2</link>
            <guid isPermaLink="false">https://medium.com/p/1d9ecde244e0</guid>
            <category><![CDATA[meetup]]></category>
            <category><![CDATA[python]]></category>
            <category><![CDATA[community]]></category>
            <category><![CDATA[kubernetes]]></category>
            <category><![CDATA[culture]]></category>
            <dc:creator><![CDATA[Vinayak Mehta]]></dc:creator>
            <pubDate>Mon, 27 May 2019 10:24:46 GMT</pubDate>
            <atom:updated>2019-05-27T10:50:24.892Z</atom:updated>
            <content:encoded><![CDATA[<p>We’re excited to announce Grofers Tech Talks! This is an initiative towards our bid to foster an open exchange of ideas around technology. We’ve decided to keep the scope of this meetup a bit broad, to promote discussions on topics ranging from product to devops and from design to engineering.</p><p>We plan to do this every month. Each meetup will have four talks, with one or two talks by Grofers and the rest by the community. To propose talks, you can simply open an issue on this GitHub repo: <a href="https://github.com/grofers/talks">https://github.com/grofers/talks.</a> Pretty neat, right?</p><p>On April 20, we hosted the first Grofers Tech Talks meetup (or GT-squared as we’ve started to call it) in our Bangalore office. The meetup had two tracks for Engineering and Data Science, each comprising of two talks.</p><h3>Introduction to Kubernetes by Adit Biswas</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/946/1*lQ5476lo-VltQHU6QrZ6Lg.png" /></figure><p>The meetup was kickstarted with the Engineering track, by Adit Biswas with his introductory talk on Kubernetes. He taught us about some basic concepts about containers, explained the Kubernetes architecture which was followed by a short demo. He also talked about how we use Kubernetes at Grofers scale.</p><h3>Rulette: A simple and versatile rule engine by Kislay Verma</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/946/1*Phqy89XZ-iJvT6sjDQEvuQ.png" /></figure><p>Adit’s talk was followed by a talk on <a href="http://rulette.org/">Rulette</a> by Kislay Verma. He talked about how you can simplify business rule management using Rulette, an open-source rule engine developed by him!</p><h3>Extracting tabular data from PDFs using Camelot and Excalibur by Vinayak Mehta</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/948/1*HfCTa7KJ-tq6YAO0azCofw.png" /></figure><p>After a short break, we started with the Data Science track. The third talk (by me) focused on how you can use <a href="http://camelot-py.readthedocs.io/">Camelot</a> and <a href="https://excalibur-py.readthedocs.io/">Excalibur</a>, a Python library and a web interface developed by me, to extract tabular data from PDFs files very easily.</p><h3>Introduction to Tweets Analysis in R by Abdul Majed RS</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/947/1*3plQuMxLr5wA-5XnRGxcdA.png" /></figure><p>In the final talk, Abdul Majed RS showed us how we can easily analyze tweets using R. He used the tweets made about The Patriot Act with Hasan Minhaj’s episode on Indian elections and showed us some interesting insights.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/949/1*ONUPsG4h1d46IT08I7IDrQ.png" /></figure><p>In the end, we opened the space for lightning talks before initiating a coordinated attack on pizzas. Devjyoti Patra talked about <a href="https://github.com/devjyotipatra/tenalisorcerer">tenalisorcerer</a>, an open-source SQL parsing and analysis framework that he’s working on.</p><p>Sounds fun, right? You can find links to talk videos and slides from <a href="https://www.meetup.com/Grofers-Tech-Talks-Bangalore/events/260569166">Meetup #1</a> in the README on this GitHub repo: <a href="https://github.com/grofers/talks">https://github.com/grofers/talks.</a></p><h3>Call for Proposals</h3><p>We’re organizing <a href="https://www.meetup.com/Grofers-Tech-Talks-Bangalore/events/261607636">Meetup #2</a> on 1st June (this Saturday) in our Bangalore office. You can propose talks about anything interesting that you’re working on by simply opening an issue on the GitHub repo mentioned above, we would love to hear from you.</p><p>If you’re interested in solving the kind of problems we write about on Lambda, check out our open positions <a href="https://grofers.recruiterbox.com/">here</a>. You can follow Grofers Engineering on <a href="https://twitter.com/groferseng">Twitter</a> and <a href="https://www.instagram.com/groferseng">Instagram</a> to always stay updated on what we’re doing. Hope to see you at our next meetup!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1d9ecde244e0" width="1" height="1" alt=""><hr><p><a href="https://lambda.blinkit.com/community-update-announcing-grofers-tech-talks-1d9ecde244e0">Community Update: Announcing Grofers Tech Talks!</a> was originally published in <a href="https://lambda.blinkit.com">Lambda by Blinkit</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Community Update — March 2019 (Bangalore)]]></title>
            <link>https://lambda.blinkit.com/community-update-march-2019-bangalore-7c8e198b5a7a?source=rss-5c1aac1323f4------2</link>
            <guid isPermaLink="false">https://medium.com/p/7c8e198b5a7a</guid>
            <category><![CDATA[meetup]]></category>
            <category><![CDATA[python]]></category>
            <category><![CDATA[culture]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[bangalore]]></category>
            <dc:creator><![CDATA[Vinayak Mehta]]></dc:creator>
            <pubDate>Tue, 19 Mar 2019 05:55:25 GMT</pubDate>
            <atom:updated>2019-03-19T06:35:14.595Z</atom:updated>
            <content:encoded><![CDATA[<h3>Community Update — March 2019 (Bangalore)</h3><p>Meetups are an important platform to learn new things, meet like-minded people and get helpful advice. They promote an open exchange of ideas and expose you to perspectives other than your own. Some even go on to become “<a href="https://en.wikipedia.org/wiki/Homebrew_Computer_Club">the crucible for an entire industry</a>”. With that in mind, we were super excited to host the first ever meetup at our Bangalore office!</p><p>Last weekend we hosted <a href="https://www.meetup.com/BangPypers">BangPypers — Bangalore Python Users Group</a>, a monthly meetup where developers meet and discuss topics related to the Python programming language.</p><p>On Saturday, our office was filled with 40 young students and professionals from across Bangalore who were there to engage in talks on how they can make their Python code more robust by writings tests!</p><h3>Continuous Quality by Sanket Saurav</h3><p>The meetup was kickstarted with a talk on <a href="https://deepsource.io/blog/6-benefits-continuous-quality/">Continuous Quality</a> (CQ) where Sanket emphasized on how CQ forms an integral part of the development process and how it can help you ship more reliable, secure and maintainable software.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Z2X1IzsFJ93ml0Xs.jpg" /><figcaption>Picture credits: <a href="https://twitter.com/DeepSourceHQ/status/1106787803688394752">Deepsource</a></figcaption></figure><p>You can reach out to Sanket on <a href="https://twitter.com/sanketsaurav">Twitter</a>. His Github profile is <a href="https://github.com/sanketsaurav">https://github.com/sanketsaurav</a>.</p><h3>Using dependency injection to overcome your testing woes by Joydeep Bhattacharjee</h3><p>In the second talk, Joydeep spoke on how requirement injection can enable you to write generic tests that don’t have to change with your Python requirements. He also spoke on how you can “mock” complex dependencies, for example: APIs or databases, so that your tests don’t have to rely on their availability. You can find the slides and code for his talk <a href="https://github.com/infinite-Joy/programming-languages/tree/master/python-projects/python-testing">here</a>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/899/1*fC23BW8dQESgWO5hCw0bkg.jpeg" /><figcaption>Picture credits: <a href="https://twitter.com/__bangpypers__/status/1106797834576236544">BangPypers</a></figcaption></figure><p>You can reach out to Joydeep on <a href="https://twitter.com/alt227Joydeep">Twitter</a>. His Github profile is <a href="https://github.com/infinite-Joy">https://github.com/infinite-Joy</a>.</p><h3>Data Validation by Ankur Gupta</h3><p>The next talk by Ankur focused on how you can use <a href="http://docs.python-cerberus.org/en/stable/">Cerberus</a> to validate key-value data. He shared various tips and tricks on how you can offload the data validation logic from your code to a simple Cerberus configuration. You can find the Jupyter notebook used in his talk <a href="https://github.com/originalankur/data_validation/blob/master/data_validation.ipynb">here</a>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/899/1*3-mOvXiKbmycG-1hLtkgNg.jpeg" /><figcaption>Picture credits: <a href="https://twitter.com/__bangpypers__/status/1106811964498628608">BangPypers</a></figcaption></figure><p>You can reach out to Ankur on <a href="https://twitter.com/originalankur">Twitter</a>. His Github profile is <a href="https://github.com/originalankur">https://github.com/originalankur</a></p><h3>Why build an automation library? by Praveen G Shirali</h3><p>The final talk by Praveen focused on how you can create an automation library (an API to automate your product) which can then be used for testing, among other things. He also talked about how you can create utilities on top of this library to promote exploratory testing and save engineering time. You can find the slides for his talk <a href="https://pshirali.github.io/why_build_autolib">here</a>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*LQGGXLy8-KbKFDFW.jpg" /><figcaption>Picture credits: <a href="https://twitter.com/__bangpypers__/status/1106823687842529280">BangPypers</a></figcaption></figure><p>You can reach out to Praveen <a href="https://pshirali.github.io/">here</a>. His Github profile is <a href="https://github.com/pshirali">https://github.com/pshirali</a>.</p><p>Thanks to everyone who came to the meetup, it was a great day filled with fun and learning! We’re looking to host a lot more meetups in the future. If you’re a community organizer and need a venue for your meetups, you can reach out to <a href="https://twitter.com/kasisnu">Kasisnu</a> (Gurgaon) and <a href="https://twitter.com/vortex_ape">Vinayak</a> (Bangalore).</p><p>If you’re interested in solving the kind of problems we write about on Lambda, check out our open positions <a href="https://grofers.recruiterbox.com/">here</a>. You can follow Grofers Engineering on <a href="https://twitter.com/groferseng">Twitter</a> and <a href="https://www.instagram.com/groferseng/">Instagram</a> to always stay updated on what we’re doing. Hope to see you at our next meetup!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7c8e198b5a7a" width="1" height="1" alt=""><hr><p><a href="https://lambda.blinkit.com/community-update-march-2019-bangalore-7c8e198b5a7a">Community Update — March 2019 (Bangalore)</a> was originally published in <a href="https://lambda.blinkit.com">Lambda by Blinkit</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[An Open-Source Tool to Extract Tables from PDFs into CSVs]]></title>
            <link>https://medium.com/hackernoon/an-open-source-science-tool-to-extract-tables-from-pdfs-into-excels-3ed3cc7f22e1?source=rss-5c1aac1323f4------2</link>
            <guid isPermaLink="false">https://medium.com/p/3ed3cc7f22e1</guid>
            <category><![CDATA[python]]></category>
            <category><![CDATA[open-data]]></category>
            <category><![CDATA[pdf]]></category>
            <category><![CDATA[open-science]]></category>
            <category><![CDATA[open-source]]></category>
            <dc:creator><![CDATA[Vinayak Mehta]]></dc:creator>
            <pubDate>Mon, 26 Nov 2018 01:09:16 GMT</pubDate>
            <atom:updated>2018-12-11T10:06:49.014Z</atom:updated>
            <content:encoded><![CDATA[<blockquote>Excalibur is a free and open-source tool that can help you to easily extract tabular data from PDFs. I originally wrote this post for my <a href="https://www.vinayakmehta.com/2018/11/26/open-source-tool-extract-tables-pdfs-excels/">website</a>.</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*8YsOjqB-FQPkCAlY.png" /><figcaption>Photo by <a href="https://unsplash.com/photos/Oaqk7qqNh_c?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Patrick Tomasso</a> on <a href="https://unsplash.com/search/photos/books?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p><em>Borrowing the first three paragraphs from my </em><a href="https://www.vinayakmehta.com/2018/10/03/camelot-python-library-extract-tables-pdf/"><em>previous blog post</em></a><em> since they perfectly explain why extracting tables from PDFs is hard.</em></p><p>The PDF (<a href="https://en.wikipedia.org/wiki/PDF">Portable Document Format</a>) was born out of <a href="http://www.planetpdf.com/planetpdf/pdfs/warnock_camelot.pdf">The Camelot Project</a> to create “a universal way to communicate documents across a wide variety of machine configurations, operating systems and communication networks”. Basically, the goal was to make documents viewable on any display and printable on any modern printer. PDF was built on top of <a href="https://en.wikipedia.org/wiki/PostScript">PostScript</a> (a page description language), which had already solved this “view and print anywhere” problem. PDF encapsulates the components required to create a “view and print anywhere” document. These include characters, fonts, graphics and images.</p><p>A PDF file defines instructions to place characters (and other components) at precise <strong>x,y</strong> coordinates relative to the bottom-left corner of the page. Words are simulated by placing some characters closer than others. Similarly, spaces are simulated by placing words relatively far apart. How are tables simulated then? You guessed it correctly — by placing words as they would appear in a spreadsheet.</p><p>The PDF format has no internal representation of a table structure, which makes it difficult to extract tables for analysis. Sadly, a lot of open data is stored in PDFs, which was not designed for tabular data in the first place!</p><h3>Excalibur: Extract tables from PDFs into CSVs</h3><p>Excalibur is a web interface to extract tabular data from PDFs, written in Python 3! It is powered by <a href="https://camelot-py.readthedocs.io/">Camelot</a>. You can check out fantastic documentation at <a href="https://excalibur-py.readthedocs.io/">Read the Docs</a> and follow the development on <a href="https://github.com/camelot-dev/excalibur/">GitHub</a>.</p><p><strong>Note</strong>: Excalibur only works with text-based PDFs and not scanned documents. (As Tabula <a href="https://github.com/tabulapdf/tabula#why-tabula">explains</a>, “If you can click and drag to select text in your table in a PDF viewer, then your PDF is text-based”.)</p><h3>How to install Excalibur</h3><p>After installing <a href="https://www.ghostscript.com/">ghostscript</a> (see <a href="https://camelot-py.readthedocs.io/en/master/user/install-deps.html">install instructions</a>), you can simply use pip to install Excalibur:</p><pre>$ pip install excalibur-py</pre><p><strong>Note</strong>: You can also download executables for Windows and Linux from the <a href="https://github.com/camelot-dev/excalibur/releases">releases page</a> and run them directly!</p><h3>How to use Excalibur</h3><p>After installation with pip, you can initialize the metadata database using:</p><pre>$ excalibur initdb</pre><p>And then start the webserver using:</p><pre>$ excalibur webserver</pre><p>That’s it! Now you can go to <a href="http://localhost:5000/">http://localhost:5000</a> and start extracting tabular data from your PDFs.</p><ol><li><strong>Upload</strong> a PDF and enter the page numbers you want to extract tables from.</li><li>Go to each page and select the table by drawing a box around it. (You can choose to skip this step since Excalibur can automatically detect tables on its own. Click on “<strong>Autodetect tables</strong>” to see what Excalibur sees.)</li><li>Choose a flavor (Lattice or Stream) from “<strong>Advanced</strong>”: <strong>Lattice, </strong>for tables formed with lines or <strong>Stream,</strong> for tables formed with whitespaces.</li><li>Click on “<strong>View and download data</strong>” to see the extracted tables.</li><li>Select your favorite format (CSV/Excel/JSON/HTML) and click on “<strong>Download</strong>”!</li></ol><h3>A table detection upgrade</h3><p>Camelot, the Python library that powers Excalibur, implements two methods to extract tables from two different types of table structures: <strong>Lattice</strong>, for tables formed with lines, and <strong>Stream</strong>, for tables formed with whitespaces. Lattice gave nice results from v0.1.0 since it was able to detect different tables on a single PDF page, in contrast to Stream which treated the whole page as a table.</p><p>But last week, Camelot v0.4.0 was released to fix that problem. <a href="https://github.com/socialcopsdev/camelot/pull/206">#206</a> adds an implementation of the table detection algorithm described by Anssi Nurminen’s <a href="https://github.com/socialcopsdev/camelot/pull/206">master’s thesis</a> that is able to detect multiple <em>Stream</em>-type tables on a single PDF page (most of the time)! You can see the difference in the following images.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*6S3pPeb750_L8hwC.png" /><figcaption>Both <em>Stream</em>-type tables detected in v0.4.0</figcaption></figure><p>as compared to</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*NLS8HL9MD9mzt8Tn.png" /><figcaption>Whole page being treated as a table in v0.3.0</figcaption></figure><h3>Voted #1 on Labworm</h3><p>Excalibur was voted #1 on <a href="https://labworm.com/">Labworm</a> in the second week of November! Labworm is a platform that guides scientists to the best online resources for their research and helps mediate knowledge exchange by promoting open science.</p><h3>LabWorm on Twitter</h3><p>Votes are in! In 1st place: Excalibur, a web interface to extract tabular data from PDFs. See &amp;amp; Vote TOP #research tools at https://t.co/50tYJLLZqc</p><h3>Why another PDF table extraction tool?</h3><p>There are both open (<a href="https://tabula.technology/">Tabula</a>, <a href="https://github.com/jsvine/pdfplumber">pdfplumber</a>) and closed-source (<a href="https://smallpdf.com/">Smallpdf</a>, <a href="https://docparser.com/">Docparser</a>) tools that are widely used to extract data tables from PDFs. They either give a nice output or fail miserably. There is no in between. This is not helpful since everything in the real world, including PDF table extraction, is fuzzy.</p><p>Excalibur uses Camelot under the hood, which was created to offer users complete control over table extraction. If you can’t get your desired output with the default settings, you can tweak the “<strong>Advanced</strong>” settings and get the job done!</p><p>For a more detailed account of why Camelot was created, you should also check out “The longer read” section of my <a href="https://www.vinayakmehta.com/2018/10/03/camelot-python-library-extract-tables-pdf/">previous blog post</a>. Use <strong>Ctrl + F</strong>.</p><h3>The road ahead</h3><p>Reiterating from “The longer read” section I talked about above, it was a pain to see open-source tools not give a nice table extraction output every time. And it was frustrating to see paywalls on closed-source tools. I think that paywalls should not block the way to <a href="https://opensource.com/resources/open-science">open science</a>. I believe that Camelot was a successful attempt by us, at SocialCops, to address the problem of extracting tables from text-based PDFs accurately. Excalibur has made it more easier for anyone to access Camelot’s goodness with a nice web interface.</p><p>But there’s still a lot of open data trapped inside images and image-based PDFs. And state of the art <a href="https://en.wikipedia.org/wiki/Optical_character_recognition">optical character recognition</a> software is locked behind paywalls.</p><blockquote>‘At this time, proprietary OCR software drastically outperforms free and open source OCR software and as such could be worth a public agency’s investment depending on the amount and type of OCR jobs the public agency is needing to perform.’ — <a href="https://how-to.usopendata.org/en/latest/The-Basics-of-Open-Data/Working-with-PDFs/">How to Open Data — Working with PDFs</a></blockquote><p>So the next step is to make it easy for anyone to extract tables (or any other type of data for that matter) from images or image-based PDFs by adding OCR support to Camelot and Excalibur. If you would like to contribute your ideas towards this, do add your comments on <a href="https://github.com/socialcopsdev/camelot/issues/101">#101</a>. You can also check out the <a href="https://excalibur-py.readthedocs.io/en/master/dev/contributing.html">Contributor’s Guide</a> for guidelines around contributing code, documentation or tests, reporting issues and proposing enhancements.</p><p>If Excalibur has helped you extract tables from PDFs, please consider supporting its development by <a href="https://opencollective.com/excalibur">becoming a backer or a sponsor on OpenCollective</a>!</p><p>Also, stop publishing open data as PDFs and keep looking up! :)</p><p><strong>Thanks</strong> to Christine Garcia for providing feedback and suggesting edits.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=3ed3cc7f22e1" width="1" height="1" alt=""><hr><p><a href="https://medium.com/hackernoon/an-open-source-science-tool-to-extract-tables-from-pdfs-into-excels-3ed3cc7f22e1">An Open-Source Tool to Extract Tables from PDFs into CSVs</a> was originally published in <a href="https://medium.com/hackernoon">HackerNoon.com</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Announcing Camelot, a Python Library to Extract Tabular Data from PDFs]]></title>
            <link>https://medium.com/hackernoon/announcing-camelot-a-python-library-to-extract-tabular-data-from-pdfs-605f8e63c2d5?source=rss-5c1aac1323f4------2</link>
            <guid isPermaLink="false">https://medium.com/p/605f8e63c2d5</guid>
            <category><![CDATA[pdf]]></category>
            <category><![CDATA[data-extraction]]></category>
            <category><![CDATA[data-science]]></category>
            <category><![CDATA[open-source]]></category>
            <category><![CDATA[python]]></category>
            <dc:creator><![CDATA[Vinayak Mehta]]></dc:creator>
            <pubDate>Wed, 03 Oct 2018 06:28:02 GMT</pubDate>
            <atom:updated>2019-07-04T22:12:11.783Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*3_s33_p0TJ5zTeSLVRAh2A.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/photos/05ci_hxKWr4?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Carles Rabada</a> on <a href="https://unsplash.com/?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p>The PDF (<a href="https://en.wikipedia.org/wiki/PDF">Portable Document Format</a>) was born out of <a href="http://www.planetpdf.com/planetpdf/pdfs/warnock_camelot.pdf">The Camelot Project</a> to create “a universal way to communicate documents across a wide variety of machine configurations, operating systems and communication networks”. Basically, the goal was to make documents viewable on any display and printable on any modern printer. PDF was built on top of <a href="https://en.wikipedia.org/wiki/PostScript">PostScript</a> (a page description language), which had already solved this “view and print anywhere” problem. PDF encapsulates the components required to create a “view and print anywhere” document. These include characters, fonts, graphics and images.</p><p>A PDF file defines instructions to place characters (and other components) at precise <em>x,y </em>coordinates relative to the bottom-left corner of the page. Words are simulated by placing some characters closer than others. Similarly, spaces are simulated by placing words relatively far apart. How are tables simulated then? You guessed it correctly — by placing words as they would appear in a spreadsheet.</p><p>The PDF format has no internal representation of a table structure, which makes it difficult to extract tables for analysis. Sadly, a lot of open data is stored in PDFs, which was not designed for tabular data in the first place!</p><h3>Camelot: PDF table extraction for humans</h3><p>Today, we’re pleased to announce the release of Camelot, a Python library and command-line tool that makes it easy for anyone to extract data tables trapped inside PDF files! You can check out the documentation at <a href="https://camelot-py.readthedocs.io/">Read the Docs</a> and follow the development on <a href="https://github.com/camelot-dev/camelot">GitHub</a>.</p><h3>How to install Camelot</h3><p>Installation is easy! After <a href="https://camelot-py.readthedocs.io/en/latest/user/install.html#install">installing the dependencies</a>, you can install Camelot using pip (the recommended tool for installing Python packages):</p><pre>$ pip install camelot-py</pre><h3>How to use Camelot</h3><p>Extracting tables from a PDF using Camelot is very simple. Here’s how you do it. (<a href="https://camelot-py.readthedocs.io/en/latest/_static/pdf/foo.pdf">Here’s the PDF</a> used in the following example.)</p><pre>&gt;&gt;&gt; import camelot<br>&gt;&gt;&gt; tables = camelot.read_pdf(&#39;foo.pdf&#39;)<br>&gt;&gt;&gt; tables<br>&lt;TableList n=1&gt;<br>&gt;&gt;&gt; tables.export(&#39;foo.csv&#39;, f=&#39;csv&#39;, compress=True) # json, excel, html<br>&gt;&gt;&gt; tables[0]<br>&lt;Table shape=(7, 7)&gt;<br>&gt;&gt;&gt; tables[0].parsing_report<br>{<br>    &#39;accuracy&#39;: 99.02,<br>    &#39;whitespace&#39;: 12.24,<br>    &#39;order&#39;: 1,<br>    &#39;page&#39;: 1<br>}<br>&gt;&gt;&gt; tables[0].to_csv(&#39;foo.csv&#39;) # to_json, to_excel, to_html<br>&gt;&gt;&gt; tables[0].df # get a pandas DataFrame!</pre><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/40652afca4b940a4a249a1c9696c1f01/href">https://medium.com/media/40652afca4b940a4a249a1c9696c1f01/href</a></iframe><p>You can also check out the <a href="https://camelot-py.readthedocs.io/en/latest/user/cli.html">command-line interface</a>.</p><h3>Why use Camelot?</h3><ul><li>Camelot gives you complete control over table extraction by letting you tweak its settings.</li><li>Bad tables can be discarded based on metrics like accuracy and whitespace, without ever having to manually look at each table.</li><li>Each table is a <a href="https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.html">pandas DataFrame</a>, which seamlessly integrates into <a href="https://gist.github.com/vinayak-mehta/e5949f7c2410a0e12f25d3682dc9e873">ETL and data analysis workflows</a>.</li><li>You can export tables to multiple formats, including CSV, JSON, Excel and HTML.</li></ul><h3>Okay, but why another PDF table extraction library?</h3><h3>TL;DR: Total control for better table extraction</h3><p>Many people use open (<a href="http://tabula.technology/">Tabula</a>, <a href="https://github.com/ashima/pdf-table-extract">pdf-table-extract</a>) and closed-source (<a href="https://smallpdf.com/">smallpdf</a>, <a href="https://pdftables.com/">pdftables</a>) tools to extract tables from PDFs. But they either give a nice output or fail miserably. There is no in between. This is not helpful since everything in the real world, including PDF table extraction, is fuzzy. This leads to the creation of ad-hoc table extraction scripts for each type of PDF table.</p><p>We created Camelot to offer users complete control over table extraction. If you can’t get your desired output with the default settings, you can tweak them and get the job done!</p><p>You can check out a <a href="https://github.com/camelot-dev/camelot/wiki/Comparison-with-other-PDF-Table-Extraction-libraries-and-tools">comparison of Camelot’s output with other open-source PDF table extraction libraries</a>.</p><h3>The longer read</h3><p>We’ve often needed to extract data trapped inside PDFs.</p><p>The first tool that we tried was <a href="http://tabula.technology/">Tabula</a>, which has nice user and command-line interfaces, but it either worked perfectly or failed miserably. When it failed, it was difficult to tweak the settings — such as the image thresholding parameters, which influence table detection and can lead to a better output.</p><p>We also tried closed-source tools like <a href="https://smallpdf.com/">smallpdf</a> and <a href="https://pdftables.com/">pdftables</a>, which worked slightly better than Tabula. But then again, they also didn’t allow tweaking and cost money. (We wrote a blog post about how we went about extracting tables from PDFs back in 2015, titled <a href="https://blog.socialcops.com/technology/engineering/pdf-evil-extracting-tabular-data-pdfs/">“PDF is evil”</a>.)</p><p>When these full-blown PDF table extraction tools didn’t work, we tried <a href="https://en.wikipedia.org/wiki/Pdftotext">pdftotext</a> (an open-source command-line utility). pdftotext extracts text from a PDF while preserving the layout, using spaces. After getting the text, we had to write Python scripts with complicated regexes (<a href="https://en.wikipedia.org/wiki/Regular_expression">regular expressions</a>) to convert the text into tables. This wasn’t scalable, since we had to change the regexs for each new table layout.</p><p>We clearly needed a tweakable PDF table extraction tool, so we started developing one in December 2015. We started with the idea of giving the tool back to the community, which had given us so many open-source tools to work with.</p><p>We knew that Tabula classifies PDF tables into two classes. It has two methods to extract these different classes: Lattice (to extract tables with clearly defined lines between cells) and Stream (to extract tables with spaces between cells). We named Camelot’s table extraction flavors, Lattice and Stream, after Tabula’s methods.</p><p>For Lattice, <a href="https://www.propublica.org/nerds/heart-of-nerd-darkness-why-dollars-for-docs-was-so-difficult">Tabula uses Hough Transform</a>, an image processing technique to detect lines. Since we wanted to use Python, <a href="https://en.wikipedia.org/wiki/OpenCV">OpenCV</a> was the obvious choice to do image processing. However, OpenCV’s <a href="https://docs.opencv.org/2.4/doc/tutorials/imgproc/imgtrans/hough_lines/hough_lines.html">Hough Line Transform</a> returned only line equations. After more exploration, we settled on <a href="https://docs.opencv.org/3.4/d9/d61/tutorial_py_morphological_ops.html">morphological transformations</a>, which gave the exact line segments. From here, representing the table trapped inside a PDF was straightforward.</p><p>To get more information on how Lattice and Stream work in Camelot, check out the <a href="https://camelot-py.readthedocs.io/en/latest/user/how-it-works.html">“How It Works”</a> section of the documentation.</p><h3>How we use Camelot</h3><p>We’ve battle tested Camelot by using it in a variety of projects, both for one-off and automated table extraction.</p><p>Earlier this year, we developed our <a href="https://socialcops.com/solutions/sdg-tracking/">UN SDG Solution</a> to help organizations track and measure their contribution to <a href="https://en.wikipedia.org/wiki/Sustainable_Development_Goals">Agenda 2030</a>. For India, we identified open data sources (primarily PDF reports) for each of the 17 Sustainable Development Goals. For example, one of our sources for Goal 3 (“Good Health and Well-Being for People”) is the <a href="http://rchiips.org/NFHS/NFHS-4Report.shtml">National Family Health Survey (NFHS) report</a> released by <a href="http://iipsindia.org/">IIPS</a>. To get data from these PDF sources, we created an internal web interface built on top of Camelot, where our data analysts could upload PDF reports and extract tables in their preferred format.</p><p><em>Note: </em><a href="https://blog.socialcops.com/inside-sc/press/un-sdg-action-awards-finalist/"><em>We became finalists for the UN SDG Action Awards in February 2018</em></a><em>.</em></p><p>We also set up an <a href="https://blog.socialcops.com/technology/data-science/apache-airflow-disease-outbreaks-india/">ETL workflow using Apache Airflow to track disease outbreaks in India</a>. The workflow scrapes the <a href="http://www.idsp.nic.in/index4.php?lang=1&amp;level=0&amp;linkid=406&amp;lid=3689">Integrated Disease Surveillance Programme (IDSP)</a> website for weekly PDFs of disease outbreak data, and then it extracts tables from the PDFs using Camelot, sends alerts to our team, and loads the data into a data warehouse.</p><h3>To infinity and beyond!</h3><p>Camelot has some limitations. (We’re developing solutions!) Here are a couple of them:</p><ul><li>When using Stream, tables aren’t autodetected. Stream treats the whole page as a single table, which gives bad output when there are multiple tables on the page.</li><li>Camelot only works with text-based PDFs and not scanned documents. (As Tabula <a href="https://github.com/tabulapdf/tabula#why-tabula">explains</a>, “If you can click-and-drag to select text in your table in a PDF viewer… then your PDF is text-based”.)</li></ul><p>You can check out the <a href="https://github.com/camelot-dev/camelot">GitHub repository</a> for more information.</p><p>You can help too — every contribution counts! Check out the <a href="https://camelot-py.readthedocs.io/en/latest/dev/contributing.html">Contributor’s Guide</a> for guidelines around contributing code, documentation or tests, reporting issues and proposing enhancements. You can also head to the <a href="https://github.com/camelot-dev/camelot/issues">issue tracker</a> and look for issues labeled “help wanted” and “good first issue”.</p><p>We urge organizations to release open data in a “data friendly” format like the <a href="https://en.wikipedia.org/wiki/Comma-separated_values">CSV</a>. But while tables are trapped inside PDF files, there’s Camelot :)</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=605f8e63c2d5" width="1" height="1" alt=""><hr><p><a href="https://medium.com/hackernoon/announcing-camelot-a-python-library-to-extract-tabular-data-from-pdfs-605f8e63c2d5">Announcing Camelot, a Python Library to Extract Tabular Data from PDFs</a> was originally published in <a href="https://medium.com/hackernoon">HackerNoon.com</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Airflow, Meta Data Engineering, and a Data Platform for the World’s Largest Democracy]]></title>
            <link>https://medium.com/hackernoon/airflow-meta-data-engineering-and-a-data-platform-for-the-worlds-largest-democracy-3b49a3efd5e8?source=rss-5c1aac1323f4------2</link>
            <guid isPermaLink="false">https://medium.com/p/3b49a3efd5e8</guid>
            <category><![CDATA[india]]></category>
            <category><![CDATA[data-engineering]]></category>
            <category><![CDATA[public-sector]]></category>
            <category><![CDATA[python]]></category>
            <category><![CDATA[airflow]]></category>
            <dc:creator><![CDATA[Vinayak Mehta]]></dc:creator>
            <pubDate>Sat, 25 Aug 2018 08:53:06 GMT</pubDate>
            <atom:updated>2018-10-03T06:48:20.771Z</atom:updated>
            <content:encoded><![CDATA[<blockquote>I originally wrote this post for the <a href="https://blog.socialcops.com/technology/engineering/airflow-meta-data-engineering-disha/">SocialCops engineering blog</a>.</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*0uIC1_An9TbTrK_o6VBwGg.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/photos/a9KHeyRyFJU?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">arihant daga</a> on <a href="https://unsplash.com/?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p>In our <a href="https://blog.socialcops.com/technology/data-science/apache-airflow-disease-outbreaks-india/">last post on Apache Airflow</a>, we mentioned how it has taken the data engineering ecosystem by storm. We also talked about how we’ve been using it to move data across our internal systems and explained the steps we took to create an internal workflow. The ETL workflow (e)xtracted PDFs from a website, (t)ransformed them into CSVs and (l)oaded the CSVs into a store. We also touched briefly on the breadth of ETL use cases you can solve for, using the Airflow platform.</p><p>In this post, we will talk about how one of Airflow’s principles, of being ‘Dynamic’, offers <a href="https://confluence.atlassian.com/bamboo/what-is-configuration-as-code-894743909.html">configuration-as-code</a> as a powerful construct to automate workflow generation. We’ll also talk about how that helped us use Airflow to power DISHA, a national data platform where Indian <a href="https://en.wikipedia.org/wiki/Member_of_Parliament,_Lok_Sabha">MPs</a> and <a href="https://en.wikipedia.org/wiki/Member_of_the_Legislative_Assembly_(India)">MLAs</a> monitor the progress of 42 national level schemes. In the end, we will discuss briefly some of our reflections from the project on today’s public data technology.</p><h3>Why Airflow?</h3><p>To recap from the <a href="https://blog.socialcops.com/technology/data-science/apache-airflow-disease-outbreaks-india/">previous post</a>, Airflow is a workflow management platform created by Maxime Beauchemin at Airbnb. We have been using Airflow to set up batching data workflows in production for more than a year, during which we have found the following points, some of which are also its core principles, to be very useful.</p><ul><li><strong>Dynamic</strong>: A workflow can be defined as a <a href="https://en.wikipedia.org/wiki/Directed_acyclic_graph">Directed Acyclic Graph</a> (DAG) in a Python file (the DAG file), making dynamic generation of complex workflows possible.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/573/1*B5KZ7SlkP7bYyPWXknlphw.png" /><figcaption>An <a href="https://airflow.apache.org/concepts.html">Airflow DAG</a></figcaption></figure><ul><li><strong>Extensible</strong>: There are a lot of operators right out of the box! An operator is a building block for your workflow and each one performs a certain function. For example, the PythonOperator lets you define the logic that runs inside each of the tasks in your workflow, using Python!</li><li><strong>Scalable</strong>: The tasks in your workflow can be executed parallely by multiple Celery workers, using the CeleryExecutor.</li><li><strong>Open Source</strong>: The project is under incubation at the Apache Software Foundation and being actively maintained. It also has an active <a href="https://gitter.im/apache/incubator-airflow">Gitter room</a>.</li></ul><p>Furthermore, Airflow comes with a web interface that gives you all the context you need about your workflow’s execution, from each task’s state (running, success, failed, etc.) to logs that the task generated!</p><h3>The problem with static code</h3><p>Here at SocialCops, we’ve observed a recurring use case of extracting data from various systems using web services, as a component of our ETL workflows. One of the ways to go forward with this task is to write Python code, which can be used with the PythonOperator to integrate the data into a workflow. Let’s look at a very rudimentary DAG file that illustrates this.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/1066f1495e914c519dc2472b88574189/href">https://medium.com/media/1066f1495e914c519dc2472b88574189/href</a></iframe><p>As you can observe, the PythonOperator can be instantiated by specifying the name of the function containing your Python code using the python_callable keyword argument. Multiple instantiated operators can then be linked using Airflow API’s set_downstream and set_upstream methods.</p><p>In the DAG file above, the extract function makes a GET request to <a href="http://httpbin.org/">httpbin.org</a>, with a query parameter. Web services can vary in their request limit (if they support multiple requests at the same time), query parameters, response format and so on. Since writing custom Python code for each web service would be a nightmare for anyone maintaining the code, we decided to build a Python library (we call it Magneton, since it is a magnet for data), which takes in the JSON configuration describing a particular web service as input and fetches the data using a set of pre-defined queries. But that solved only half of our problem.</p><p>In our <a href="https://blog.socialcops.com/technology/data-science/apache-airflow-disease-outbreaks-india/">last post</a> and in the example DAG file above, we could link operators together by writing static calls to the set_downstream and set_upstream methods since the workflows were pretty basic. But imagine a DAG file’s readability with 1,000 operators defined in it. You would have to be a savant to infer the relationships between operators. Moreover, everyone in your team (including people who don’t work with Python as their primary language) wouldn’t have the know-how to write a DAG file, and writing them manually would be repetitive and inefficient.</p><h3>Meta data engineering</h3><p>In his talk “<a href="https://www.youtube.com/watch?v=23_1WlxGGM4">Advance Data Engineering Patterns with Apache Airflow</a>“, Maxime Beauchemin, the author of Airflow, explains how data engineers should find common patterns (ways to build workflows dynamically) in their work and build frameworks and services around them. He gives some examples of such patterns, one of which is AutoDAG. It is an Airflow plugin that Airbnb developed internally to automate DAG creation, allowing the users who just need to run a scheduled SQL query (and don’t want to go author a workflow) to create the query on the web interface itself.</p><p>Finding patterns involves identifying the building blocks of a workflow and chaining them based on a static configuration. Look at the DAG file that we showed in the section above and try to identify the building blocks. It has just three components, which can be modeled into a <a href="https://en.wikipedia.org/wiki/YAML">YAML</a> configuration.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b6a582d72a50ff7640bd2795eba5c31a/href">https://medium.com/media/b6a582d72a50ff7640bd2795eba5c31a/href</a></iframe><p>This is a very basic example. For a more detailed one, you should check out how <a href="http://docs.pachyderm.io/en/latest/reference/pipeline_spec.html">Pachyderm</a> and <a href="http://docs.digdag.io/workflow_definition.html">Digdag</a> have modeled their workflow specifications, which they use to dynamically generate workflows.</p><p>This makes it easy for us to now write a <em>single</em> DAG file that can take in a bunch of these YAML configurations and build DAGs dynamically, by linking operators which have the same identifiers (in this example, we have used a number, 1, for the sake of simplicity). Moreover, anyone in your team who wants to create a workflow can just write a YAML, which makes it easy for a human to define a configuration that is machine-readable. Once you’ve figured out a way to create DAGs based on configurations, you can build a interface to let users build a DAG without writing configurations, making it easy for anyone looking to create a workflow!</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/23215c76a914e4fdfdf4511e53ae0830/href">https://medium.com/media/23215c76a914e4fdfdf4511e53ae0830/href</a></iframe><p>For DISHA, we needed to (E)xtract scheme data from source systems via web services and then follow that with the T and L. At an atomic level, our workflows could be broken down into:</p><ul><li>a PythonOperator to (E)xtract data from the source system, by using Magneton (the Python library we had developed).</li><li>a BashOperator to run R or Python-based (T)ransformations on the extracted data, like cleaning, reshaping, and standardizing geographies across data sets.</li><li>a PythonOperator to (L)oad the transformed data into our data warehouse, on which <a href="https://socialcops.com/visualize/">Visualize</a> can run analytical queries.</li><li>Additionally, we added Slack and email alerts using the PythonOperator.</li></ul><p>Identifying this pattern let us automate DAG creation. Using a web interface, anyone could now add the configuration needed for the three basic tasks outlined above. This helped us to distribute the work of setting up workflows within our small team, most of whom were comfortable only in R. Soon, everyone was writing R scripts and building intricate workflows, like the one below.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*I2321H2U0PLzWECh3UdYgA.jpeg" /></figure><p>The Airflow web interface lets the project stakeholders manage complex workflows (like the one shown above) with ease, since they can check the workflow’s state and pinpoint the exact step where something failed, look at the logs for the failed task, resolve the issue and then resume the workflow by retrying the failed task. Making tasks <a href="https://en.wikipedia.org/wiki/Idempotence">idempotent</a> is a good practice to deal with retries. (Note: retries can be automated within Airflow too.)</p><h3>An overview on DISHA</h3><blockquote><strong>‘DISHA is a crucial step towards good governance through which we will be able to monitor everything centrally. It will enable us to effectively monitor every village of the country.’ — </strong>Narendra Modi, Prime Minister of India</blockquote><p>The District Development Coordination and Monitoring Committee (DISHA) was <a href="http://pib.nic.in/newsite/mbErel.aspx?relid=147922">formed in 2016</a>. The goal was to coordinate between the Central, State and Local Panchayat Governments for successful and timely implementation of key schemes (such as the National Rural Livelihoods Mission, Pradhan Mantri Awaas Yojana and Swachh Bharat Mission). To monitor the schemes and make data-driven implementation decisions, stakeholders needed to get meaningful insights about the schemes. This required integrating the different systems containing the scheme data.</p><p>Last year, we partnered with the Ministry of Rural Development (MoRD) and National Informatics Centre (NIC) to create the DISHA dashboard, which was <a href="https://blog.socialcops.com/inside-sc/announcements/pm-modi-launches-disha-data-platform/">launched by the Prime Minister in October</a>. The DISHA Dashboard helps Members of Parliament (MPs), Members of Legislative Assembly (MLAs) and District Officials track the performance of flagship schemes of different central ministries in their respective districts and constituencies.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2F6hvPEhRXm_s%3Ffeature%3Doembed&amp;url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3D6hvPEhRXm_s&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2F6hvPEhRXm_s%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/16c02890f2c2399c48eba5c0d8f6f6fc/href">https://medium.com/media/16c02890f2c2399c48eba5c0d8f6f6fc/href</a></iframe><p>Back in October 2017, the dashboard had data for 6 schemes, and it was updated in August 2018 to show data for a total of 22 schemes. In its final phase, the dashboard will unify data from 42 flagship schemes to help stakeholders find the answer to life, universe and everything. For the first time, data from 20 ministries will break silos to come together in one place, bringing accountability to a government budget of over Rs. 2 lakh crores!</p><p>The DISHA meetings are held <a href="http://pib.nic.in/newsite/mbErel.aspx?relid=147922">once every quarter</a>, where the committee members meet to ensure that all schemes are being implemented in accordance with the guidelines, look into irregularities with respect to implementation and closely review the flow of allocated funds. Workflows, like the one showed above, have automated the flow of data from scheme databases to the DISHA Dashboard, updating the dashboard regularly with the most recent data for a scheme. This is useful for the committee members since they can plan for the meeting agenda by checking each scheme’s performance and identifying priorities and gap areas.</p><p><em>Watch the Prime Minister speak about how he uses the DISHA dashboard to monitor the progress of Pradhan Mantri Awas Yojna </em><a href="https://blog.socialcops.com/inside-sc/announcements/pm-narendra-modi-monitoring-pmay-disha-dashboard/"><em>here</em></a><em>.</em></p><h3>Going towards better public technology</h3><p>Data extraction is a piece of a larger puzzle called <a href="https://en.wikipedia.org/wiki/Data_integration">data integration</a> (getting the data you want to a single place, from different systems, the way you want it), which people have been working on since the <a href="https://dl.acm.org/citation.cfm?id=1500483">early 1980s</a>. Integrating different data systems can be quite complex due to the systems being heterogeneous; this means they can differ in the way they are implemented, how data is stored within them and how they interact with other systems, making them silos of information.</p><p>To successfully extract data from another system, people on both ends of the transaction first need to agree upon a schema for how the data will be shared. As we found, this can be the most time-consuming part of a project, given how heterogeneous different data systems can be. Even though we have successfully integrated 22 data sources together so far, the time we spent on getting the data in the right format, with the variables we needed for each scheme, would’ve been saved if there was a standard for storing and sharing data across all ministries.</p><p>In his article “<a href="https://medium.com/a-r-g-o/bringing-wall-street-technology-to-bear-on-public-service-delivery-26f8d794c1d5">Bringing Wall Street and the US Army to bear on public service delivery</a>”, Varun Adibhatla of <a href="http://www.argolabs.org/">ARGO Labs</a> talks about ‘Information Exchange protocols’. He calls it jargon for, being able to share standardized data or speak a common language at some considerable scale. He further explains <a href="https://www.astronomer.io/blog/using-apache-airflow-to-create-data-infrastructure/">here</a> that, in the 1990s, Wall Street financial institutions got together and agreed to speak in a common transactional language. This led to the creation of the FIX protocol, which let them share data quickly. He mentions that data standards like the FIX protocol are not unique to Wall Street, but exist in almost every sphere of trade and commerce.</p><blockquote><strong>‘A small team of purpose-driven public technologists, leveraging advances in low-cost device, data and decision-making and the right kind of support is all it takes to build and maintain public, digital infrastructures.’ — </strong>Varun Adibhatla in <a href="https://medium.com/a-r-g-o/bringing-wall-street-technology-to-bear-on-public-service-delivery-26f8d794c1d5">“Bringing Wall Street and the US Army to bear on public service delivery.”</a></blockquote><p>As we move towards a Digital India, we need a fundamental shift from the Excel-for-everything mindset and how today’s public technology is set up. We need a standardized data infrastructure across public services that will help ministries and departments share data with each other quickly, and with the public. A <a href="https://civichall.org/civicist/manifesto-for-public-technology/">new generation of public servants</a> with Silicon Valley–grade technical chops need to be trained and hired. There’s already a Chief Economic Advisor to the government and a Chief Financial Officer for the RBI. It’s high time a Chief Data Officer is appointed for India!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=3b49a3efd5e8" width="1" height="1" alt=""><hr><p><a href="https://medium.com/hackernoon/airflow-meta-data-engineering-and-a-data-platform-for-the-worlds-largest-democracy-3b49a3efd5e8">Airflow, Meta Data Engineering, and a Data Platform for the World’s Largest Democracy</a> was originally published in <a href="https://medium.com/hackernoon">HackerNoon.com</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to Create a Workflow in Apache Airflow to Track Disease Outbreaks in India]]></title>
            <link>https://medium.com/hackernoon/how-to-create-a-workflow-in-apache-airflow-to-track-disease-outbreaks-in-india-fd145575efa4?source=rss-5c1aac1323f4------2</link>
            <guid isPermaLink="false">https://medium.com/p/fd145575efa4</guid>
            <category><![CDATA[etl]]></category>
            <category><![CDATA[pdf]]></category>
            <category><![CDATA[disease]]></category>
            <category><![CDATA[data-science]]></category>
            <category><![CDATA[airflow]]></category>
            <dc:creator><![CDATA[Vinayak Mehta]]></dc:creator>
            <pubDate>Wed, 27 Jun 2018 09:30:42 GMT</pubDate>
            <atom:updated>2018-11-26T22:50:11.232Z</atom:updated>
            <content:encoded><![CDATA[<blockquote>I originally wrote this post for the <a href="https://blog.socialcops.com/technology/data-science/apache-airflow-disease-outbreaks-india/">SocialCops engineering blog</a>.</blockquote><p>What is the first thing that comes to your mind upon hearing the word ‘Airflow’? Data engineering, right? For good reason, I suppose. You are likely to find Airflow mentioned in every other blog post that talks about data engineering.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*SJYEdGnpKTF9R6C2LB-zjw.jpeg" /></figure><p><a href="https://airflow.apache.org/">Apache Airflow</a> is a workflow management platform. To oversimplify, you can think of it as cron, but on steroids! It was started in October 2014 by Maxime Beauchemin at Airbnb. From the very first commit, Airflow was open source. Less than a year later, it was moved into the Airbnb Github. Since then, it has become a vital part of the data engineering ecosystem.</p><p>We have been using Airflow to move data across our internal systems for more than a year, over the course of which we have created a lot of ETL (Extract-Transform-Load) pipelines. In this post, we’ll talk about one of these pipelines in detail and show you the set-up steps.</p><p><em>Note: We will not be going through how to set up Airflow. You can check out </em><a href="http://site.clairvoyantsoft.com/installing-and-configuring-apache-airflow/"><em>a great blog from Clairvoyant</em></a><em> for that.</em></p><h3>Why use Airflow?</h3><ul><li><strong>Dependency Management: </strong>A workflow can be defined as a Directed Acyclic Graph (DAG). Airflow will make sure that the defined tasks are executed one after the other, managing the dependencies between tasks.</li><li><strong>Extensible</strong>: Airflow offers a variety of Operators, which are the building blocks of a workflow. One example is the PythonOperator, which you can use to write custom Python code that will run as a part of your workflow.</li><li><strong>Scalable</strong>: Celery, which is a distributed task queue, can be used as an Executor to scale your workflow’s execution.</li><li><strong>Open Source</strong>: It is under incubation at the Apache Software Foundation, which means it is being actively maintained.</li></ul><h3>IDSP: The disease data source</h3><p>Even though open data portals are cropping up across multiple domains, working with the datasets they provide is difficult. In our bid to identify and help prevent disease outbreaks at <a href="https://socialcops.com">SocialCops</a>, we came across one such difficult data source.</p><p>The <a href="https://mohfw.gov.in/">Ministry of Health and Family Affairs</a> (MHRD) runs the <a href="http://www.idsp.nic.in/">Integrated Disease Surveillance Programme</a> (IDSP) scheme, which identifies disease outbreaks at the sub-district &amp; village level across India. Under this scheme, the MHRD releases weekly outbreak data as a PDF document.</p><p>PDFs are notorious for being hard to scrape and incorporate in data science workflows, but just wait till you see the IDSP PDFs. It may look like the data in them is in a nice table format, but they’ve changed the table formatting over the years and may continue to do so. We’ve also encountered glitches in the document like different tables being joined together, tables flowing out of the page and even tables within tables!</p><h3>Setting up the ETL pipeline</h3><p>No brownie points for figuring out the steps involved in our pipeline. We (<strong>E</strong>)xtract the PDFs from the IDSP website, (<strong>T</strong>)ransform the PDFs into CSVs and (<strong>L</strong>)oad this CSV data into a store.</p><h3>Conventions</h3><p>Let us set up some conventions now, because without order, anarchy would ensue! Each Directed Acyclic Graph should have a unique identifier. We can use an ID, which describes what our DAG is doing, plus a version number. Let us name our DAG idsp_v1.</p><p><em>Note: We borrowed this naming convention from the </em><a href="https://cwiki.apache.org/confluence/display/AIRFLOW/Common+Pitfalls"><em>Airflow “Common Pitfalls” documentation</em></a><em>. It comes in handy when you have to change the start date and schedule interval of a DAG, while preserving the scheduling history of the old version. Make sure you check out this link for other common pitfalls.</em></p><p>We will also define a base directory where data from all the DagRuns will be kept. What is a DagRun, you ask? It is just an instance of your DAG in time. We will also create a new directory for each DagRun.</p><p>Here’s a requirements.txt file which you can use to install the dependencies.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e7ae54a0f6c215cce6ef324ad8e7071d/href">https://medium.com/media/e7ae54a0f6c215cce6ef324ad8e7071d/href</a></iframe><h3>How to DAG</h3><p>In Airflow, DAGs are defined as Python files. They have to be placed inside the dag_folder, which you can define in the Airflow configuration file. Based on the ETL steps we defined above, let’s create our DAG.</p><p>We will define three tasks using the Airflow PythonOperator. You need to pass your Python functions containing the task logic to each Operator using the python_callable keyword argument. Define these as dummy functions in a <strong>utils.py</strong> file for now. We’ll look at each one later.</p><p>We will also link them together using the set_downstream methods. This will define the order in which our tasks get executed. Observe how we haven’t defined the logic that will run inside the tasks, but our DAG is ready to run!</p><p>Have a look at the DAG file. We have set the schedule_interval to 0 0 * * 2. Yes, you guessed it correctly — it’s a cron string.This means that our DAG will run every Tuesday at 12 AM. Airflow scheduling can be a bit confusing, so we suggest you check out the <a href="https://airflow.apache.org/scheduler.html#scheduling-triggers">Airflow docs</a> to understand how it works.</p><p>We have also set provide_context to True since we want Airflow to pass the DagRun’s context (think metadata, like the dag_id, execution_date etc.) into our task functions as keyword arguments.</p><p><em>Note: We’ll use execution_date (which is a Python datetime object) from the context Airflow passes into our function to create a new directory, like we discussed above, to store the DagRun’s data.</em></p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9924141031afad674910270942d5d981/href">https://medium.com/media/9924141031afad674910270942d5d981/href</a></iframe><p>At this point, you can go ahead and create a DAG run by executing airflow trigger_dag idsp_v1 on the command line. Make sure you go to the Airflow UI and unpause the DAG before creating a DagRun. The DagRun should be a success since our tasks are just dummy functions.</p><p>Now that we have our DAG file ready, let’s look at the logic that will run inside our tasks.</p><p><em>Note: Everything you print to standard output</em> <em>inside the function passed to the PythonOperator will be viewable on the Airflow UI. Just click on View Log in the respective operator’s DAG node.</em></p><h3>Scraping the IDSP website</h3><p>A new PDF document is released almost every week (with some lag) on the IDSP website. We can’t keep scraping all the PDFs every time a new one is released. Instead, we will have to save the week number of the PDF we last scraped somewhere.</p><p>We can store this state in a CSV file in our base directory at the end of each DagRun and refer to it at the start of another. Take a look at the scraping code. nThere’s nothing fancy here, just your run-of-the-mill web scraping, using <em>requests</em> and <em>lxml</em>.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a35d302c549b857c5ec7aa86b922f915/href">https://medium.com/media/a35d302c549b857c5ec7aa86b922f915/href</a></iframe><p><em>Note: In production, we don’t run the scraping code inside Airflow. It is run on a separate service, which can connect to REST/SOAP APIs to extract data, in addition to running these scrapers. This gives us a central place to schedule and track how data is pulled into our platform. The task logic is replaced with a call to the data export service.</em></p><h3>Scraping the PDFs</h3><p>Yay! Now that we have new PDFs, we can go about scraping them. We will use <em>pdfminer</em> to accomplish this.</p><p>But first, let me just point out that PDF is the worst format for tabular data. A PDF contains instructions for PDF viewers to place text in the desired font at specific X,Y coordinates on the 2D plane. It doesn’t matter if we just need to get text from of a PDF, but if we need to get tabular data with the table structure intact, it gets difficult. We use a simple heuristic here to get this data out.</p><p>First, we extract all text objects using <em>pdfminer</em>. A text object contains a string and a float coordinate tuple, which describes the string’s position. We then sort all these objects in increasing X and increasing Y order. We now have all these text objects in row-major format, starting from the last row. We can just group them based on their x-axis projections into different columns, discarding any objects that span multiple columns. We can drop the first and last columns since we don’t have any use for them in this post.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/0db1d266e36da7c89089a166b4868999/href">https://medium.com/media/0db1d266e36da7c89089a166b4868999/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*eGYiG5CwNqCZ8Lcc.png" /></figure><p>Voila, we have our table! It is still not usable though and needs some minor cleaning. We are leaving this as an exercise to you. It is easy to define some rules in code to convert the above CSV to something cleaner, like the following.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*SDRHOyMm8uBXvl8B.png" /></figure><p>You can add this cleaning code as another PythonOperator or within the same scrape_pdfoperator. If you are not comfortable with Python and want to use R instead, you can use the BashOperator to call your R script. Extensibility FTW!</p><p><em>Note: It is very difficult to get 100% table scraping accuracy on all types of PDF with a single tool. We can just throw various heuristics at the problem and hope for the best result. A cleaning step is usually required.</em></p><p><em>When we were in the process of preparing the IDSP dataset, using all the previous years’ PDFs, we couldn’t find any tool/library that could solve this problem. We tried many open source tools like </em><a href="https://tabula.technology/"><em>Tabula</em></a><em>, as well as closed source tools like </em><a href="https://pdftables.com/"><em>PDFTables</em></a><em> without any success.</em></p><p><em>This led us to developing our own library, which uses image recognition with a bunch of heuristics to try and solve the PDF table scraping problem. It gave us an acceptable scraping accuracy on a lot of PDF types, including the IDSP ones. Once we plugged this into our data cleaning product, </em><a href="https://socialcops.com/transform/"><em>Transform</em></a><em>, we could finally convert PDF data into a fully clean CSV.</em></p><p><strong><em>Update (5th October 2018):</em></strong><em> We released </em><a href="https://blog.socialcops.com/technology/engineering/camelot-python-library-pdf-data/"><em>Camelot, a Python library that helps anyone extract tabular data from PDFs</em></a><em>. You can find a version of the code provided in this blog post that uses Camelot in this </em><a href="https://gist.github.com/vinayak-mehta/e5949f7c2410a0e12f25d3682dc9e873"><em>Jupyter notebook.</em></a></p><h3>Curating the scraped data</h3><p>Now that we have a clean CSV, we can add it to our master IDSP dataset. The operator contains just a for loop, which appends page-wise CSVs to our master CSV dataset. We could’ve used <a href="https://pandas.pydata.org/">pandas</a> here, but we didn’t want to add another requirement just for this append.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/cc0df6edca8ed3ac43822aec1c74715b/href">https://medium.com/media/cc0df6edca8ed3ac43822aec1c74715b/href</a></iframe><p>Internally, our ETL pipeline doesn’t stop here though. We pass the text in the ‘Comments’ column that we dropped earlier through our entity recognition system, which gives us a list of geographies where the outbreaks happened. This is then used to send alerts to our team and clients.</p><h3>Where can you go from here?</h3><p>Congrats! You have a regularly updating disease outbreaks data set! Now it’s up to you to figure out how you’re gonna use it. <em>cough</em> predictive analytics <em>cough. </em>You can replace the scraping code to scrape data from any other website, write it to the run directory, plug in the PDF scraping operator (if the data you scraped is in PDF format), or plug in a bunch of your own operators to do anything.</p><p>You can find the complete code repo for this exercise <a href="https://github.com/socialcopsdev/airflow_blog">here.</a></p><p>If you do extend this DAG, do <a href="https://twitter.com/social_cops">tweet at us</a>. We’d love to hear what you did!</p><p>Seize the data!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=fd145575efa4" width="1" height="1" alt=""><hr><p><a href="https://medium.com/hackernoon/how-to-create-a-workflow-in-apache-airflow-to-track-disease-outbreaks-in-india-fd145575efa4">How to Create a Workflow in Apache Airflow to Track Disease Outbreaks in India</a> was originally published in <a href="https://medium.com/hackernoon">HackerNoon.com</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>