<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Anna Zubova</title>
    <description>The latest articles on DEV Community by Anna Zubova (@annazubova).</description>
    <link>https://dev.to/annazubova</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F158190%2F2cc45ff0-d045-41dc-931b-2676844560fa.png</url>
      <title>DEV Community: Anna Zubova</title>
      <link>https://dev.to/annazubova</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/annazubova"/>
    <language>en</language>
    <item>
      <title>SOLID Programming (Part 2): Open/Closed Principle</title>
      <dc:creator>Anna Zubova</dc:creator>
      <pubDate>Fri, 27 Sep 2019 14:22:00 +0000</pubDate>
      <link>https://dev.to/annazubova/solid-programming-part-2-open-closed-principle-3ddj</link>
      <guid>https://dev.to/annazubova/solid-programming-part-2-open-closed-principle-3ddj</guid>
      <description>&lt;p&gt;‘O’ in SOLID stands for Open/Closed Principle. It is closely related to the Single Responsibility Principle as code written with Single Responsibility in mind tends to comply with the Open/Closed Principle too.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Open/Closed Principle says that the code should be open for extension but closed for modification&lt;/strong&gt;. In other words, the code should be organized in such a way that new modules can be added without modifying the existing code.&lt;/p&gt;

&lt;p&gt;Let’s look at an example of the function that counts words in a text after extracting it in a local file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;count_word_occurrences&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;localfile&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"r"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
 &lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;counter&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But what if we wanted to extract content from other source, like for example a url? If we worked with the above function, to implement new functionality, we would need to modify the existing function which would go against the Open/Closed Principle.&lt;/p&gt;

&lt;p&gt;The better way of organizing the code would be the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;read_localfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s"&gt;'''Read file'''&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"r"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;count_word_occurrences&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s"&gt;'''Count number of word occurrences in a file'''&lt;/span&gt;

    &lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;counter&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way, if we wanted to add reading from url functionality, we would just add the function that extracts text from url:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;bs4&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;urllib.request&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;urlopen&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_text_from_url&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s"&gt;'''Extract html as string from given url'''&lt;/span&gt;
    &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;urlopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;soup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;soup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_text&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next we would just call the already existing function &lt;code&gt;count_word_occurrences()&lt;/code&gt; with the content extracted using &lt;code&gt;get_text_from_url()&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_text_from_url&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'https://en.wikipedia.org/wiki/Main_Page'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;count_word_occurrences&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'and'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So we added new functionality to the code without needing to modify the existing code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Code in GitHub
&lt;/h3&gt;

&lt;p&gt;You can find the code for this article in this GitHub repository:&lt;br&gt;
&lt;a href="https://github.com/AnnaLara/SOLID_blogposts"&gt;https://github.com/AnnaLara/SOLID_blogposts&lt;/a&gt;&lt;/p&gt;

</description>
      <category>solidprogramming</category>
      <category>python</category>
    </item>
    <item>
      <title>SOLID Programming (Part 1): Single Responsibility Principle</title>
      <dc:creator>Anna Zubova</dc:creator>
      <pubDate>Sat, 21 Sep 2019 10:43:34 +0000</pubDate>
      <link>https://dev.to/annazubova/solid-programming-part-1-single-responsibility-principle-1ki6</link>
      <guid>https://dev.to/annazubova/solid-programming-part-1-single-responsibility-principle-1ki6</guid>
      <description>&lt;p&gt;SOLID principles are among the most valuable in Software Engineering. They allow to write code that is clean, scalable and easy to extend. In this series of posts I will explain what each of the principles is and why it is important to apply.&lt;/p&gt;

&lt;p&gt;Some people believe that SOLID is only applicable to OOP, while in reality most of its principles can be used in any paradigm.&lt;/p&gt;

&lt;p&gt;‘S’ in SOLID stands for &lt;strong&gt;single responsibility&lt;/strong&gt;. The error of many novice programmers is to write complex functions and classes that do a lot of things. However, according to the Single Responsibility Principle, a module, a class or a function has to only do one thing. In other words, they have to have only one responsibility. This way the code is more robust, easier to debug, read and reuse.&lt;/p&gt;

&lt;p&gt;Let’s look at this function that takes a word and a file path as parameters and returns a ratio of number of the word's occurrences in the text to the total number of words.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;percentage_of_word&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;search&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;search&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;search&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"r"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;words&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;number_of_words&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;words&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;occurrences&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;words&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;search&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;occurrences&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;occurrences&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;number_of_words&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code does many things in one function: reads file, calculates number of total words, number of word's occurrences, and then returns the ratio.&lt;/p&gt;

