<?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 Elii Skeans on Medium]]></title>
        <description><![CDATA[Stories by Elii Skeans on Medium]]></description>
        <link>https://medium.com/@elibenjamin?source=rss-aab0243a8d9e------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/0*DrLy91jojjNHbeRq.</url>
            <title>Stories by Elii Skeans on Medium</title>
            <link>https://medium.com/@elibenjamin?source=rss-aab0243a8d9e------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 15 Nov 2026 22:59:28 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@elibenjamin/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[Creating a GeoDatabase with PostgreSQL/PostGIS and Connecting to QGIS]]></title>
            <link>https://medium.com/analytics-vidhya/creating-a-geodatabase-with-postgresql-postgi-and-connecting-to-qgis-bc3c923653ba?source=rss-aab0243a8d9e------2</link>
            <guid isPermaLink="false">https://medium.com/p/bc3c923653ba</guid>
            <category><![CDATA[postgres]]></category>
            <category><![CDATA[postgis]]></category>
            <category><![CDATA[geodatabase]]></category>
            <category><![CDATA[gis]]></category>
            <category><![CDATA[qgis]]></category>
            <dc:creator><![CDATA[Elii Skeans]]></dc:creator>
            <pubDate>Sat, 13 Aug 2022 05:47:42 GMT</pubDate>
            <atom:updated>2022-08-14T03:29:57.132Z</atom:updated>
            <content:encoded><![CDATA[<p>GIS data is used in many industries mainly for mapping and spatial analyses. The two main types of GIS data are rasters and vectors. If you’re reading this article you likely don’t need an introduction to GIS data, but a brief breakdown is given below.</p><ul><li>Raster files are continuous grid data with a defined resolution usually stored as .tiff, .jpeg, .bmp, or .png. For example, a satellite image georeferenced to a coordinate system is a raster file.</li><li>Vector files are either point, line or polygon features. Most commonly these are stored as shapefiles, but can also be GeoJSON, KML, GML, TIGER or nested inside a geodatabase (GDB)</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/209/1*uJcsbtOkNqbMPOSsTzuOQA.jpeg" /></figure><p>GIS data is inherently complex due to the file format structures and the hundreds reference coordinate systems used. For example, a single polygon shapefile is actually a collection of at minimum (3) files (.shp, .shx and .dbf) with up to (13) other associated filetypes storing various metadata.</p><p>The complexity of these data types requires special consideration when storing the data in a database management system (DBMS). One of the most popular open-source DBMS is PostgreSQL which can store GIS data by installing the PostGIS extension.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/240/1*rKXAftLhcujq-cCFcVNzVw.png" /></figure><h3>Getting Started</h3><p>First you must have PostgreSQL downloaded locally or have access to an instance on a server. This article assumes some experience with Postgres and the associated tools pgAdmin and psql (Shell).</p><p>If you need/want a crash course with Postgres then follow this link: <a href="https://www.postgresql.org/docs/9.4/tutorial-install.html">https://www.postgresql.org/docs/9.4/tutorial-install.html</a>. ←Walks you through the download and creation of your first database.</p><h3>Installing PostGIS Extension</h3><p>Open <em>Application Stack Builder</em> from Windows Start menu.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/518/1*LcbK6uwNSfBr5MOYIkhi9w.png" /></figure><p>Choose the version of PostgreSQL you want to install PostGIS onto.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/573/1*C5UgtyNubDk9ouXlTJllEQ.png" /></figure><p>Click <em>Next</em> and expand the <em>Spatial Extensions</em> tree and choose the latest PostGIS version.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/573/1*W3ymP-YJMxCqIIbDZMI_Zg.png" /></figure><p>You’ll be prompted about various installation parameters during the install, just go with the defaults.</p><h3>Creating a GeoDatabase</h3><p>Once installation is complete open psql (Shell) and login. Make sure you are in the version of Postgres the PostGIS extension was added to.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/624/1*R1JvGRV29gxSGWlUbHIsxQ.png" /><figcaption>log in to psql</figcaption></figure><p>Create a new database, here I call it <em>gis</em>. You’ll see CREATE DATABASE as a callback confirming one has been created.</p><pre>postgres=# CREATE DATABASE gis;<br>CREATE DATABASE</pre><p>Create the PostGIS extension for the new database.</p><pre>postgres=# CREATE EXTENSION postgis;<br>CREATE EXTENSION</pre><p>At this point you have a new database named <em>gis</em> which is populated with the PostGIS extension attributes. You can open the database in pgAdmin and visually inspect the properties.</p><p>There are many functions that are added which allow for specialized GIS queries and, most importantly, there is a table added called <em>spatial_ref_sys</em>. This table contains all of the SRIDs (spatial reference identifier) which you’ll need as a reference for importing GIS data (this will be shown later).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*rC9JjYphG9hfB8kGBurA1g.png" /><figcaption>psql response showing that a table has been added to the database after adding the PostGIS extension</figcaption></figure><h3>Source Some Spatial Data</h3><p>With the database created and configured for GIS we can upload a shapefile to it. I found a shapefile in the public domain which is the 100-year floodplain for Colorado from FEMA (<a href="https://geo.colorado.edu/catalog/47540-5ca228ffd43267000b8c7448">https://geo.colorado.edu/catalog/47540-5ca228ffd43267000b8c7448</a>). Download and extract the files to a separate folder.</p><h3>shp2pgsql Utility</h3><p>When PostGIS was installed it came along with some utilities. One of those utilities is <em>shp2pgsql</em>. This tool is capable of converting a shapefile into a SQL format digestible by Postgres. It will have been placed at <em>C:/Program Files/PostgreSQL/14/bin/shp2pgsql.exe.</em></p><p>Let’s use this tool to convert our shapefile. The first step is to figure out the reference coordinate system for the shapefile. To do this open the .prj file, included in the floodplain download, with a text editor.</p><pre>PROJCS[“NAD_1983_UTM_Zone_13N”,GEOGCS[“GCS_North_American_1983”,DATUM[“D_North_American_1983”,SPHEROID[“GRS_1980”,6378137.0,298.257222101]],PRIMEM[“Greenwich”,0.0],UNIT[“Degree”,0.0174532925199433]],PROJECTION[“Transverse_Mercator”],PARAMETER[“False_Easting”,500000.0],PARAMETER[“False_Northing”,0.0],PARAMETER[“Central_Meridian”,-105.0],PARAMETER[“Scale_Factor”,0.9996],PARAMETER[“Latitude_Of_Origin”,0.0],UNIT[“Meter”,1.0]]</pre><p>Unfortunately this doesn’t include SRID; the information shown is stored in the <em>srtext</em> which is a column of the <em>spatial_ref_sys </em>table in our new database. So, the best approach is to query this table using SQL to find the closest matching SRID.</p><p>Open psql and connect to the <em>gis </em>database. Use the following command format to search the <em>spatial_ref_sys </em>table:</p><pre>SELECT srid, srtext FROM spatial_ref_sys WHERE srtext ILIKE ‘%NAD83 / UTM zone 13n%;’;</pre><p>Doing so shows us:</p><pre>26913 | PROJCS[“NAD83 / UTM zone 13N”,GEOGCS[“NAD83”,DATUM[“North_American_Datum_1983”,SPHEROID[“GRS 1980”,6378137,298.257222101,AUTHORITY[“EPSG”,”7019&quot;]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY[“EPSG”,”6269&quot;]],PRIMEM[“Greenwich”,0,AUTHORITY[“EPSG”,”8901&quot;]],UNIT[“degree”,0.0174532925199433,AUTHORITY[“EPSG”,”9122&quot;]],AUTHORITY[“EPSG”,”4269&quot;]],PROJECTION[“Transverse_Mercator”],PARAMETER[“latitude_of_origin”,0],PARAMETER[“central_meridian”,-105],PARAMETER[“scale_factor”,0.9996],PARAMETER[“false_easting”,500000],PARAMETER[“false_northing”,0],UNIT[“metre”,1,AUTHORITY[“EPSG”,”9001&quot;]],AXIS[“Easting”,EAST],AXIS[“Northing”,NORTH],AUTHORITY[“EPSG”,”26913&quot;]]</pre><p>This tells us that the SRID is 26913. Now we can import the shapefile into our database.</p><p>Open command prompt and <em>cd </em>to the folder containing the shapefile library.</p><pre>cd <em>custompath</em>/Floodplain_Colorado_100yr_Effective_1_28_2016_X2</pre><p>Now you’ll need to point to shp2pgsql, specify the SRID, the file to convert and the name of the resultant sql file. In the code below, the <strong><em>-D</em></strong> specifies ‘<em>dump format</em>’ which speeds up the process, <strong><em>-I</em></strong> creates a geospatial index and after <strong><em>-s</em></strong> is where you define the SRID we found.</p><pre>C:/”Program Files”/PostgreSQL/14/bin/shp2pgsql -D -I -s 26913 Floodplain_Colorado_100yr_Effective_1_28_2016.shp &gt; Floodplain_Colorado_100yr_Effective_1_28_2016.sql</pre><p>After execution of this code you’ll see a new file added to the shapefile directory:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Wkiii4SGORwYvYKD82mHEA.png" /><figcaption>Resultant .sql file created with shp2pgsql</figcaption></figure><h3>Importing the Transformed Shapefile into PostgreSQL</h3><p>Use the command line to import the file to postgres. You’ll be prompted to input your postgres admin password.</p><pre>psql -p 5433 -U postgres -d gis -f Floodplain_Colorado_100yr_Effective_1_28_2016.sql</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*y7HVbWhmdURAn1DziQT5uQ.png" /><figcaption>Output from adding shapefile to Postgres</figcaption></figure><p>Using <em>/dt</em> we can confirm that the shapefile was added as a new table to the <em>gis </em>database.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ItH-Qg1mjhwXeuLUEpbcIQ.png" /></figure><h3>Connecting to QGIS — Adding Layer</h3><p>This tutorial also assumes that you have experience with QGIS which is a freeware GIS solution with a lot of really advanced analytical tools built in.</p><p>Open QGIS and in the browser panel you’ll see PostGIS with the PostgreSQL icon next to it. Right-click on it to add a new connection.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/300/1*HHGFZFjH48l8HQ33LODqXA.png" /><figcaption>Adding a new connection to PostgreSQL from QGIS</figcaption></figure><p>Now add in the appropriate credentials and name the connection, here I chose <em>GIS</em>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/385/1*Byk7VwmQo4I1zrC_hdL_bw.png" /><figcaption>Adding new connection to PostgreSQL</figcaption></figure><p>Once connected you see the database and shapefile added previously.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/509/1*Su3T9kGD41fV_QVVK6QLgA.png" /><figcaption>Browser tree view after PostgreSQL connection</figcaption></figure><p>You can add the shapefile to the project by right-clicking. You’ll be prompted to choose a conversion method from a list of options. It estimates the error margin from each method which is convenient for determining which to choose.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/988/1*H3KyF-OrjmQRyiH_Jxtcqw.png" /><figcaption>Conversion options for importing the SQLized shapefile</figcaption></figure><p>After conversion add the layer onto a basemap to view it.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*nnBMEMA4ZBvvSLL7B3h7wA.png" /><figcaption>View of the Colorado 100-year floodplain layer added from the newly created PostGIS database</figcaption></figure><h3>Adding a Raster File to PostGIS</h3><p>Raster files can be loaded into PostGIS similarly, but using a different tool. The utility needed is in the same bin folder previously described, called, you guessed it, <strong><em>raster2pgsql</em></strong>.</p><p>First download a raster file. I got one from the public domain at: <a href="https://www.naturalearthdata.com/downloads/50m-raster-data/50m-natural-earth-1/">https://www.naturalearthdata.com/downloads/50m-raster-data/50m-natural-earth-1/</a>. At this link I downloaded the <em>Shaded Relief and Water</em> raster.</p><p>The raster file is a .<em>tif </em>file and it comes with a read me that says its coordinate reference system is WGS84 a very commonly used coordinate reference. I happen to know the SRID for this 4326, but you could query the <em>spatial_ref_sys </em>table as before if needed.</p><p>Open the command prompt and <em>cd </em>to the location of the .<em>tif </em>file. Similar to before, enter the path to raster2pgsql followed by cod ein the format below:</p><pre>C:/”Program Files”/PostgreSQL/14/bin/raster2pgsql -I -C -F -s 4326 NE1_50M_SR_W.tif public.shaded_relief_ocean_basemap &gt; shaded_relief_ocean_basemap.sql</pre><p>Here’s a code breakdown:</p><ul><li><strong>-I </strong>: creates a spatial index in the raster table</li><li><strong>-F</strong> : creates a column containing the filename (good for housekeeping)</li><li><strong>-C</strong> : opens constraints for ref coordinate system declaration (-s)</li><li><strong>-s</strong> : followed by an SRID applies the coordinate system to the raster</li><li><strong>public.shaded_relief_ocean_basemap</strong> : This is the &lt;schema&gt;.&lt;table&gt; you want to create when importing to postgres. So you’re seeing me want the table in public schema with an intuitive name</li><li><strong>shaded_relief_ocean_basemap.sql</strong> : this is the SQL dump file created which will be imported to postgres</li></ul><p>After the file is created, upload it to the <em>gis </em>database as before.</p><pre>psql -p 5433 -U postgres -d gis -f shaded_relief_ocean_basemap.sql</pre><p><em>**Note that you will run into an issue if postgis_raster is not added as an extension to your database. To check if it is run \dx in psql. You can easily add it via pgAdmin by right-clicking on extensions in the database tree**</em></p><h4>Congrats, now you have a geodatabase with one shapefile and a raster file which can be connected to QGIS or ArcGIS.</h4><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=bc3c923653ba" width="1" height="1" alt=""><hr><p><a href="https://medium.com/analytics-vidhya/creating-a-geodatabase-with-postgresql-postgi-and-connecting-to-qgis-bc3c923653ba">Creating a GeoDatabase with PostgreSQL/PostGIS and Connecting to QGIS</a> was originally published in <a href="https://medium.com/analytics-vidhya">Analytics Vidhya</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Data Engineering: Automatically Update PostgreSQL Database from API]]></title>
            <link>https://medium.com/analytics-vidhya/data-engineering-automatically-update-postgresql-database-from-api-4f07da1df2a9?source=rss-aab0243a8d9e------2</link>
            <guid isPermaLink="false">https://medium.com/p/4f07da1df2a9</guid>
            <category><![CDATA[data-engineering]]></category>
            <category><![CDATA[etl]]></category>
            <category><![CDATA[postgresql]]></category>
            <category><![CDATA[api]]></category>
            <category><![CDATA[python]]></category>
            <dc:creator><![CDATA[Elii Skeans]]></dc:creator>
            <pubDate>Tue, 19 Jul 2022 20:50:07 GMT</pubDate>
            <atom:updated>2022-07-21T19:27:29.784Z</atom:updated>
            <content:encoded><![CDATA[<h3><strong>Data Engineering: Automatically Update a PostgreSQL Database from an API</strong></h3><p><strong>Prelude</strong></p><p>A data engineer is mainly tasked with extracting data from multiple sources, transforming the data, checking the validity of the data, transforming it for specific uses before finally loading it into a data warehouse for end users to access (a process often described by the acronym ETL). More often than not the data is streaming (updating frequently); so these tasks must be built as scripts and compiled into a ‘pipeline’ which can run automatically at specific intervals.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*3cpObDUhJRgVe0dfn1Xilg.png" /><figcaption>Visualization of a generalized data engineering workflow</figcaption></figure><p>This tutorial shows a simple example of how to extract data from an API, transform it with Python, store it in a local PostgreSQL database and then compile the actions as a pipeline which automatically recurs on a schedule and logs each occurrence.</p><p>This workflow has many applications from small scale personal use up to large scale commercial applications. The actual example I present was chosen to simplify the tutorial and likely doesn’t have much actual utility. Enjoy!</p><p><strong>Description</strong></p><p><strong>Case</strong></p><p>You want to collect intraday stock trade data for stocks in your portfolio to store in your local Postgres database. Maybe you’re interested in developing a machine learning model which attempts to predict the market and you want to build your own data pool rather than buying it from a vendor, or something like that.</p><p><em>**Now, there are a million billion trillion market analysis applications already developed and available for free even so actually doing this would be silly, but that’s our case here. Actually useful cases I can think of are too domain-specific and add too much complexity which would make things a bit thick for most readers.**</em></p><p><strong>Prerequisite Skills &amp; Software</strong></p><ul><li>Development was performed in a Jupyter Notebook (<a href="https://www.anaconda.com/products/distribution">https://www.anaconda.com/products/distribution</a>)</li><li>PostgreSQL (local) is the database (<a href="https://www.postgresql.org/download/">https://www.postgresql.org/download/</a>)</li></ul><p>You should at least be a seasoned beginner with Python and know Pandas to hang here. SQL… you can’t be a data person without SQL, so leave and go do intro tutorials for that, at minimum, before attempting this. This could be your first foray into PostgreSQL, but you should understand relational database theory or else you’ll be quite lost.</p><p><strong>Getting the Data</strong></p><p>Alpha Vantage (<a href="https://www.alphavantage.co/">https://www.alphavantage.co/</a>) offers a free API for intraday stock data; just sign up and receive a free API key. The intraday API offers 1–2 months of historical price and volume data in intervals as low as 1 minute. This will be our data source.</p><p>The API documentation for building queries is found here: <a href="https://www.alphavantage.co/documentation/">https://www.alphavantage.co/documentation/</a></p><p>Data can be accessed as either CSV or JSON, we’ll do JSON to add some complexity (everyone knows how to use CSV data, it’s boring).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*wOuzfLDnV2bz4SKS7cSJtQ.png" /><figcaption>** My API key is chopped from the image…get your own, it’s free **</figcaption></figure><p>Examining the query string for the URL and referencing the API documentation you’ll see that I am requesting intraday data for Tesla (TSLA) at a 1-minute interval.</p><p>Doing this provides JSON data which structurally is a dictionary of dictionaries; one containing metadata and the other containing the time series data with open, close, high and low prices for each minute interval as well as the volume.</p><p>Converting the JSON data to a Pandas data frame lets us examine it visually.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*0I2pFT9WuIkmh5pWl1ZOAg.png" /></figure><p>The meta data offers the description of the data (time interval etc.), the refresh date and the ticker symbol. The time series data clearly needs transforming to be useful. We’ll want the rows switched into columns and the column names changed mainly.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*dW-ODo8sdqSoRZmeZZcXWA.png" /></figure><p>Much better. Since we’ll also we collecting data for multiple stocks (composing a portfolio) an additional column for the ticker symbol should be added as well.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*tx6U8Xc-SXYJRZJEG2bOag.png" /></figure><p>Before we move on from the data set we need to check and transform the data types if needed.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*0vTy4vyaWNM0AH6J1xjorQ.png" /></figure><p>All object (strings) data types, not good. Obviously time should be datetime, volume should be integer and all others (besides ticker) should be floats. Although <em>time</em> should be a datatime data type, we’ll leave it as a string for easier import into Postgres which we’ll get into next.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/939/1*CXeSsjhCNvOP18z7wArHkQ.png" /></figure><h3>PostgreSQL</h3><p>If you haven’t already you’ll need to download and configure PostgreSQL which is a free open-source database management solution. There are two main ways to interact with Postgres: pgadmin and psql (shell). Pgadmin is a GUI for connecting to and managing a Postgres database; psql is a command line prompt for achieving the same goals. You really should be able to use both of these in my opinion to be proficient in Postgres.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/360/1*NxkAA-u3wlH504QCYORVvg.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/312/1*BFUCJ8u7AznlDx6sy7TFvQ.png" /><figcaption>psql shell command prompt</figcaption></figure><p>Once you download PostgreSQL you’ll setup a password for your local server. We’ll mainly use the psql shell to setup a new database for our project.</p><p>Open psql from your start menu. To connect to the server just hit enter to accept the defaults unless you’ve specified otherwise previously. Then you’ll be prompted to enter the password you set up earlier.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*H4pK8zMRtxhU5IhUAK9S0Q.png" /><figcaption>psql shell after connecting to the server successfully</figcaption></figure><p>Next, create a data base with:</p><pre>CREATE DATABASE stocks;</pre><p>If you’re learning PostgreSQL, it’s useful to open pgadmin as well and check that the commands you are performing are actually working. If you do, you’ll see a new database called <em>stocks </em>has been created.</p><p>Now we’ll create a tables, also called stocks, where our data will be housed. This is where your SQL skills come into play. The table should be equivalent to the table you’ve transformed from the JSON data collected via the API.</p><pre>CREATE TABLE IF NOT EXISTS stocks( <br>     ticker VARCHAR(10) NOT NULL, <br>     time TIMESTAMP NOT NULL,<br>     open FLOAT(2),<br>     high FLOAT(2),<br>     low FLOAT(2),<br>     close FLOAT(2),<br>     volume INTEGER<br>);</pre><p>You’ll notice the <em>time </em>column in SQL is defined as <em>TIMESTAMP</em>, Postgres will convert the string timestamp as long as the format is <em>yyyy-mm-dd hh:mm:ss</em>.</p><p>Now there is an empty table called <em>stocks </em>inside of a database called <em>stocks</em>. We will also want an index. Below is the code for establishing a multi-level index which will ensure efficient queries as the database grows in size (a more advanced topic; see: <a href="https://www.timescale.com/blog/select-the-most-recent-record-of-many-items-with-postgresql/">https://www.timescale.com/blog/select-the-most-recent-record-of-many-items-with-postgresql/</a>).</p><pre>CREATE INDEX ix_ticker_time ON stocks (ticker, time DESC);</pre><h3>Connecting to PostgreSQL from Python</h3><p>The next steps are more complex for a Python beginner, but the methodology can be copied easily without knowing exactly what’s going on here (maybe).</p><p>First there are two Python packages I use which are not standard and need installed; pip install if you don’t have them already.</p><ul><li>psycopg2 — a popular tool for connecting to PostgreSQL from Python</li><li>pytz — a package for getting time for specific time zones</li></ul><p>There are (3) main processes needed to achieve our goal at this stage:</p><ol><li>Connect to the PostgreSQL database</li><li>Inject the API data into the <em>stocks </em>table</li><li>Log the successful transaction or capture any errors generated</li></ol><p>We want to achieve these goals programmatically using Python so that we can have a script that runs on a schedule.</p><p>Code below shows how to connect to the database with psycopg2; a tuple of connection parameters is entered into the <em>connect </em>module.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Ap3Y10H8Tq2tzS762WM_sA.png" /><figcaption>Connection to PostgreSQL via psycopg2</figcaption></figure><p>A cursor is needed to allow submission of SQL queries to the connection, see below.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/690/1*cl1KaaXDTBWaASjh8dfKmA.png" /></figure><p>The extras module of psycopg2 will allow for the UPSERT of the data into the empty table (<em>UPSERT is the method of updating a table while avoiding duplication</em>). This module takes (3) arguments which are:</p><ul><li>a cursor for the Postgres connection (created already above)</li><li>a SQL query</li><li>a list of tuples with the collected data</li></ul><p>After you execute the values you must <em>commit </em>the connection to execute the action on the data base.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*W2lsqZMI_x7ZOI0JpFXfBw.png" /><figcaption>Add the API data to the database</figcaption></figure><p>Awesome! Use <em>pgadmin </em>if you want to see that you’ve added the data successfully to your <em>stocks </em>database. This proves the concept and sets up the framework for establishing a script which contains all of these steps which performs all of these steps sequentially in (1) .<em>py </em>file.</p><p>In setting up a singular script we must not forget about an important step which is we want to log our transactions with the database. I’ve wrapped the entire database transaction into a single function. Also included is a try — except block in the advent of an error. A log file is written and saved with a numeric file name representing the NYC time zone of the update.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*kPy8zNwIQSa2DuXAX4eBqA.png" /></figure><p>As stated in the case description we want to cycle through a portfolio of stocks. A for loop is used to cycle through the API queries and concatenate a compiled data frame. All of this is compiled into a single python script which you can view as <em>gist </em>at the end of this article.</p><h3>Scheduling the Job to Run Daily</h3><p>We will set this job to run daily using Windows Task Scheduler. You could have it run in smaller intervals by setting up a <em>cron </em>scheduler alternatively.</p><p>First step is to create a batch file. To do so, open notepad and save a file with .<em>bat </em>extension. Inside of this file write (3) lines as shown below:</p><pre>&quot;C:\Program Files\Python37\python.exe&quot;<br>&quot;C:\your_custom_path\python_file_name.py&quot;<br>pause</pre><p>Obviously change the paths to fit your specific scenario and then follow the next steps outlined below:</p><ol><li>Open Windows Task Scheduler</li><li>in the <em>Action </em>tab choose <em>Create Basic Task</em></li><li>Click <em>Next </em>and choose the time you want the script to run each day</li><li>Click <em>Next </em>and in the <em>program/script</em> box enter the path to your python.exe</li><li>In the <em>Add Arguments</em> box enter the name of the python file you’re scheduling</li><li>In the <em>Start In</em> box enter the path the to python file</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*BGH0IPVn9yMsT2T7W7ue1A.png" /><figcaption>Final step in Task Scheduler process</figcaption></figure><p>Great! Now, every day, you PostgreSQL database will be updated with the minute-by-minute trade data for all stocks in your portfolio.</p><p>I hope that someone somewhere out there in the ether has found this useful.</p><p>Cheers.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/3c014a9be5e091358431d7567dc45057/href">https://medium.com/media/3c014a9be5e091358431d7567dc45057/href</a></iframe><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4f07da1df2a9" width="1" height="1" alt=""><hr><p><a href="https://medium.com/analytics-vidhya/data-engineering-automatically-update-postgresql-database-from-api-4f07da1df2a9">Data Engineering: Automatically Update PostgreSQL Database from API</a> was originally published in <a href="https://medium.com/analytics-vidhya">Analytics Vidhya</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Oilfield Data Analytics: Extract, Transform, Load (ETL) and Decline Curve Analysis (DCA)]]></title>
            <link>https://medium.com/analytics-vidhya/oilfield-data-analytics-extract-transform-load-etl-and-decline-curve-analysis-dca-f9ce7f4c778e?source=rss-aab0243a8d9e------2</link>
            <guid isPermaLink="false">https://medium.com/p/f9ce7f4c778e</guid>
            <dc:creator><![CDATA[Elii Skeans]]></dc:creator>
            <pubDate>Mon, 26 Oct 2020 03:24:03 GMT</pubDate>
            <atom:updated>2020-11-28T02:05:17.157Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/940/1*HOQF7WfY5w-h5cCfh45oHA.jpeg" /></figure><h3><strong>Self Introduction</strong></h3><p>My name is Elii Skeans and I am a reservoir engineer at Surtek. I hold a B.S. Petroleum Engineering from Colorado School of Mines, B.B.A. International Business from the University of Akron and a M.S. Data Analytics from CSU.</p><p>I specialize in compositional numerical modeling for enhanced oil recovery in conventional and unconventional reservoirs, oilfield data analytics and economic modeling for oilfield valuation.</p><p>I have had the luxury in my position so far to perform reservoir simulation on world class assets in South America, Libya, Kuwait, Canada and the U.S.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ngm0Ks8IAa6VciuowZrFSA.png" /></figure><p>Since 1978 Surtek has been a global leader in enhanced oil recovery</p><ul><li>Experience includes all forms of EOR but specialty is in chemical EOR (liquids)</li><li>Laboratory services specialized in EOR, world recognition for EOR coreflooding expertise. (250+ laboratory evaluations)</li><li>Client list includes nation oil companies, major and independent oil companies, and chemical manufacturers. (375+ clients in 25+ countries)</li><li>Most successful Chemical EOR hotspots initiated/assisted by Surtek (China, Wyoming, Canada, Kuwait, etc.)</li><li>30+ years in modeling of EOR technologies. Compositional modeling specialists.</li></ul><h3><strong>Problem Statement</strong></h3><p>Production data is one of the most common datasets that a reservoir engineer will encounter. Every asset I have worked on has had production data in different formats.</p><p>Depending on the type of analysis planned, different formats are needed:</p><ul><li>FHF data for simulation software</li><li>Month normalized data for DCA</li><li>Rates vs. Cums</li><li>Etc.</li></ul><p>Python is the perfect tool to complete the require transformations and code is often reusable.</p><h4><strong>Wyoming Oil &amp; Gas Commission Field Data (WOGC)</strong></h4><p>The example I have built for this exercise involves the extraction of field production data (at the individual well level) for a field in Wyoming called Hartzog Draw.</p><p>The field was chosen for no specific reason other than that it is still active and has many oil-bearing wells.</p><p>Field data is available at <a href="http://pipeline.wyo.gov/FieldMenu2.cfm">http://pipeline.wyo.gov/FieldMenu2.cfm</a> on the WOGC website.</p><p>Unfortunately this data is painful to collect. The screenshot below shows that for each of the ~250 wells in the field I would have to check a box next to the well name. That is a mind numbing task that anyone would hope to avoid.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*iiQfFpzcVdnzVakn8Hp0SA.png" /></figure><h4>There is a better option but it is reserved to only those who know Python or an equivalent tool</h4><p>There is an option to download all of the Wyoming’s historic production data at the well level from the following link: <a href="http://pipeline.wyo.gov/urecordsMenu.cfm?Skip=%27Y%27&amp;oops=ID69217">http://pipeline.wyo.gov/urecordsMenu.cfm?Skip=%27Y%27&amp;oops=ID69217</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/518/1*RCH0XzpyK1ThiWwF29_oyA.png" /></figure><p>The two datasets of interest are the well headers and the well production data. Download both to follow along.</p><p>The first thing you will notice is that the production data comes in (4) CSV files. The next thing you will notice is that Excel crashes when you try to open it because each spreadsheet alone busts the row limit in Excel.</p><p><strong>This is the PERFECT Python example in that you cannot even use Excel if you wanted to.</strong></p><h3><strong>Loading Data</strong></h3><p>For those who are new to Python, Pandas is an absolutely essential package which utilizes data frames which I will abbreviate to <em>df</em> . A great tool for aggregating data is the <em>glob</em> package. Using <em>glob</em> I tell Python to cycle through each file that starts with ‘<em>Counties</em>’.</p><ul><li><strong>As a warning I will tell you that this bit of code takes upwards of 30 minutes to complete. I provide a slice of the data frame that allows for quicker runtimes and less RAM.</strong></li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/98e2e6fe62d873fd1db1303ae3ab6463/href">https://medium.com/media/98e2e6fe62d873fd1db1303ae3ab6463/href</a></iframe><p>We can see from the data frame’s shape that there are 1,490,485 rows in the data set. Printing the head of the df shows us that it is not listed as continuous time series data. <strong>You will notice that there are separate columns for each month and each production fluid.</strong> This means that you cannot plot this data in the current format.</p><p>For this data to be useful it must be transformed. Doing so will explode the number of rows in the dataset. Each row currently represents a year, so <strong>doing a transform will increase the number of rows by 12X</strong>.</p><p>The next dataset we need is the well headers. This is a much more manageable data set with only 142k rows.</p><p>This data table contains the field name for each well which is missing form the production data set.</p><p>We will find the API numbers associated with the field and select only those wells from the total production data set.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c1491fdda04400ee95c46ccfa4eccd47/href">https://medium.com/media/c1491fdda04400ee95c46ccfa4eccd47/href</a></iframe><p>Now our production data set includes only wells in the Hartzog Draw field. The shape of the data frame is shown below and we can see it is now only 7,768 rows long and there are 359 wells included.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/51b7e067bb986535a5fdac6dd3a085b1/href">https://medium.com/media/51b7e067bb986535a5fdac6dd3a085b1/href</a></iframe><h3><strong>Now for the Transform</strong></h3><p>The main tool used here is _melt_ which is included in the Pandas package.</p><p><em>id_vars</em> defines the columns that will remain columns and <em>value_vars</em> are the column you want converted into rows. <em>var_name</em> sets the name of the new row data and <em>value_name</em> sets the name of the newly created column.</p><p>This tool is used to create columns for a new data frame called <em>dfnew</em> which is then reloaded into <em>df_HD_prd.</em></p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a69fb9ff4f94648ba3c8c5f1db6289f1/href">https://medium.com/media/a69fb9ff4f94648ba3c8c5f1db6289f1/href</a></iframe><p><strong>Now that is the format we are all used to and is easy to work with.</strong></p><p>This completes the ETL protion of the webinar. The idea here was to show how Python can save you time and effort in loading, manipulating and transforming data into formats that are useable in your work flow. Each data transformation is unique requiring the development of unique code. This example should show some of the basic functionalities of Pandas in Python.</p><h3>Decline Curve Analysis (DCA)</h3><p>If you are watching this webinar then surely you are familiar with Arp’s equation for decline curve analysis. This is the most basic tool used in estimating the future performance of a well.</p><p><strong>Arp’s Equation for Hyperbolic Decline</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*SZ04UBlje0M0ry9iF6xX_A.png" /></figure><p>Typically DCA is done using commercial software. That software is expensive and a lot of smaller companies limit their access to these tools due to cost especially with the market today. This workflow is more to showcase the capabilities of Python and how it can boost your workflow to the next level.</p><p>In this section I’ll introduce two new packages that we’ll combine together in this analysis; <strong>Plotly</strong> and <strong>SciPy</strong>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/696/1*ytByFk8oa_ewf-tT8-mj_g.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-HuLB1OI2gwrIzWmHOSI9w.png" /></figure><p>Plotly is a package for making interactive plots. We are going to be using an extension called <em>plotly.express</em> which still blows my mind at how easy it is to use. In the next section I make an interactive scatter plot in one line using 46 characters.</p><p>SciPy is an essential package in Python that acts as an ecosystem for hundreds of pre-defined mathematical operations typical in science and engineering. Optimization is listed as one of the main competencies of SciPy along with numerical integration, interpolation, linear algebra, and statistics.</p><p>We want to create a function that fits a decline curve using Arp’s equation. We also want to be able to view the decline fit in real time and manipulate the variables as needed. So Plotly will show us the results and let us interact with them and SciPy will run code to generate a best fit to our data.</p><h3><strong>Plotting</strong></h3><p>Let’s make a simple plot of the production of some random well.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/5374d0b5dc3630f8c37bbcad9a4fc1fc/href">https://medium.com/media/5374d0b5dc3630f8c37bbcad9a4fc1fc/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ayRzsFJSImBQRx39aTxWfw.gif" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*xnqKmI26c7gX1P6-0gMPUQ.gif" /></figure><p>Great. Now it looks like there has been some recompletions or well workover done around 2017 so lets grab a decline off of that.</p><p>To do so we’ll have to subset the data. I’ll just manually enter a date as a variable in prewritten code.</p><h3><strong>Fitting the Data</strong></h3><p>Now we will create a function that contains the various permutations of Arp’s equation. I want my function to be able to fit an exponential, hyperbolic, or harmonic decline.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/0afefdccbb5ff648e55c186f3dd8dc5c/href">https://medium.com/media/0afefdccbb5ff648e55c186f3dd8dc5c/href</a></iframe><p>With the function built we can load the production data into the algorithm.</p><p>Below I sort the df by date, then reset the index which creates a new index from 0 to len(df). Now my x values are the df.index numbers and my y data is the oil rate. You must provide a starting point for the optimization variables to the algorithm which is what I am doing with <em>p0</em></p><p>The optimize function outputs (2) arrays. One contains the fitted values for variables and the other is a covariance array. I’ll print the popt list to see the values for b, Qi, and Di.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d4b8fab2dd2f5be927d1e991528d3106/href">https://medium.com/media/d4b8fab2dd2f5be927d1e991528d3106/href</a></iframe><p>Neat. Now I want to plot all of this. First lets create a new data frame for the fit data. We’ll pass the fitted variables into the dca() function to create a decline that goes out 20 years into the future. We will also set an economic limit, below this number the well will be shut in.</p><p>We might as well output the expected remaining production for the well to assign a PDP value as well.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*iCPzmzpAVnE9QhQOtJhzCg.png" /></figure><p>The code below is plotting the decline data onto the total production history.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f070d6258ac2778a64dea5d4403bdfef/href">https://medium.com/media/f070d6258ac2778a64dea5d4403bdfef/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*d95-27kAMMpno16ZeldMcA.png" /></figure><p>Now we have reached the conclusion. DCA was applied to a well in an automated way that was then tweaked manually for a better fit. The data was then analyzed to determine the PDP (proved-developed-producing) from the remaining life of the well.</p><p>Find the GitHub repo @: <a href="https://github.com/es42289/HackerVillage_1">https://github.com/es42289/HackerVillage_1</a></p><p>Feel free to reach out to me for any clarifications or requests regarding this post at es42289@gmail.com.</p><p>Cheers,</p><p>Elii</p><h3><strong>BONUS</strong></h3><p>How cool would and interactive tool with a dropdown menu to cycle through each well be? The answer is very cool. I won’t add any discourse here to support this but below is code to make the same charts with a dropdown for each well. Also included in the code is an automated DCA applied to each well (which it does unsuccessfully).</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/cdeff24d50f5ddb71b5404f1883513fd/href">https://medium.com/media/cdeff24d50f5ddb71b5404f1883513fd/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*6unun_HjZwWkcJFvoJwFxA.gif" /></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f9ce7f4c778e" width="1" height="1" alt=""><hr><p><a href="https://medium.com/analytics-vidhya/oilfield-data-analytics-extract-transform-load-etl-and-decline-curve-analysis-dca-f9ce7f4c778e">Oilfield Data Analytics: Extract, Transform, Load (ETL) and Decline Curve Analysis (DCA)</a> was originally published in <a href="https://medium.com/analytics-vidhya">Analytics Vidhya</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Data Analytics for Life Optimization: Buying a Car]]></title>
            <link>https://medium.com/analytics-vidhya/data-analytics-for-life-optimization-buying-a-car-3540870b7a08?source=rss-aab0243a8d9e------2</link>
            <guid isPermaLink="false">https://medium.com/p/3540870b7a08</guid>
            <category><![CDATA[pandas]]></category>
            <category><![CDATA[scraping]]></category>
            <category><![CDATA[web-scraping]]></category>
            <category><![CDATA[scrapy]]></category>
            <category><![CDATA[python]]></category>
            <dc:creator><![CDATA[Elii Skeans]]></dc:creator>
            <pubDate>Tue, 03 Mar 2020 20:39:34 GMT</pubDate>
            <atom:updated>2020-03-09T08:28:22.950Z</atom:updated>
            <content:encoded><![CDATA[<p>Several months ago I was interested in purchasing a new car. Specifically, I wanted to buy a Jeep for off-roading in the summer. I was more interested in buying a used Jeep with some modifications (lift kit, larger tires, winch, etc.). Jeeps are very popular in Colorado and as a result the market for them is high volume with quick turnaround. This makes it hard to analyze all of the options on the market in a time-effective way.</p><p>I was in no hurry to buy a car and wanted to make sure that when I bought it I was getting a good deal. It can be pretty hard to compare value across Jeeps with all kinds of different features and modifications; there is no clear market value like new cars have.</p><p>To do this I needed to think of some way to automate a daily search which identifies features I value and presents them with easily digestible graphs and charts. This way I would save countless hours of scrolling through ads and prevent myself from making a brash decision because I was fed up with the search.</p><h3><strong>Automating the Search</strong></h3><p>All of my future potential Jeeps are listed on the internet and the posts are changing daily due to the high volume of sales. I needed to automate a search, extract data from the search results, store the data, run analytics, and then output useful graphs.</p><h3><strong>Identifying Features</strong></h3><p>First, I needed to know what information I wanted to search for and collect. The following parameters are what I chose:</p><p>· Miles driven</p><p>· Model Year</p><p>· Make/Model</p><p>· Location</p><p>· Date Posted</p><p>· Price (&lt;$20,000)</p><h3><strong>Scraping</strong></h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/462/1*V8BzhrqA3Be0pYc5TdN7bg.png" /></figure><p>I like to buy cars from Craigslist.org, so this was the website I needed my code to search. I knew that there were multiple web scraping tools available in the wonderful and labyrinth-like world of Python packages. I decided to use Scrapy which is self-described as “An open source and collaborative framework for extracting the data you need from websites. In a fast, simple, yet extensible way.”</p><p>When you search on Craiglist for something you can examine how the url changes for each search page and notice that it is a regular expression (meaning it follows a pattern). Recognizing this was the key to building the web-crawling ‘spider’. The basic tasks my spider accomplished were:</p><p>· Search ‘Jeep’ on craigslist at a 100 mile radius around Denver</p><p>· Extract the title, price, mileage, odometer, year, and make from the listing</p><p>· Output the results to a file</p><p>On a Craigslist search page there are tiles for each posting. The spider had to ‘crawl’ across each one of them to get the data I wanted. Luckily each add is labeled with regular html tags which can be searched. For example, the price is located at xpath: ‘///span[@class=”result-price”]/text()’. Each of my variables has its own common tag which I can search for and output sequentially to a text document. Not being a web developer can make this part of the code pretty tricky, but if you are interested in seeing what I am talking about, go to any website and right-click and choose ‘Inspect Element’. If you hover around in the html code you can find the part of the webpage you are interested in, then you can right-click again to copy the xpath.</p><h3><strong>Scrapy Code</strong></h3><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f9c05e8fd5bb29516332e5e1893b2b50/href">https://medium.com/media/f9c05e8fd5bb29516332e5e1893b2b50/href</a></iframe><h3><strong>Data Analysis</strong></h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/1*IEEBG9bFqSLd_dkAV8oLiw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/542/1*OF13NAbtSTcszGroz_IjfQ.png" /></figure><p>Now we have this text file built as a table with the output of the days search for Jeeps. Next, I have a separate code which I run in Jupyter Notebook to analyze the data. The main libraries used for this task are <strong>pandas</strong> and <strong>matplotlib</strong>.Pandas is an absolutely essential data science library for python and matplotlib is a robust visualization package for making graphs.</p><p>The most basic analysis I ran was price by year shown in this figure:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1015/1*Qs74ip67-hA6uA-28VXQ5w.jpeg" /></figure><p>This chart tells me a number of things even though it is pretty basic. (1) There are more newer Jeeps than older ones for sale. This is expected since cars tend to die after 20–30 years or so of use. (2) The oldest Jeeps are the most expensive. This is also logical given that a 1960 Jeep must have had extensive renovations and may be a collectors item as well.</p><p>There are several Jeep models to choose from; Wrangler, Cherokee, Commander, Liberty, etc. I was mostly interested in finding either a Cherokee or a Wrangler so I split the dataset into three categories:</p><p>· Wrangler</p><p>· Cherokee</p><p>· Other</p><p>Plotting the same graph for each category gives further insight:</p><p>The next figure provides additional useful information for each type. The conclusions are that Wranglers are more expensive than Cherokees on average and that both are more expensive than other types of Jeeps.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*0TWGOhW3e8S6VZtoasOV1w.jpeg" /></figure><p>Another important parameter to consider was the odometer reading for each car. To plot this I decided to segment the ads into three odometer ranges:</p><p>· 0–50k miles</p><p>· 50–100k miles</p><p>·100–150k miles</p><p>I wasn’t interested in cars with more than 150k miles on the engine so this worked well. Plotting Wrangler and Cherokee separately for price by year and coloring by odometer range outputs the next figure:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*pJFhvIOh3rQSL1CNFsVRWg.jpeg" /></figure><p>From this we see that:</p><p>· Jeeps with less miles are newer</p><p>· Most have over 100k miles</p><p>· There are few Wranglers under $20k with less than 100k miles</p><p>· Cherokees with less than 100k miles tend to be newer than Wranglers with the same mileage</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1006/1*NzG-ekRHrMUc95nuuHdp4Q.jpeg" /><figcaption>3D Scatter plot of Odometer by Year by Price</figcaption></figure><p>It is easier to analyze the data all on one graph, so I decided to plot a 3D scatter chart for each odometer range by price by year and colored by model. In Figure 4 we see the output for this idea. From this we see that the quantity of Jeeps decreases with less mileage and that there is an inverse relationship between price and mileage. My ideal purchase would be a Wrangler with less than 100k miles and less than $15,000. With this in mind, my target is the middle of the far right cluster for potential purchases.</p><p>Running my web-crawler and analyzing the graphs led me to my final decision after about 3 months. I’ve been more than pleased with my final purchase and had a lot of fun building my python skills while solving a real life problem.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/451/1*OcOfoFBXGExjFzz_8-4yIg.png" /><figcaption>Final Purchase</figcaption></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=3540870b7a08" width="1" height="1" alt=""><hr><p><a href="https://medium.com/analytics-vidhya/data-analytics-for-life-optimization-buying-a-car-3540870b7a08">Data Analytics for Life Optimization: Buying a Car</a> was originally published in <a href="https://medium.com/analytics-vidhya">Analytics Vidhya</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Visualizing Reservoir Data with Plotly by Elii Skeans]]></title>
            <link>https://medium.com/analytics-vidhya/visualizing-reservoir-data-with-plotly-a03c754c940d?source=rss-aab0243a8d9e------2</link>
            <guid isPermaLink="false">https://medium.com/p/a03c754c940d</guid>
            <category><![CDATA[reservoir-engineering]]></category>
            <category><![CDATA[reservoir]]></category>
            <category><![CDATA[petroleum-engineering]]></category>
            <category><![CDATA[oil-and-gas]]></category>
            <category><![CDATA[petroleum]]></category>
            <dc:creator><![CDATA[Elii Skeans]]></dc:creator>
            <pubDate>Fri, 21 Feb 2020 03:32:14 GMT</pubDate>
            <atom:updated>2020-03-06T08:17:11.271Z</atom:updated>
            <content:encoded><![CDATA[<h3>Visualizing Reservoir Data with Plotly</h3><p>Volve is an oil field located on the Norwegian continental shelf. The field was discovered in 1993, but production did not begin until 2008. Equinor (formally known as Statoil) was the majority stake operator of the field. Approximately 63 million barrels of oil were produced from the field with peak rates reaching 56Mbpd before being shutdown in 2016.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/850/1*mim8WPT9P8s0jLL8hT7VNA.png" /><figcaption>Field Location (Filho, Meles, Curtis, &amp; Ravasi, 2017)</figcaption></figure><p>In 2018, Equinor took the unprecented step of releasing all associated files used in the management and development of the field. Files include seismic, drilling, production, dynamic model, PVT, and many other types of data. The purpose of the release was to add a comprehensive and rich data set for use in academia to bolster the next generation of engineers. The data can be found here: <a href="https://www.equinor.com/en/how-and-why/digitalisation-in-our-dna.html">https://www.equinor.com/en/how-and-why/digitalisation-in-our-dna.html</a></p><p>Historically this type of reservoir data has been read and analyzed within commercial software packages. Programs like Petra, Landmark, or Petrel are very powerful and very, very expensive. Licenses for these softwares can run thousands of dollars a month. This expense is justifiable for large corporations, but out of reach for individuals outside of these companies.</p><p>The purpose of this article is to show open source methods for visualizing the Volve reservoir data using Plotly and Python.</p><p>A plethora of data is available but we will focus on surface data for the Ty, Hugin, and Shetland formations along with the well data. The formation top data is found in the Geophysical Interpretations data set.</p><p>First let’s explore the data.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/ede83f7553b941885ea57a9b115bbe28/href">https://medium.com/media/ede83f7553b941885ea57a9b115bbe28/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*hzGRUBCTvrsqjUKDIjZGoA.png" /><figcaption>The well data set from <em>wells.csv</em></figcaption></figure><p>The well data has latitudes, longitudes, depths, and perforation information. The horizon files all contain just three columns: latitude, longitude, and depth.</p><p>Let’s plot the well locations on a simple scatter plot just to get the orientation of the wells.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/5044c8c2b2046540342e3466f9c9a740/href">https://medium.com/media/5044c8c2b2046540342e3466f9c9a740/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*admv5XGQb-jO41wdFOy-FA.png" /><figcaption>Scatter plot of well locations. Axes are in UTM system meters</figcaption></figure><p>This is slightly useful in that it shows the general location of the wells compared to each other.</p><p>To make things a little more fancy we can create a meshgrid that interpolates values between known depths of the wells to create a contour plot.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b078f870bd35370af56c265b1adc9399/href">https://medium.com/media/b078f870bd35370af56c265b1adc9399/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2PrnX2BRp1YsqMZJdSc0DQ.png" /><figcaption>Well location scatter plot showing a contour plot of the well locations. Lighter colors are shallower.</figcaption></figure><p>This provides some extra insight to the reservoir structure. We can see one outlier well off to the west which could be a disposal well or a dry hole at a much deeper depth and we see some wells in what might be the crestal region of the field.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b8a87aa7be255e159460b8729273d80c/href">https://medium.com/media/b8a87aa7be255e159460b8729273d80c/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/866/1*kffb2bA9av1IQ-oIZwpfxg.png" /><figcaption>3D scatter of the total well depths. Axes are in meters.</figcaption></figure><p>Plotting things in 3D gets us closer towards having something useful to visualize. Let’s set the well data aside and incorporate the formation tops to get some structure.</p><p>We want to make 3D surface plots here so we need to make a smooth and continuous surface from the simple formation top data. The data is robust enough to give us a pretty picture. We are using the surface function from Plotly graph_objects which gives us some cool features out of the box including contour and spike lines.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f49164ab227cfdc3d441639372a0ab50/href">https://medium.com/media/f49164ab227cfdc3d441639372a0ab50/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Mk63WO-gcfKvqHWdbeHZ4A.gif" /></figure><p>Now we really have something useful and pretty cool to play with also. The graph is interactive showing contour lines, spike lines, and a hover text with location and layer data.</p><p>Now let’s get the well bores plotted showing the perforation intervals in red so we can see where the producing formation is.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b5d94dd3a3d763e24d51fa8b91489e9c/href">https://medium.com/media/b5d94dd3a3d763e24d51fa8b91489e9c/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2dTonaUNfcOdYxwAvHCQ-Q.png" /></figure><p>Now we can see the wellbores in the main crestal region of the Hugin formation. If we remove the other layers we can get a cleaner image of the in the main target formation.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/47fe5a093fe57669af40ae449c6c5723/href">https://medium.com/media/47fe5a093fe57669af40ae449c6c5723/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*WtbgrhsI83WZlNBAZ0at6g.png" /><figcaption>3D surface plot of Hugin reservoir in the Volve field with wellbores and perforations using Plotly</figcaption></figure><p>A fully interactive version of this plot can be found at <a href="https://es42289.github.io/Volve_Hugin">https://es42289.github.io/Volve_Hugin</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a03c754c940d" width="1" height="1" alt=""><hr><p><a href="https://medium.com/analytics-vidhya/visualizing-reservoir-data-with-plotly-a03c754c940d">Visualizing Reservoir Data with Plotly by Elii Skeans</a> was originally published in <a href="https://medium.com/analytics-vidhya">Analytics Vidhya</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>