&lt;p&gt;If we want to follow the Single Responsibility Principle, we can substitute it with this code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;read_localfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s"&gt;'''Read file'''&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"r"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;number_of_words&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s"&gt;'''Count number of words in a file'''&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;count_word_occurrences&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s"&gt;'''Count number of word occurrences in a file'''&lt;/span&gt;

    &lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;counter&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;percentage_of_word&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s"&gt;'''Calculate ratio of number of word occurrences to number of all words in a text'''&lt;/span&gt;

    &lt;span class="n"&gt;total_words&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;number_of_words&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;word_occurrences&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;count_word_occurrences&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;word_occurrences&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;total_words&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;percentage_of_word_in_localfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s"&gt;'''Calculate ratio of number of word occurrences to number
       of all words in a text file'''&lt;/span&gt;

    &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;read_localfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;percentage_of_word&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now each function does only one thing. The first one reads the file. The second one calculates the total number of words. There is a function that calculates the number of occurrences of a word in a text. Another function calculates the ratio of word's occurrences to total number of words. And if to get this ratio we prefer to pass the file path instead of text as a parameter, there is a function for that specifically.&lt;/p&gt;

&lt;p&gt;So what are we gaining restructuring the code this way?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The functions are easily &lt;strong&gt;reusable&lt;/strong&gt; and can be mixed depending on the task, thus making the code easily &lt;strong&gt;extendable&lt;/strong&gt;. For example, if we wanted to calculate the frequency of a word in a text that is contained in a AWS S3 bucket instead of a local file, we just need to write a new function &lt;code&gt;read_s3&lt;/code&gt;, the rest of the code would work without modification.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The code is &lt;strong&gt;DRY&lt;/strong&gt;. No code is repeated, so if we need to make a modification in one of the functions, we would only need to do it in one place.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The code is &lt;strong&gt;clean, organized and very easy to read and understand&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We can write &lt;strong&gt;tests for each function separately&lt;/strong&gt;, so it is easier to debug the code. You can check out tests for these functions &lt;a href="https://github.com/AnnaLara/SOLID_blogposts/blob/master/tests.py"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Code in GitHub
&lt;/h3&gt;

&lt;p&gt;The code and tests from this article are available in GitHub:&lt;br&gt;
&lt;a href="https://github.com/AnnaLara/SOLID_blogposts"&gt;https://github.com/AnnaLara/SOLID_blogposts&lt;/a&gt;&lt;/p&gt;

</description>
      <category>solidprogramming</category>
      <category>oop</category>
      <category>python</category>
      <category>drycode</category>
    </item>
    <item>
      <title>Introduction to Web Scraping with Selenium And Python</title>
      <dc:creator>Anna Zubova</dc:creator>
      <pubDate>Thu, 12 Sep 2019 14:57:36 +0000</pubDate>
      <link>https://dev.to/annazubova/introduction-to-web-scraping-with-selenium-and-python-4p7b</link>
      <guid>https://dev.to/annazubova/introduction-to-web-scraping-with-selenium-and-python-4p7b</guid>
      <description>&lt;p&gt;Web scraping is a fast, affordable and reliable way to get data when you need it. What is even better, the data is usually up-to-date. Now, bear in mind that when scraping a website, you might be violating its usage policy and can get kicked out of it. While scraping is mostly legal, there might be some exceptions depending on how you are going to use the data. So make sure you do your research before starting. For a simple personal or open-source project, however, you should be ok. &lt;/p&gt;

&lt;p&gt;There are many ways to scrape data, but the one I prefer the most is to use &lt;a href="https://www.seleniumhq.org/" rel="noopener noreferrer"&gt;Selenium&lt;/a&gt;. It is primarily used for testing as what it basically does is browser automation. In simple language, it creates a robot browser that does things for you: it can get HTML data, scroll, click buttons, etc. The great advantage is that we can tell specifically what HTML data we want so we can organize and store it appropriately.&lt;/p&gt;

&lt;p&gt;Selenium is compatible with many programming languages, but this tutorial is going to focus on Python. Check &lt;a href="https://selenium-python.readthedocs.io/index.html" rel="noopener noreferrer"&gt;this link&lt;/a&gt; to read Selenium (with Python) documentation.&lt;/p&gt;

&lt;h3&gt;
  
  
  First Steps
&lt;/h3&gt;

&lt;p&gt;To download Selenium use this simple command in your command line:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;pip install selenium&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If you are working in a Jupyter Notebook, you can do it right there instead of the command line. Just add an exclamation mark in the beginning:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;!pip install selenium&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;After that all you need to do is import the necessary modules:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;from selenium.webdriver import Chrome, Firefox&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Other browsers are also supported but these two are the most commonly used.&lt;/p&gt;

&lt;p&gt;Two simple commands are needed to get started:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;browser = Firefox()&lt;/code&gt;&lt;br&gt;
(or &lt;code&gt;browser = Chrome()&lt;/code&gt; depending on your preference)&lt;/p&gt;

&lt;p&gt;This creates an instance of a Firefox WebDriver that will allow us to access all its useful methods and attributes. We assigned it to the variable &lt;code&gt;browser&lt;/code&gt; but you are free to choose your own name. A new blank window of the Firefox browser will be automatically opened.&lt;/p&gt;

&lt;p&gt;Next get the URL that you want to scrape:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;browser.get('https://en.wikipedia.org/wiki/Main_Page')&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;get()&lt;/code&gt; method will open the URL in the browser and will wait until it is fully loaded. &lt;/p&gt;

&lt;p&gt;Now you can get all the HTML information you want from this URL.&lt;/p&gt;
&lt;h3&gt;
  
  
  Locating Elements
&lt;/h3&gt;

&lt;p&gt;There are different ways to locate elements with Selenium. Which is the best one, depends on the HTML structure of the page you are scraping. It can be tricky to figure out what is the most efficient way to access the element you want. So take your time and inspect the HTML carefully.&lt;/p&gt;

&lt;p&gt;You can either access a single element with a chosen search parameter (you will get the first element that corresponds to your search parameter) or all the elements that match the search parameter. To get a single one use these methods:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;find_element_by_id()&lt;/code&gt;&lt;br&gt;
&lt;code&gt;find_element_by_name()&lt;/code&gt;&lt;br&gt;
&lt;code&gt;find_element_by_xpath()&lt;/code&gt;&lt;br&gt;
&lt;code&gt;find_element_by_link_text()&lt;/code&gt;&lt;br&gt;
&lt;code&gt;find_element_by_partial_link_text()&lt;/code&gt;&lt;br&gt;
&lt;code&gt;find_element_by_tag_name()&lt;/code&gt;&lt;br&gt;
&lt;code&gt;find_element_by_class_name()&lt;/code&gt;&lt;br&gt;
&lt;code&gt;find_element_by_css_selector()&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;To locate multiple elements just substitute &lt;code&gt;element&lt;/code&gt; with &lt;code&gt;elements&lt;/code&gt; in the above methods. You will get a list of WebDriver objects located by this method.&lt;/p&gt;
&lt;h3&gt;
  
  
  Scraping Wikipedia
&lt;/h3&gt;

&lt;p&gt;So let’s see how it works with the already mentioned Wikipedia page &lt;a href="https://en.wikipedia.org/wiki/Main_Page" rel="noopener noreferrer"&gt;https://en.wikipedia.org/wiki/Main_Page&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We have already created &lt;code&gt;browser&lt;/code&gt; variable containing an instance of the WebDriver and loaded the main Wikipedia page.&lt;/p&gt;

&lt;p&gt;Let’s say we want to access the list of languages that this page can be translated to and store all the links to them. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F0t5yfmelqetofksexffu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F0t5yfmelqetofksexffu.png" alt="'languages'"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After some inspection we can see that all elements have a similar structure: they are &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt; elements of class &lt;code&gt;'interlanguage-link'&lt;/code&gt; that contain &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; with a URL and text:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;li class="interlanguage-link interwiki-bg"&amp;gt;

   &amp;lt;a href="https://bg.wikipedia.org/wiki/" title="Bulgarian"
   lang="bg" hreflang="bg" class="interlanguage-link-target"&amp;gt;

       Български

   &amp;lt;/a&amp;gt;

&amp;lt;/li&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;So let’s first access all &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt; elements. We can isolate them using class name:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;languages = browser.find_elements_by_class_name('interlanguage-link')&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;languages&lt;/code&gt; is a list of WebDriver objects. If we print the first element of it with: &lt;/p&gt;

&lt;p&gt;&lt;code&gt;print(languages[0])&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;It will print something like this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;selenium.webdriver.firefox.webelement.FirefoxWebElement (session="73e70f48-851a-764d-8533-66f738d2bcf6", element="2a579b98-1a03-b04f-afe3-5d3da8aa9ec1")&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;So to actually see what’s inside, we will need to write a for loop to access each element from the list, then access it’s &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; child element and get &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt;'s text and &lt;code&gt;'href'&lt;/code&gt; attribute.&lt;/p&gt;

&lt;p&gt;To get the text we can use &lt;code&gt;text&lt;/code&gt; attribute. To get the &lt;code&gt;'href'&lt;/code&gt; use &lt;code&gt;get_attribute('attribute_name')&lt;/code&gt; method. So the code will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;language_names = [language.find_element_by_css_selector('a').text 
                 for language in languages]

links = [language.find_element_by_css_selector('a').get_attribute('href') 
        for language in languages]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can print out &lt;code&gt;language_names&lt;/code&gt; and &lt;code&gt;links&lt;/code&gt; to see that it worked.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scrolling
&lt;/h3&gt;

&lt;p&gt;Sometimes not the whole page is loaded from the start. In this case we can make the browser scroll down to get HTML from the rest of the page. It is quite easy with &lt;code&gt;execute_script()&lt;/code&gt; method that takes JavaScript code as a parameter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;scroll_down = "window.scrollTo(0, document.body.scrollHeight);"
browser.execute_script(scroll_down)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;scrollTo(x-coord, y-coord)&lt;/code&gt; is a JavaScript method that scrolls to the given coordinates. In our case we are using &lt;code&gt;document.body.scrollHeight&lt;/code&gt; which returns the height of the element (in this case &lt;code&gt;body&lt;/code&gt;). &lt;/p&gt;

&lt;p&gt;As you might have guessed, you can make the browser execute all kind of scripts with &lt;code&gt;execute_script()&lt;/code&gt; method. So if you have experience with JavaScript, you have a lot of room to experiment.&lt;/p&gt;

&lt;h3&gt;
  
  
  Clicking
&lt;/h3&gt;

&lt;p&gt;Clicking is as easy as selecting an element and applying &lt;code&gt;click()&lt;/code&gt; method to it. In some cases if you know the URLs that you need to go to, you can make the browser load the page with URLs. Again, see what is more efficient.&lt;/p&gt;

&lt;p&gt;To give an example of the &lt;code&gt;click()&lt;/code&gt; method, let’s click on the 'Contents' link from the menu on the left. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F9i2ajnasq8xcspw4ni1p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F9i2ajnasq8xcspw4ni1p.png" alt="'contents'"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The HTML of this link is the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;li id="n-contents"&amp;gt;
   &amp;lt;a href="/wiki/Portal:Contents" title="Guides to browsing Wikipedia"&amp;gt;

        Contents

   &amp;lt;/a&amp;gt;
&amp;lt;/li&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have to find the &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt; element with the unique id &lt;code&gt;'n-contents'&lt;/code&gt; first and then access its &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; child&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;content_element = browser.find_element_by_id('n-contents') \
                         .find_element_by_css_selector('a')

content_element.click()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see now that the browser loaded the 'Contents' page.&lt;/p&gt;

&lt;h3&gt;
  
  
  Downloading Images
&lt;/h3&gt;

&lt;p&gt;Now what if we decide to download images from the page. For this we will use &lt;code&gt;urllib&lt;/code&gt; library and a uuid generator. We will first locate all images with CSS selector &lt;code&gt;'img'&lt;/code&gt;, then access its &lt;code&gt;'src'&lt;/code&gt; attribute, and then creating a unique id for each image download the images with &lt;code&gt;urlretrieve('url', 'folder/name.jpg')&lt;/code&gt; method. This method takes 2 parameters: a URL of the image and a name we want to give it together with the folder we want to download to (if applicable).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from urllib.request import urlretrieve
from uuid import uuid4

# get the main page again
browser.get('https://en.wikipedia.org/wiki/Main_Page')

# locate image elements
images = browser.find_elements_by_css_selector('img')

# access src attribute of the images
src_list = [img.get_attribute('src') for img in images]


for src in src_list:
    # create a unique name for each image by using UUID generator
    uuid = uuid4()

    # retrieve umages using the URLs
    urlretrieve(src, f"wiki_images/{uuid}.jpg")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Adding Waiting Time Between Actions
&lt;/h3&gt;

&lt;p&gt;And lastly, sometimes it is necessary to introduce some waiting time between actions in the browser. For example, when loading a lot of pages one after another. It can be done with &lt;code&gt;time&lt;/code&gt; module.&lt;/p&gt;

&lt;p&gt;Let’s load 3 URLs from our &lt;code&gt;links&lt;/code&gt; list and make the browser wait for 3 seconds before loading each page using &lt;code&gt;time.sleep()&lt;/code&gt; method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import time

urls = links[0:3]

for url in urls:
    browser.get(url)
    # stop for 3 seconds before going for the next page
    time.sleep(3)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Closing the WebDriver
&lt;/h3&gt;

&lt;p&gt;And finally we can close our robot browser’s window with&lt;/p&gt;

&lt;p&gt;&lt;code&gt;browser.close()&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Don’t forget that &lt;code&gt;browser&lt;/code&gt; is a variable that contains an instance of &lt;code&gt;Firefox()&lt;/code&gt; method (see the beginning of the tutorial).&lt;/p&gt;

&lt;h3&gt;
  
  
  Code in GitHub
&lt;/h3&gt;

&lt;p&gt;The code from this article is available in GitHub:&lt;br&gt;
&lt;a href="https://github.com/AnnaLara/scraping_with_selenium_basics" rel="noopener noreferrer"&gt;https://github.com/AnnaLara/scraping_with_selenium_basics&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webscraping</category>
      <category>python</category>
      <category>selenium</category>
      <category>datascience</category>
    </item>
    <item>
      <title>Dockerize It!</title>
      <dc:creator>Anna Zubova</dc:creator>
      <pubDate>Wed, 15 May 2019 04:40:11 +0000</pubDate>
      <link>https://dev.to/annazubova/dockerize-it-4pne</link>
      <guid>https://dev.to/annazubova/dockerize-it-4pne</guid>
      <description>&lt;p&gt;Solving problems with code is a lot of fun. But when your creative process gets interrupted by a dependency issue where you have to dig into the terminal and check versions fearing that one wrong move can break what you have been building for weeks, it is definitely a frustrating setback. &lt;/p&gt;

&lt;p&gt;On my path to learn Data Science, I have struggled a lot with creating the right environment for my project and making sure that all my packages are installed and are not creating any issues. But what happens when I need to run my application on a server where I don’t have my hand-crafted development environment? Luckily, Docker saves the day.&lt;/p&gt;

&lt;p&gt;Docker is an open source &lt;strong&gt;platform for developers and sysadmins to develop, deploy, and run applications with containers&lt;/strong&gt; (from &lt;a href="https://docs.docker.com/" rel="noopener noreferrer"&gt;Docker documentation&lt;/a&gt;). Here we are talking about linux containers, or in other words, applications that let developers wrap a project into one package that contains all the libraries and dependencies along with the project code itself. A container can be compared with a virtual machine, but it is much more lightweight since it uses only the right amount of resources from the host machine, rather than creating a full operating system inside the host machine. &lt;/p&gt;

&lt;p&gt;In this tutorial I will introduce you to some key Docker concepts and components to be able to start using them in your development process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Download Docker: &lt;a href="https://docs.docker.com/docker-for-mac/install/" rel="noopener noreferrer"&gt;https://docs.docker.com/docker-for-mac/install/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are 2 Docker editions available: Docker CE (Community Edition) and EE (Enterprise Edition). The documentation recommends CE for learning purposes and small team projects. Docker can be run on AWS or downloaded to run on your local machine. In this tutorial I am going to download Docker for MacOS. If you don’t have a Docker account, you will need to create one to be able to download the installation file.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F75rjgiuqfhu1jnwe4jpr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F75rjgiuqfhu1jnwe4jpr.png" alt="download Docker"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Run Docker.dmg installation file and move the application to your Applications folder&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Open Docker from your Applications folder. You will see an icon appearing in the upper right corner of your screen.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Sign in with your Docker ID&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frdw7za8zc3bd2laq5j0q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frdw7za8zc3bd2laq5j0q.png" alt="sign in to Docker"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In Terminal type the following to see if it is working correctly:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;docker run hello-world&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The output should look like thi:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

latest: Pulling from library/hello-world
1b930d010525: Pull complete 
Digest: sha256:5f179596a7335398b805f036f7e8561b6f0e32cd30a32f5e19d17a3cda6cc33d
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Docker Images and Dockerfiles
&lt;/h2&gt;

&lt;p&gt;There are 2 key components of Dockerizing your project: Docker images and Dockerfiles.&lt;/p&gt;

&lt;p&gt;An image can be described as a set of tools and instructions that we need to execute the project's code: system tools, libraries, dependencies, etc. Conveniently, this set of tools can be reused in a very easy way, so you would not need to define a new project environment, but can rather reuse an existing one.&lt;/p&gt;

&lt;p&gt;A Dockerfile is a text file with a set of instructions to assemble an image. Each line of the Dockerfile is considered a layer which can be later reused.&lt;/p&gt;

&lt;p&gt;There is also a cloud service called &lt;a href="https://hub.docker.com/" rel="noopener noreferrer"&gt;Docker Hub&lt;/a&gt; where Docker users can share Docker images. This service is similar to what GitHub does for git.&lt;/p&gt;
&lt;h2&gt;
  
  
  Running an existing image
&lt;/h2&gt;

&lt;p&gt;To test how Docker can run a Jupyter server, I followed this &lt;a href="https://www.dataquest.io/blog/docker-data-science/" rel="noopener noreferrer"&gt;tutorial&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I started with running this command in my terminal:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;docker run ubuntu:16.04&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This command will run an image called [ubuntu] with image version [16.04]. If Docker doesn’t find the image on a local machine, it will then look in the Docker Hub to download the image.&lt;/p&gt;

&lt;p&gt;There are some extra options for the &lt;code&gt;run&lt;/code&gt; command that can be found in the &lt;a href="https://docs.docker.com/engine/reference/run/" rel="noopener noreferrer"&gt;Docker Official Documentation&lt;/a&gt;.  &lt;/p&gt;

&lt;p&gt;As I mentioned before, it is very convenient to use existing images. Let’s run an image already created by Jupyter development community that has just Python and Jupyter installed: &lt;a href="https://hub.docker.com/r/jupyter/minimal-notebook" rel="noopener noreferrer"&gt;https://hub.docker.com/r/jupyter/minimal-notebook&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;docker run -p 8880:8888 jupyter/minimal-notebook&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In the above line, &lt;code&gt;-p &amp;lt;host_port&amp;gt;:&amp;lt;container_port&amp;gt;&lt;/code&gt; is the part that tells Docker to open connection between the Docker container and host machine, so interaction with the running container is possible.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;jupyter/minimal-notebook&lt;/code&gt;is the image that we want to run.&lt;/p&gt;

&lt;p&gt;After running this command, you will see this type of output in your terminal:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

To access the notebook, open this file in a browser:
        file:///home/jovyan/.local/share/jupyter/runtime/nbserver-6-open.html
    Or copy and paste one of these URLs:
        http://(2f0da4326d97 or [my IP address]):8888/?token=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;From the last URL we have to take the token number, which I represented with 'x' since it is a secret key. With the port number 8880 that I used to run the image, I was able to access the notebook:&lt;br&gt;
&lt;code&gt;http://localhost:8880/?token=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Next step would be to allow to create and make changes to a Jupyter notebook with a container running. There is a special option in &lt;code&gt;run&lt;/code&gt; command: &lt;/p&gt;

&lt;p&gt;&lt;code&gt;-v &amp;lt;host_directory&amp;gt;:&amp;lt;container_directory&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Host directory specifies where to store the notebook we are going to create, and container directory should be specified in the container documentation (if using Docker Hub container). In our case the container directory from the documentation was &lt;code&gt;/home/jovyan&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;So the final code to run an image with the option to access it and create notebook is:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;docker run -p 8880:8888 -v ~/docker_tests:/home/jovyan jupyter/minimal-notebook&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Going to &lt;code&gt;http://localhost:8880/?token=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&lt;/code&gt; in your browser will allow you access your Jupyter server and create notebooks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dockerizing your Python project
&lt;/h2&gt;

&lt;p&gt;To Dockerize your project, you will first need to create a Dockerfile containing instructions on what image you are going to be using, what packages you need to install, and what your project’s directory is. &lt;/p&gt;

&lt;p&gt;Imagine that you need to Dockerize your python script called &lt;code&gt;add_numbers.py&lt;/code&gt; that would require installation of the &lt;code&gt;scikit-learn&lt;/code&gt; library. &lt;/p&gt;

&lt;p&gt;First, create a file called Dockerfile (don't add extension to it!). Add these lines to the file in any text editor:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

FROM python:3

ADD add_numbers.py /

RUN pip install -U scikit-learn

CMD [ "python", "add_numbers.py" ]


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;FROM&lt;/code&gt; command says what image you are using as a template. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;ADD&lt;/code&gt; tells Docker to add certain script to the Dockerfile. This command takes 2 parameters: source and destination&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ADD &amp;lt;source&amp;gt; &amp;lt;destination&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;RUN&lt;/code&gt; says that before executing the script, installation of &lt;code&gt;scikit-learn&lt;/code&gt; should be done. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;CMD&lt;/code&gt; provides the default command that will be executed after the image has loaded unless overwritten by other command.&lt;/p&gt;

&lt;p&gt;My python file &lt;code&gt;add_numbers.py&lt;/code&gt; has just the following code:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add_numbers&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;

&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;add_numbers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;After creating my script and my Dockerfile that has the instructions on how to create an image, I can run this command to build a new image based on newly created Dockerfile: &lt;/p&gt;

&lt;p&gt;&lt;code&gt;docker build -t add_numbers .&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This commands creates an image called ‘add_numbers’ based on a Dockerfile from the same directory we are running the command from.&lt;/p&gt;

&lt;p&gt;Finally, we can run the image with this command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;docker run add_numbers&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;As my python script contained a function that would add two numbers and print out the result, and also had one function call to add 3 + 4, I got 7 as an output in my terminal.&lt;/p&gt;

&lt;p&gt;To learn more, please refer to the official Docker documentation:&lt;br&gt;
&lt;a href="https://docs.docker.com/" rel="noopener noreferrer"&gt;https://docs.docker.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Useful tutorials on starting working with Docker:&lt;br&gt;
&lt;a href="https://runnable.com/docker/python/dockerize-your-python-application" rel="noopener noreferrer"&gt;https://runnable.com/docker/python/dockerize-your-python-application&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.dataquest.io/blog/docker-data-science/" rel="noopener noreferrer"&gt;https://www.dataquest.io/blog/docker-data-science/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>python</category>
      <category>datascience</category>
    </item>
    <item>
      <title>Deconstructing the Box and Whisker Plot</title>
      <dc:creator>Anna Zubova</dc:creator>
      <pubDate>Tue, 30 Apr 2019 03:57:37 +0000</pubDate>
      <link>https://dev.to/annazubova/deconstructing-the-box-and-whisker-plot-11f3</link>
      <guid>https://dev.to/annazubova/deconstructing-the-box-and-whisker-plot-11f3</guid>
      <description>&lt;p&gt;When trying to understand what a set of data looks like, there are plenty of options as to how to visualize it. It is important to pick the ones that serve the specific question we want to ask.&lt;/p&gt;

&lt;p&gt;A histogram is usually the first choice when visualizing data and making a preliminary analysis of a distribution. A box and whisker plot (often referred to as box plot), however, can be used on its own or as an additional tool in data analysis.&lt;/p&gt;

&lt;p&gt;A box plot uses 5 important descriptive statistics of a distribution: &lt;strong&gt;median value&lt;/strong&gt;, &lt;strong&gt;lower quartile&lt;/strong&gt;, &lt;strong&gt;upper quartile&lt;/strong&gt;, and &lt;strong&gt;maximum and minimum values&lt;/strong&gt;. It quickly gives us a sense of what data looks like and allows to compare different groups of data in one simple plot.&lt;/p&gt;

&lt;p&gt;Here is an example of a basic box plot:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FAnnaLara%2Fvisualizations_with_boxplot_blogpost%2Fraw%2Fmaster%2Fbasic_boxplot.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FAnnaLara%2Fvisualizations_with_boxplot_blogpost%2Fraw%2Fmaster%2Fbasic_boxplot.png" alt="Basic box plot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Limitations
&lt;/h2&gt;

&lt;p&gt;It is important to understand that these 5 statistics cannot be the only measure of spread used to describe a distribution, being inferior to metrics like mean and standard deviation. However, in case the distribution is highly skewed or if there are outliers, it can be a very useful tool to check shape, spread and variability of data.&lt;/p&gt;

&lt;p&gt;Box plots are great in showing whether the data is symmetric, but they will not show the type of symmetry. For example, two sets of data can look exactly the same as box plots, but one can have a significant variability of frequencies and another is uniformly distributed. A box plot wouldn’t be the right tool to check for those features. For that reason, box plots are better to be used in combination with other visualization methods like, for example, a histogram.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FAnnaLara%2Fvisualizations_with_boxplot_blogpost%2Fraw%2Fmaster%2Fhist_vs_box_1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FAnnaLara%2Fvisualizations_with_boxplot_blogpost%2Fraw%2Fmaster%2Fhist_vs_box_1.png" alt="Histogram vs box plot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Visualizing outliers with box plots
&lt;/h2&gt;

&lt;p&gt;One of the main purposes of the box plot is to quickly visualize outliers to see if it is necessary to remove them for further analysis. But to actually understand what is considered an outlier, let’s look at the following representation of the box plot and PDF of a normal distribution.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FAnnaLara%2Fvisualizations_with_boxplot_blogpost%2Fraw%2Fmaster%2F512px-Boxplot_vs_PDF.svg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FAnnaLara%2Fvisualizations_with_boxplot_blogpost%2Fraw%2Fmaster%2F512px-Boxplot_vs_PDF.svg.png" alt="Source: https://commons.wikimedia.org/wiki/File:Boxplot_vs_PDF.svg"&gt;&lt;/a&gt;&lt;/p&gt;
Source: https://commons.wikimedia.org/wiki/File:Boxplot_vs_PDF.svg



&lt;p&gt;The whiskers actually represent values beyond which the data will be considered outliers. To determine the lower limit, interquartile range times 1.5 is subtracted from the 1st quartile value. To determine the upper limit, we should add 1.5 times the interquartile range to the 3rd quartile value.&lt;/p&gt;

&lt;p&gt;In a normal distribution the box plot with whiskers represents 99.3% of all the data; that is, the outliers are only 0.7% of data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparing data
&lt;/h2&gt;

&lt;p&gt;Another very important utility of box plots is to compare data from different groups. Plotting several box plots next to each other gives us a perfect sense of whether the groups are similar.&lt;/p&gt;

&lt;p&gt;The things we have to look for are: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If boxes overlap.&lt;br&gt;
If there is no overlapping, it is quite clear that the groups are different.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the medians are in visual range of the box compared with. If not, it is likely that the groups are different.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ranges of the boxes.&lt;br&gt;
It is helpful to evaluate the comparative range of the boxes to see how much difference there is in the spread of the data.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Skewness.&lt;br&gt;
As skewness is easily observed from the box plots, it can be useful to compare this parameter between two plots.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This preliminary visual analysis can help understand if two groups we are looking at are similar and if we need to apply some other techniques to further measure how different they are. &lt;/p&gt;

&lt;p&gt;Let’s look at the data from the World Happiness Report from &lt;a href="https://www.kaggle.com/unsdsn/world-happiness" rel="noopener noreferrer"&gt;Kaggle&lt;/a&gt;. First, let’s look at the happiness scores from 2017 and 2016.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FAnnaLara%2Fvisualizations_with_boxplot_blogpost%2Fraw%2Fmaster%2Fhappiness_2017_2016.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FAnnaLara%2Fvisualizations_with_boxplot_blogpost%2Fraw%2Fmaster%2Fhappiness_2017_2016.png" alt="Happiness scores"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The groups are clearly very similar since the medians are located at the same level. The spread of the second plot is slightly wider that the first one.&lt;/p&gt;

&lt;p&gt;However, if we compare health and freedom scores, the box plots will show more differences. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FAnnaLara%2Fvisualizations_with_boxplot_blogpost%2Fraw%2Fmaster%2Fhealth_freedom_2017.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FAnnaLara%2Fvisualizations_with_boxplot_blogpost%2Fraw%2Fmaster%2Fhealth_freedom_2017.png" alt="Health and freedom scores, 2017"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can actually extract the values of the statistics calculated by the box plot. The object that is returned after creating a plot has all the values stored in it. To see what keys it has, we can run &lt;code&gt;bp.keys()&lt;/code&gt;. For example, to extract the median, we can use the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#get values for the medians
#bp is a box plot object
&lt;/span&gt;
&lt;span class="n"&gt;medians&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;bp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;medians&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="n"&gt;medians&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_data&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;medians&lt;/code&gt; now is equal to &lt;code&gt;[0.6060415506362921, 0.43745428323745705]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;To get the upper and lower levels of the boxes, we can implement this code, where we will access the second element from the &lt;code&gt;bp['boxes']&lt;/code&gt; object that represents y-axis values for the lines. After that we will select first and third element that are lower and upper y-axis value of the box:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#get values for boxes' lower and upper values
&lt;/span&gt;&lt;span class="n"&gt;boxes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;bp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;boxes&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="n"&gt;boxes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_data&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;boxes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_data&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;boxes&lt;/code&gt; now contains the list &lt;code&gt;[0.36986629664897896, 0.723007529973984, 0.3036771714687345, 0.5165613889694209]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;So, the range of the first box (where 50% of the data is located) lies between 0.37 and approximately 0.72, with 0.61 as median value. The second box plot has a range of 0.30 to 0.52 with median value at 0.44.&lt;/p&gt;

&lt;h2&gt;
  
  
  Notched box plot
&lt;/h2&gt;

&lt;p&gt;One interesting feature of the box plots that is often overlooked is the &lt;em&gt;notched&lt;/em&gt; parameter, which allows to compare confidence intervals for the median value. By default, the confidence level is 95%. This option is especially useful to compare groups of the same values, and we would look for visual overlapping of the notches that would indicate similarities/differences in median values.&lt;/p&gt;

&lt;p&gt;Notched box plots can be used together with another parameter in Matplotlib’s box plot, &lt;em&gt;bootstrap&lt;/em&gt;. By default it is set equal to None. If set to an integer, that would indicate how many times bootstrapping should be performed in order to determine confidence intervals.&lt;/p&gt;

&lt;h2&gt;
  
  
  Other useful options
&lt;/h2&gt;

&lt;p&gt;There are some other parameters that can be useful when creating a box plot with Matplotlib library.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;sym&lt;/em&gt;: determines the look of flier points. Setting it equal to empty string will tell Matplotlib that we don’t want to show outliers.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;whis&lt;/em&gt;:  parameter allows to change the reach of whiskers. By default this parameter is equal to 1.5. Lower and upper range of whiskers is determined by Q1 - 1.5*IQR and Q3 + 1.5*IQR accordingly. If &lt;em&gt;whis&lt;/em&gt; is set to 'range' string, the whiskers reach to minimum and maximum values.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;vert&lt;/em&gt;:  accepts a boolean value. By default it is set to True, but if set to False, the box plot will appear horizontally.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;positions&lt;/em&gt;: accepts an array-like parameter. By default it is (1, N+1) where N is the number of box plots. If set to (1,1), 2 box plots will overlap.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;widths&lt;/em&gt; : sets the width of each box. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;labels&lt;/em&gt; : sets labels for each box plot.&lt;/p&gt;

&lt;h3&gt;
  
  
  References and further reading
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://matplotlib.org/api/_as_gen/matplotlib.pyplot.boxplot.html?highlight=boxplot#matplotlib.pyplot.boxplot" rel="noopener noreferrer"&gt;Matplotlib documentation on box plots&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www150.statcan.gc.ca/n1/edu/power-pouvoir/ch12/5214889-eng.html" rel="noopener noreferrer"&gt;Constructing box and whisker plots&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.brighthubpm.com/six-sigma/58254-box-plots-vs-histograms-in-project-management/" rel="noopener noreferrer"&gt;Comparing Box Plots and Histograms – Which Is the Better Tool?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://towardsdatascience.com/understanding-boxplots-5e2df7bcbd51" rel="noopener noreferrer"&gt;Understanding Boxplots&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.bioturing.com/2018/05/22/how-to-compare-box-plots/" rel="noopener noreferrer"&gt;How to compare box plots&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.bioturing.com/2018/05/22/more-on-how-to-compare-box-plots/" rel="noopener noreferrer"&gt;More on how to compare box plots&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Visualizations from this blogpost can be found in my &lt;a href="https://github.com/AnnaLara/visualizations_with_boxplot_blogpost" rel="noopener noreferrer"&gt;GitHib profile&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>datavisualizations</category>
      <category>datascience</category>
      <category>python</category>
    </item>
    <item>
      <title>Why I Decided to Become a Data Scientist</title>
      <dc:creator>Anna Zubova</dc:creator>
      <pubDate>Mon, 22 Apr 2019 15:20:37 +0000</pubDate>
      <link>https://dev.to/annazubova/why-i-decided-to-become-a-data-scientist-3ihb</link>
      <guid>https://dev.to/annazubova/why-i-decided-to-become-a-data-scientist-3ihb</guid>
      <description>&lt;p&gt;I did not always dream of becoming a data scientist. It was rather a thought-through decision that I made after trying different things, learning what I can be good at, and getting to know myself better.&lt;/p&gt;

&lt;p&gt;The first time I heard about Data Science was when I read a &lt;a href="https://www.forbes.com/sites/kashmirhill/2012/02/16/how-target-figured-out-a-teen-girl-was-pregnant-before-her-father-did/#d9190bf66686"&gt;story about how Target was able to figure out a girl was pregnant&lt;/a&gt; before her parents knew, using data they collected from their customers. That time I thought that those people had some kind of wicked superpowers. It wasn’t until I started to learn programming when I found out that there is this fascinating field called Data Science, which I have recently chosen as my new career trajectory. At the moment I am a Flatiron School student going through the Immersive Data Science Bootcamp. Here are the most important reasons why I am confident I have chosen the right path.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. I am curious to find hidden information insights
&lt;/h3&gt;

&lt;p&gt;The world has never been so confusing and is changing so rapidly. There is more information than people can possibly deal with, but with a lot of insights hidden in the data. I would love to be able to discover those insights and make use of a huge stream of information that is out there thanks to the new technologies. Besides, it makes me feel confident that I can find out the truth for myself instead of relying on other people telling me what is true and what is not. The skills I am learning help me make independent conclusions and decisions, so I feel empowered and incredibly optimistic about the future.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. I love coding
&lt;/h3&gt;

&lt;p&gt;It was a big surprise to me when I realized that I can code and that I actually love doing that. When I was growing up, everybody thought that programming was boring and one had to have a certain math-oriented and analytical personality profile to do that. But later I discovered that coding actually has a great deal of creativity in it. Creating a program can be compared to building a physical object like a house or a piece of furniture. You need to design it, think of what features it will have, and how it can be useful. This is my favorite part about coding: the tools it gives to create something incredibly useful out of just our imagination. In Data Science coding skills are essential to process data unbelievably fast, which lets you focus on the most interesting things like interpreting the results and drawing conclusions.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Data Science promotes social responsibility
&lt;/h3&gt;

&lt;p&gt;I have a special interest in Open Data and using Data Science for the benefit of my community. It seems that there is so much for people to gain from twisting the facts and manipulating public opinion, so I almost feel it is my responsibility as a data scientist to contribute to providing society with reliable analyses of information. &lt;/p&gt;

&lt;h3&gt;
  
  
  4. Data Science is the career of the future
&lt;/h3&gt;

&lt;p&gt;My choice of data science as my career path was also quite pragmatic. I feel that it will be one of the most useful skills that businesses will want to benefit from. Data is a very powerful asset for all kind of business processes: sales, marketing, operations, human resources, etc. It is relatively easy to collect a lot of information these days, but to be able to analyze it and use it to boost a company's growth is a relatively new idea that is going to spread very fast. The demand for these kinds of skills is growing, and I wanted to make sure I jump on this train too.&lt;/p&gt;

&lt;h3&gt;
  
  
  5.  I can make use of my background and experience
&lt;/h3&gt;

&lt;p&gt;To be a good data scientist, it is not enough to just know how to code and do statistics. One of the most important things is to be able to ask the right questions that you want to find answers to. So it is very helpful to have a broad understanding of different industries to be able to help different kinds of companies. I have a degree in Economics, Management, as well as work experience in Tourism and hopefully some life experience. I wanted all these skills to actually be useful for me. It all came together when I realized that in Data Science every experience counts, because I will need to make sense of the things that don’t seem to make sense, and for that every additional skill/experience is helpful.&lt;/p&gt;

&lt;h3&gt;
  
  
  BONUS:  Data Science is fun!
&lt;/h3&gt;

&lt;p&gt;Maybe it is not the most obvious reason one can think of, but the further I am into the Data Science Bootcamp, the more I realize this. There is always a way to creatively approach the problem, turn it around and come up with a completely new insight!&lt;/p&gt;

</description>
      <category>datascience</category>
    </item>
    <item>
      <title>King County House Sales dataset: log-transformations and interpreting results</title>
      <dc:creator>Anna Zubova</dc:creator>
      <pubDate>Fri, 19 Apr 2019 16:03:43 +0000</pubDate>
      <link>https://dev.to/annazubova/king-county-house-sales-dataset-log-transformations-and-interpreting-results-19b2</link>
      <guid>https://dev.to/annazubova/king-county-house-sales-dataset-log-transformations-and-interpreting-results-19b2</guid>
      <description>&lt;p&gt;Log transformations turn out to be very useful when working with linear regression models. They are very helpful in correcting skewness in the data, and allow to make the distribution more normal.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/ZMBailey" rel="noopener noreferrer"&gt;Alexander Bailey&lt;/a&gt; and I worked on a dataset of housing prices in King County in order to develop a linear regression model that explains price variations.&lt;/p&gt;

&lt;p&gt;We tried log transformation on several continuous variables but we had best results applying log transformation to the set of distance from major central locations: downtown Seattle, downtown Bellevue, and South Lake Union. The distance to each of these locations was expressed in miles.&lt;/p&gt;

&lt;p&gt;Let’s look at one of the variables: distance in miles from downtown Seattle. This is how the distribution looked before and after the log transformation:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FAnnaLara%2Fdsc-1-final-project%2Fraw%2Fmaster%2Fdis_downtown_distr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FAnnaLara%2Fdsc-1-final-project%2Fraw%2Fmaster%2Fdis_downtown_distr.png" alt="Distance from Seattle downtown distribution"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can see that the log transformation corrected the skewness and made the distribution more normal, which was beneficial for linear regression model performance. By taking the natural logarithm of parameter values, we were able to improve our model’s metrics: R squared from 0.627 to 0.686 and MAE from 134016.02 to 131342.48 in one of model fitting iterations.&lt;/p&gt;

&lt;p&gt;In case of the distance from downtown Bellevue, the distribution was also significantly improved by taking the natural logarithm of the variable values:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FAnnaLara%2Fdsc-1-final-project%2Fraw%2Fmaster%2Fdis_bellvue_distr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FAnnaLara%2Fdsc-1-final-project%2Fraw%2Fmaster%2Fdis_bellvue_distr.png" alt="Distance from Bellevue downtown distribution"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Change in distribution after log-transformation of the distance from South Lake Union parameter:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FAnnaLara%2Fdsc-1-final-project%2Fraw%2Fmaster%2Fdis_s_lake_union_distr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FAnnaLara%2Fdsc-1-final-project%2Fraw%2Fmaster%2Fdis_s_lake_union_distr.png" alt="Distance from South Lake Union distribution"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Log-transformed distance parameters in the linear regression model
&lt;/h3&gt;

&lt;p&gt;Our final model for the housing prices focuses on making predictions for the prices up to approximately $1.1 million. Distance from downtown Seattle, downtown Bellevue, and South Lake Union are among the strongest predictors of the price.&lt;/p&gt;

&lt;p&gt;Here are the coefficients for the distance values in our model:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Coefficient name&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;'mi_from_downtown_log'&lt;/td&gt;
&lt;td&gt;210431.83668516215&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;'mi_from_bellevue_log'&lt;/td&gt;
&lt;td&gt;-109855.7636174455&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;'mi_from_south_lake_log'&lt;/td&gt;
&lt;td&gt;-294919.7693134867&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The general explanation of the coefficient values is that, an increase in one unit of the 'mi_from_downtown_log' variable, assuming other variables in the model remain constants, would result in an increase on the housing price by $210,431.84 on average. However, the difficulty is that the explaining variable was log-transformed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Distance from downtown parameter
&lt;/h3&gt;

&lt;p&gt;Let’s simulate how the increase of the distance in miles from downtown Seattle would affect housing prices, assuming that other variables are constant. &lt;/p&gt;

&lt;p&gt;First, let’s generate an array of numbers from 1 to 100, representing an increase of distance from downtown Seattle. Next step is to take the log value of these numbers that resulted in an array in range from 0 to 1.6. We then calculate y values (that is, our predicted price) for each of the values of log(x) using the coefficient of 210,431.84 from our linear regression model.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;miles_range = np.arange(1, 101)&lt;/code&gt;&lt;br&gt;
&lt;code&gt;miles_range_log = np.log(miles_range)&lt;/code&gt;&lt;br&gt;
&lt;code&gt;y = 210431.83668516215 * miles_range_log&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Here is the plot representing the relationship between y and log(x) compared to relationship between y and x:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;fig, axs = plt.subplots(2, 1, constrained_layout=True)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;axs[0].plot(miles_range_log, y)&lt;br&gt;
axs[0].set_title('Log transformed variable')&lt;br&gt;
axs[0].set_xlabel('log(mi_from_downtown)')&lt;br&gt;
axs[0].set_ylabel('price')&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;axs[1].plot(miles_range, y)&lt;br&gt;
axs[1].set_title('Raw data')&lt;br&gt;
axs[1].set_xlabel('mi_from_downtown')&lt;br&gt;
axs[1].set_ylabel('price');&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FAnnaLara%2Fdsc-1-final-project%2Fraw%2Fmaster%2Fdis_downtown_raw_vs_log.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FAnnaLara%2Fdsc-1-final-project%2Fraw%2Fmaster%2Fdis_downtown_raw_vs_log.png" alt="raw vs log-transformed data"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can see that log-transforming this variable converted the relationship from exponential to linear, which serves the purpose of improving metrics of the linear regression.&lt;/p&gt;

&lt;p&gt;Interestingly, in the case of the distance from downtown Seattle, the correlation is positive, which is the opposite to what we had expected. However, there is a negative correlation of housing prices with distance from downtown Bellevue and South Lake Union. The explanation might be that people would prefer to be further away from downtown Seattle in favor of proximity to other points.&lt;/p&gt;

&lt;h3&gt;
  
  
  Distance from downtown Bellevue parameter
&lt;/h3&gt;

&lt;p&gt;According to our model the coefficient is -109855.76.&lt;/p&gt;

&lt;p&gt;Let’s build an array of y values:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;y_bellevue = -109855.76 * miles_range_log&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Plotting the log(x) and x vs y:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;fig, axs = plt.subplots(2, 1, constrained_layout=True)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;axs[0].plot(miles_range_log, y_bellevue)&lt;br&gt;
axs[0].set_title('Log transformed variable')&lt;br&gt;
axs[0].set_xlabel('log(mi_from_bellevue)')&lt;br&gt;
axs[0].set_ylabel('price')&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;axs[1].plot(miles_range, y_bellevue)&lt;br&gt;
axs[1].set_title('Raw data')&lt;br&gt;
axs[1].set_xlabel('mi_from_bellevue')&lt;br&gt;
axs[1].set_ylabel('price');&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FAnnaLara%2Fdsc-1-final-project%2Fraw%2Fmaster%2Fdis_bellvue_raw_vs_log.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FAnnaLara%2Fdsc-1-final-project%2Fraw%2Fmaster%2Fdis_bellvue_raw_vs_log.png" alt="raw vs log-transformed data"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here the relationship is more logical: the further away a house is from Bellevue, the lower will be its price.&lt;/p&gt;

&lt;h3&gt;
  
  
  Distance from South Lake Union parameter
&lt;/h3&gt;

&lt;p&gt;The coefficient for this parameter is -294919.77, which is the most significant between all three distance parameters. &lt;/p&gt;

&lt;p&gt;Calculating an array with y values:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;y_s_lake_union = -294919.7693134867 * miles_range_log&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Visualization of the x and log(x) vs y:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FAnnaLara%2Fdsc-1-final-project%2Fraw%2Fmaster%2Fdis_south_late_union_raw_vs_log.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FAnnaLara%2Fdsc-1-final-project%2Fraw%2Fmaster%2Fdis_south_late_union_raw_vs_log.png" alt="raw vs log-transformed data"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Interpreting the results
&lt;/h3&gt;

&lt;p&gt;When log transformations are done on a dataset, it can be difficult to explain to the non-technical audience how the model works. Here is how it can be done using our model example.&lt;/p&gt;

&lt;p&gt;Let’s look at the distance from South Lake Union as it is the most significant variable out of three distance parameters. The coefficient for this value is -294919.76, which in case of non-log-transformed variable would mean that an increase in distance from South Lake Union by 1 mile would be associated with a $294,919.76 decrease of price on average. &lt;/p&gt;

&lt;p&gt;However, the values of the price are log-transformed, so we can’t use this 1-unit-increase technique. In the case of logarithmic data transformations, we can talk about percentage changes. &lt;/p&gt;

&lt;p&gt;To find out what the increase in target price would be, let’s look at the equation:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;price(x1) - price(x0) = coef * log(x1) - coef*log(x0) = coef * (log(x1) - log(x0)) = coef * log(x1/x0)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So in our case to find out what would be the change of price resulting from an increase of the distance by 10%, we will have to calculate the following:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;change_in_price = -294,919.76 * log(1.1)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;change_in_price = -294,919.76 * 0.95&lt;/code&gt;   = -28,108.85&lt;/p&gt;

&lt;p&gt;Based on the above calculation, &lt;strong&gt;with an approximately every 530 ft (10% of a mile) increase in distance from South Lake Union, the price will decrease by $28,108.85&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If we want to know the effect of increasing the distance by 1 mile, we would need to do the following calculation:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;change_in_price = -294,919.76 * log(2)&lt;/code&gt;  = -204422.8&lt;/p&gt;

&lt;p&gt;As a side note, it is helpful to know that if we are talking about small percentage of changes in x value (up to 5%), the increase of x by 5%, for example, is almost equivalent to adding 0.05 to the log(x). Similarly, the increase of x by 2%, would be almost equivalent to adding 0.02 to the log(x).&lt;/p&gt;

</description>
      <category>datascience</category>
      <category>python</category>
      <category>seattle</category>
      <category>dataanalysis</category>
    </item>
  </channel>
</rss>
