<?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 Kerry Parker on Medium]]></title>
        <description><![CDATA[Stories by Kerry Parker on Medium]]></description>
        <link>https://medium.com/@_kaparker?source=rss-219e4d5d0c99------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/0*ktOndupM0LeJ41w9.jpg</url>
            <title>Stories by Kerry Parker on Medium</title>
            <link>https://medium.com/@_kaparker?source=rss-219e4d5d0c99------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 15 Nov 2026 09:17:09 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@_kaparker/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[Your Year, Your Way — The Ultimate Notion Planning Template]]></title>
            <description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://medium.com/@_kaparker/your-year-your-way-the-ultimate-notion-planning-template-498a71e00197?source=rss-219e4d5d0c99------2"><img src="https://cdn-images-1.medium.com/max/2600/1*ibRc_TBgh6EGi350KRBZgA.png" width="2874"></a></p><p class="medium-feed-snippet">Take control of your year with Planner v2.0</p><p class="medium-feed-link"><a href="https://medium.com/@_kaparker/your-year-your-way-the-ultimate-notion-planning-template-498a71e00197?source=rss-219e4d5d0c99------2">Continue reading on Medium »</a></p></div>]]></description>
            <link>https://medium.com/@_kaparker/your-year-your-way-the-ultimate-notion-planning-template-498a71e00197?source=rss-219e4d5d0c99------2</link>
            <guid isPermaLink="false">https://medium.com/p/498a71e00197</guid>
            <category><![CDATA[productivity]]></category>
            <category><![CDATA[self-improvement]]></category>
            <category><![CDATA[notion]]></category>
            <category><![CDATA[life]]></category>
            <category><![CDATA[personal-development]]></category>
            <dc:creator><![CDATA[Kerry Parker]]></dc:creator>
            <pubDate>Sun, 02 Feb 2025 19:05:55 GMT</pubDate>
            <atom:updated>2025-02-02T19:05:55.761Z</atom:updated>
        </item>
        <item>
            <title><![CDATA[Joining data in pandas: merge vs. join]]></title>
            <link>https://blog.dataengineerthings.org/joining-data-in-pandas-merge-vs-join-436757cdd81e?source=rss-219e4d5d0c99------2</link>
            <guid isPermaLink="false">https://medium.com/p/436757cdd81e</guid>
            <category><![CDATA[pandas]]></category>
            <category><![CDATA[data-engineering]]></category>
            <category><![CDATA[data-science]]></category>
            <category><![CDATA[python]]></category>
            <category><![CDATA[editors-pick]]></category>
            <dc:creator><![CDATA[Kerry Parker]]></dc:creator>
            <pubDate>Fri, 20 Dec 2024 16:40:04 GMT</pubDate>
            <atom:updated>2024-12-28T17:43:52.153Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="Joining data in pandas: merge vs. join" src="https://cdn-images-1.medium.com/max/1024/1*ZdycDjXNE6JRR48nmrsQlA.png" /><figcaption>Image by author.</figcaption></figure><h3>Introduction</h3><p>In an interview, I was once asked “What is the difference between using join and merge in pandas?” and honestly, I was a bit stumped.</p><p>Typically when combining dataframes in pandas, I would have a quick google and head to the documentation to check the syntax — I always got mixed up which to use and whether the function is applied to the left dataframe or if the left dataframe is the first parameter.</p><p>These days, merge is my go-to over join and in this article I will explain to you why.</p><h3>Pandas merge vs join</h3><p>In pandas, both merge and join are used to combine objects. The main difference between them is that a merge offers more flexibility where you can use column(s) or index(es) to perform a join, whilst join is limited to using index(es) in at least one of the objects.</p><p>Let’s explore each in more detail.</p><h3>Pandas merge</h3><p>Of the two, merge is the most similar to a <a href="https://www.w3schools.com/sql/sql_join.asp">SQL </a><a href="https://www.w3schools.com/sql/sql_join.asp">JOIN</a>, however it <em>does</em> come with some differences.</p><h4>When to use merge</h4><ul><li>You are joining two dataframes or series objects</li><li>The join is based on column(s) or index(es)</li><li>The columns or indexes can have the same, or different names in the two objects</li></ul><h4>When not to use merge*</h4><ul><li>Unlike in SQL, if you have null values in your join columns, these are matched during the merge which could results in some strange output in your data</li></ul><p><strong>Example: left join two dataframes<br></strong>As an example, you have two dataframes, customers and orders:</p><pre>customers = pd.DataFrame(<br>    {<br>        &quot;id&quot;: [1, 2, 3, 4, 5],<br>        &quot;location&quot;: [&quot;London&quot;, &quot;New York&quot;, &quot;Paris&quot;, &quot;London&quot;, &quot;Madrid&quot;],<br>    }<br>)<br>orders = pd.DataFrame(<br>    {<br>        &quot;id&quot;: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],<br>        &quot;customer_id&quot;: [1, 2, 3, 4, 1, 1, 2, 3, 3, 3, 1],<br>        &quot;amount&quot;: [100, 150, 100, 200, 150, 300, 600, 250, 250, 400, 500],<br>        &quot;date&quot;: [<br>            &quot;2024-01-01&quot;,<br>            &quot;2024-01-10&quot;,<br>            &quot;2024-01-10&quot;,<br>            &quot;2024-01-11&quot;,<br>            &quot;2024-01-12&quot;,<br>            &quot;2024-01-12&quot;,<br>            &quot;2024-01-15&quot;,<br>            &quot;2024-01-16&quot;,<br>            &quot;2024-01-16&quot;,<br>            &quot;2024-01-17&quot;,<br>            &quot;2024-01-18&quot;,<br>        ],<br>    }<br>)</pre><p>Let’s say you want to join the two to find the location that has the most orders. Both dataframes have reference to customer ids — this is the column to join on.</p><p>If you are interested in all customer locations, even if they have 0 orders, you can use a left join. If you only want the locations with orders then use an inner join. Let’s go for a left join here.</p><p>Since the columns have different names in each dataframe, we need to use left_on and right_on. If they were both named customer_id, we could use on with the shared column name specified.</p><pre>pd.merge(customers, orders, how=&quot;left&quot;, left_on=&quot;id&quot;, right_on=&quot;customer_id&quot;)</pre><figure><img alt="Output of merge between customers and orders data using customer id as a join column" src="https://cdn-images-1.medium.com/max/1012/1*HrrodKTa0mITtrCFwK6J0Q.png" /></figure><p>The output of this merge is a dataframe with each row containing the customer data and an order from that customer. This is then ready for any aggregation. Since the join columns are named differently, both are retained in the output dataframe.</p><p>You might notice that there are also id columns in both dataframes and a suffix of x and y is added to each after the merge. The suffix is (&#39;_x&#39;, &#39;_y&#39;)by default and this can be changed by specifying your preferred suffix as a parameter.</p><blockquote><em>💡</em> I find for exploratory data analysis (EDA) work, the <em>indicator</em> flag comes in very handy! It creates a new column <em>_merge</em> to indicate whether the row is <em>left-only</em>, <em>right-only</em> or <em>both</em>. <em>indicator</em> is set to <em>False</em> by default so needs setting to <em>True</em> when calling <em>merge</em> if you want this extra detail in your joined object.</blockquote><p><strong>Example: join using columns with null values</strong></p><blockquote><em>✨</em> Want to wow your interviewers? This example covers the edge case of combining dataframes when null values exist in your join column.</blockquote><p>In this example you have two dataframes: users and activity. The user data contains user ids and their registration date, and the activity data includes the user id and number of posts. In both tables there are some cases where the user id has not been captured, resulting in null values.</p><pre>users = pd.DataFrame(<br>    {<br>        &quot;user_id&quot;: [np.nan, 1, 2, 3, 4, np.nan],<br>        &quot;registration_date&quot;: [<br>            &quot;2024-01-01&quot;,<br>            &quot;2024-01-01&quot;,<br>            &quot;2024-01-02&quot;,<br>            &quot;2024-01-02&quot;,<br>            np.nan,<br>            &quot;2024-01-03&quot;,<br>        ],<br>    }<br>)<br>activity = pd.DataFrame(<br>    {&quot;user_id&quot;: [1, np.nan, 2, 3, 4, np.nan], &quot;posts&quot;: [2, 3, 3, 5, 12, 7]}<br>)</pre><p>When joining these datasets using merge, both of the empty user ids from users get linked to both of the rows with empty user data in the activity.</p><pre>users.merge(activity, on=[&quot;user_id&quot;], how=&quot;left&quot;)</pre><figure><img alt="Output dataframe with null user_id from users linked to all empty user activity" src="https://cdn-images-1.medium.com/max/662/1*tdmpa72xMMxEbUiTJgbmHw.png" /></figure><blockquote><em>⚠️</em> *You <strong><em>can</em></strong> still use merge in these cases however do so with caution. You may want to filter out the null values or do some additional checks to avoid any unexpected results!</blockquote><p>One thing to note here, if you are joining two dataframes that have the same name for the join column, this column only appears once in the output. If there are any other columns with the same name that aren’t used in the join, then they will have a suffix appended.</p><h4>Advanced Usage</h4><p><strong>When to use </strong><strong>pandas.merge vs. </strong><strong>pandas.DataFrame.merge?<br></strong>Confusingly, both df1.merge(df2) and pd.merge(df1, df2) can be used to perform a merge — so which to use?</p><p>Well, this is a matter of preference. pandas.DataFrame.merge, is calling pandas.merge so there is no functional difference between them. <a href="https://github.com/pandas-dev/pandas/blob/v2.2.3/pandas/core/frame.py#L10813-L10846">Check out the source code</a> for details.</p><p>If you are performing multiple merges, then the <strong>chaining method</strong> df1.merge(df2).merge(df3) is a bit more readable than the <strong>wrapping style</strong> function pd.merge(pd.merge(df1, df2), df3) <a href="https://stackoverflow.com/questions/62143713/difference-between-pd-merge-and-dataframe-merge">as described on StackOverFlow</a>, but ultimately, they are doing the same thing.</p><h3>Pandas join</h3><p>Pandas join implements the <a href="https://www.geeksforgeeks.org/method-chaining-in-python/">chaining method</a> using df1.join(df2). Under the hood it actually calls merge (with some additional logic) if you <a href="https://github.com/pandas-dev/pandas/blob/v2.2.3/pandas/core/frame.py#L10580-L10811">take a look at the source code</a>.</p><h4>When to use join</h4><ul><li>Joining two dataframes based on index(es) or column(s) and index(es)</li></ul><h4>When not to use join</h4><ul><li>When joining to a series that does not have a name<br> — <em>this can be solved by naming your series object</em></li><li>When you want to join on columns, not indexes</li><li>When indexes or MultiIndex levels do not match up between dataframes</li><li>When using large dataframes, join can be less efficient than using merge</li></ul><p><strong>Example: join using an index and a column</strong></p><p>In this example we have two dataframes: user data and a lookup for location codes.</p><pre>users = pd.DataFrame(<br>    {<br>        &quot;user_id&quot;: [1, 2, 3, 4, 5, 6],<br>        &quot;user_name&quot;: [&quot;adder&quot;, &quot;cobra&quot;, &quot;viper&quot;, &quot;mamba&quot;, &quot;corn&quot;, &quot;grass&quot;],<br>        &quot;loc_code&quot;: [&quot;AU&quot;, &quot;GB&quot;, &quot;IN&quot;, &quot;US&quot;, &quot;IN&quot;, &quot;AU&quot;],<br>    }<br>)<br>location = pd.DataFrame(<br>    {<br>        &quot;code&quot;: [&quot;US&quot;, &quot;AU&quot;, &quot;GB&quot;, &quot;IN&quot;],<br>        &quot;location&quot;: [&quot;United States&quot;, &quot;Australia&quot;, &quot;Great Britain&quot;, &quot;India&quot;],<br>    }<br>) </pre><p>When creating a dataframe in this way, the index is a row label that is a sequence of integers starting at 0 for the first row. However, it can also be set as a column value.</p><p>If we are trying to get the location for each user based on the location code, this is the join key and we must set this to be the index for the second dataframe, in this case location. A requirement for using join is having the index of the second dataframe as a join key.</p><pre>location = location.set_index(&quot;code&quot;)</pre><p>We can then join the dataframes then using:</p><pre>users.join(location, on=&quot;loc_code&quot;)</pre><figure><img alt="Output of joining users to location when location code index is set" src="https://cdn-images-1.medium.com/max/806/1*ia8l4K56VE15bO7uQozf6g.png" /></figure><p>The column specified is the column name of the first dataframe and the join type is using the default which is a left join (note: this is different to merge where inner join is the default).</p><p><strong>Example: join using indexes</strong></p><p>Another way to do the same join is to also set the index of the first dataframe and repeat the join without specifying the join column:</p><pre>users = users.set_index(&quot;loc_code&quot;)<br>users.join(location)</pre><figure><img alt="Output of join when both users and location have index of location code" src="https://cdn-images-1.medium.com/max/748/1*USHcdmhsuJat2aHwWWRyog.png" /></figure><p>This will then use an index-on-index join if no column is specified. It carries over the index of the location code to the output dataframe, while when only the location dataframe index was set, the index of the user dataframe is used in the output.</p><p>It is also possible to join on multiple columns or indexes by using a MultiIndex. For example: df.set_index([&quot;col1&quot;, &quot;col2&quot;]).</p><h3>Summary</h3><p>Merge and join can be used in pandas to join two data objects. If you are joining based on the index(es), join is a great place to start. If you are joining based on columns, or dealing with large dataframes, merge is the more suitable and efficient option.</p><blockquote><em>💬</em> I typically perform column based joins, often with multiple columns and it’s rare that the names across dataframes align. This is why merge is my go-to.</blockquote><blockquote>If I <strong><em>were</em></strong> to do more index based joins, merge <em>does</em> support this but using df1.merge(df2, left_index=True, right_index=True) vs. df1.join(df2), I know which I’d prefer to write…</blockquote><p>So if you ever get asked in an interview what the difference is between the two, hopefully after reading this you can give a much better answer than the waffling I did when I was asked!</p><blockquote><em>💜</em> <strong><em>One final tip before you go!</em></strong><em> </em>I don’t know about you, but I <strong>love</strong> the <a href="https://pandas.pydata.org/docs/">pandas documentation</a>. Maybe it’s purely the amount of time I’ve spent reading it over the years but I find it so intuitive and well-formatted. The explanations of parameters are clear and further down the page provides examples which often cover my use case or are generic enough that I can easily apply it to my work. <strong>I’d highly recommend starting with the docs over StackOverFlow for your pandas syntax queries! </strong>Check out <a href="https://pandas.pydata.org/docs/reference/api/pandas.merge.html">merge</a> and <a href="https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.join.html">join</a> to see what I mean!</blockquote><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=436757cdd81e" width="1" height="1" alt=""><hr><p><a href="https://blog.dataengineerthings.org/joining-data-in-pandas-merge-vs-join-436757cdd81e">Joining data in pandas: merge vs. join</a> was originally published in <a href="https://blog.dataengineerthings.org/">Data Engineer Things</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[8 takeaways from Data Science interviews]]></title>
            <link>https://medium.com/data-science/8-takeaways-from-data-science-interviews-9945aa3745b3?source=rss-219e4d5d0c99------2</link>
            <guid isPermaLink="false">https://medium.com/p/9945aa3745b3</guid>
            <category><![CDATA[data]]></category>
            <category><![CDATA[job-hunting]]></category>
            <category><![CDATA[job-interview]]></category>
            <category><![CDATA[data-science]]></category>
            <dc:creator><![CDATA[Kerry Parker]]></dc:creator>
            <pubDate>Mon, 08 Jan 2024 19:23:06 GMT</pubDate>
            <atom:updated>2024-01-09T13:11:06.505Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ssSWE0E-4_9aIeHlreFRGg.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@christinhumephoto?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Christin Hume</a> on <a href="https://unsplash.com/photos/person-using-laptop-computer-Hcfwew744z4?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Unsplash</a></figcaption></figure><p>It’s been a while since I’ve shared an article, so hello again!</p><blockquote>Disclaimer: This article was written in August 2021, the principles still hold however some of the sites and features mentioned may have changed!</blockquote><p>I’m excited to write more articles in 2024 and share my journey as I move from Data Science to Data Engineering!</p><p>Applying for jobs can be a time-consuming process, in this article, I’ve pulled together some things that I’ve learned during my recent job application process.</p><p>I was interviewing for several roles during this time, each had several stages of interviews — the interview structure varied for each role but they all started with an informal chat with the internal recruiter to find out more about the role, the company and whether it would be a suitable fit.</p><p>Following from there, I experienced a combination of — interviews to talk through my experience, take-home tests, presentation of take-home test findings, technical interviews (SQL, quantitative analysis, statistics, data structure, algorithms), case study questions, and behavioural interviews.</p><p>Personally, I am not a fan of take-home tests, especially when applying for several jobs. I do enjoy a data challenge however when you are exhausted from a pandemic, your day job and also preparing for other stages of other job applications, I would much prefer to be assessed in an interview setting!</p><p>Here are my top takeaways from my recent job hunting!</p><h3><strong>1. Find a CV buddy</strong></h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-E5UwRaZ_DYhD-o_g9vwRw.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@joaoscferrao?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">João Ferrão</a> on <a href="https://unsplash.com/photos/white-printer-paper-on-macbook-pro-4YzrcDNcRVg?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Unsplash</a></figcaption></figure><p>Updating my CV can sometimes delay me when applying for jobs as it’s such a daunting task, I tend to put it off. On top of that, I often find myself getting stuck when trying to recall projects I’ve worked on and highlighting relevant details for the role I’m applying for — I’m too much of a perfectionist.</p><p>This time, however, I found myself a CV buddy — a friend who was also looking to update their CV. Over several video calls, we took turns going through our CVs, providing feedback to each other and the process of talking out loud helped to clarify important details. It certainly helped that they were also looking for Data roles so knew the types of skills and experience that would be applicable, but the most valuable part of teaming up was when explaining what we did in each role and having the other person summarise and pull out the relevant points! By discussing my work and being prompted by questions, I was reminded of substantially more details and was able to reword sections more succinctly. It was an iterative process over a few weeks where we would take our notes away, work to improve and come back together to further refine and we both came away with CVs that we were proud of.</p><h3><strong>2. Start with shared resources</strong></h3><p>In a few of the application processes, the recruiter provided links to resources that would be helpful when preparing for the interview. I briefly looked through these and spent time on the ones I considered most relevant, however in one case, I left a 1.5 hour YouTube video until later in the preparation as it felt overwhelming how long it was alongside many other resources that had been sent and I had collected myself. When I eventually got around to watching it, the content was incredibly useful and I regretted not watching it sooner!</p><h3><strong>3. Research the company and job interview process</strong></h3><p>It is also worth checking out Glassdoor as many people share their interview experience and the types of questions that they were asked in the interview. I made note of many of these questions to make sure that I was able to answer them, and also these came in handy when practising answering questions out loud. There are also many articles on Medium where people have shared their preparation for Data Science interviews, or with specific companies. My list of resources that I wanted to work through was way longer than the time I had to prepare so required some prioritisation. As mentioned above, in hindsight I should have started with the resources shared by the recruiter but I spent more time on the more technical-focused articles and tutorials to ensure I was up to scratch with those skills which, due to the level of detail and understanding required, was very time intensive!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2xzEI8QcatO0PUe953c0Sw.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@jasongoodman_youxventures?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Jason Goodman</a> on <a href="https://unsplash.com/photos/paper-on-wall-m2TU2gfqSeE?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Unsplash</a></figcaption></figure><h3><strong>4. Break it down</strong></h3><p>If, like me, you are preparing for several interviews in parallel, it can be useful to break down the interviews by topic, time required and memory retention. For example, if you have two interviews, both of which will be assessing your coding skills and a case study and one of them also has a behavioural interview, then it may be worth leaving the behavioural practice until last since you may wish to prepare some situations as examples that may come up. I find these types of questions are best to practice a day or two before the interview so that they are fresh in your memory.</p><p>For the coding, this is likely to be building on skills you already have and can be broken down to practising a few questions or running through a section of a tutorial each day leading up to the interview. If there is an area that you feel particularly weak in then it is useful to spend more time on this early on and you can then continue to practice questions on this topic to ensure you are confident and able to apply it — again speaking from experience here, I have little experience using SQL window functions and dedicated a fair amount of time to learn and practice these initially so that I felt confident in my first interview however before subsequent SQL interviews I didn’t spend much time practising these and panicked when under pressure. Before a final SQL interview, I knew that this had tripped me up previously so again spent some time practicing but by then I had lost my confidence and having only a day to prepare I didn’t feel as ready as I did in my initial interview!</p><p>The case study, for me, was quite a new concept in an interview so required some reading to understand what may be asked and how best to prepare. Personally, speaking through a scenario out loud with someone where they asked follow-up questions was the most helpful method.</p><h3><strong>5. Find out more</strong></h3><p>Throughout the recruitment process, I was able to talk to people within the company to ask questions about working for the company and was even offered a chat with someone about interview preparation. I’m not sure if this is usual as I’ve never come across it before but running through a practice interview question and being told what the interviewers would be looking for was incredibly helpful! After having several interviews though, each one was good preparation for the next since the types of questions and interview techniques were similar.</p><p>Another good tip would be to use your network, whether getting in touch with a connection who works for the company already or you could ask people you know who have recently got new jobs about their experience with recent interviews — there will be similarities in many of the interview processes within different companies for Data roles so it’s worth finding out more about what it was like for them and any tips they may have.</p><h3><strong>6. Interview practice questions</strong></h3><p>Here are a few resources I found useful when preparing for different types of interviews:</p><h4><strong>Statistics</strong></h4><p><a href="https://brilliant.org/courses/">Brilliant</a> has a wide range of statistics and maths courses, I really enjoyed the style of the questions however some courses do have overlapping content so it is worth being selective about which sections you complete so as not to waste time. I also signed up for the 7-day free trial which was useful for accessing more content but did require a commitment to focusing on stats for those 7 days.</p><h4><strong>SQL</strong></h4><p><a href="https://mode.com/sql-tutorial/introduction-to-sql/">Mode</a> has an interactive tutorial with access to a SQL database that you can use to practice queries.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*SiguEZ09idoerRub" /><figcaption>Photo by <a href="https://unsplash.com/@justin_morgan?utm_source=medium&amp;utm_medium=referral">Justin Morgan</a> on <a href="https://unsplash.com/?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><h4><strong>Case Studies</strong></h4><p>Overlapping with SQL, <a href="https://mode.com/sql-tutorial/sql-business-analytics-training/">Mode</a> has a few case study examples that are worth working through and also includes potential solutions to compare your answer to.</p><h4><strong>General Questions</strong></h4><p><a href="https://www.interviewquery.com/blog">Interview query</a> the blogs contained some useful example SQL, stats and case study questions to run through. I did also try to complete some of the questions on the site however you are limited to running 1 SQL query and viewing only a few solutions, even when signing up for an account so in my opinion the blogs would be more worthwhile.</p><p>Medium is full of interview preparation articles for Data Science jobs! Many articles with example questions and topics may come up, I found the articles useful to practice questions however they could often contain too much detail for example, one article contained a long list of Data Science and ML concepts and links to resources, which can be incredibly useful for your understanding but it is unlikely that you will need to learn all of these concepts for an interview.</p><p>Be realistic with the preparation time, the foundation of knowledge you already have and what you want from your next role!</p><h3><strong>7. Practice</strong></h3><p>As when writing your CV, it can be helpful to work together when preparing for job interviews. If your buddy is applying for a similar type of role, why not practice some of the technical questions together — perhaps choose a topic and ask each other interview-style questions or run through a case study and each prepare your answers — you’d be surprised how much you could learn from each other!</p><p>If your buddy is not in a similar industry, it can still be helpful to work through behavioural questions together or find a list of relevant interview questions and get someone to ask you them so that you can practice working through them out loud, communicating your answers (for example, using the STAR method)!</p><p>It is also great to have your job-hunting buddies for support when you have interviews, sharing how it went and cheering each other on! I have loved hearing about my friends smashing interviews and finding new roles where they can learn and grow!</p><h3><strong>8. Growth mindset</strong></h3><p>Regardless of the outcome of the interview, the time that you have spent researching and learning is helping you to grow! You may not find a suitable role this time but taking the time to reflect on your interview experience, what you have learnt, and requesting feedback from the interviewers will ultimately help you on the path to landing your next role!</p><h3><strong>Reflections</strong></h3><p>Whilst interviewing was an intense and busy process, I enjoyed dedicating time to brushing up on concepts that I haven’t used in a while and feel like I am a better Data Scientist because of it. I am grateful that I was offered and have accepted a new role and throughout the applications, I had a clear idea of my goals and expectations for my next role. During this time, I have also been able to reflect on what I have learnt from my current role and habits or projects I’d like to build going forward!</p><p>Have you recently been job hunting? What are your top takeaways?</p><p>If you enjoyed this article, you can <a href="https://kaparker.substack.com/">subscribe to my newsletter</a> to get my latest articles, resources I use and other tips directly in your inbox!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9945aa3745b3" width="1" height="1" alt=""><hr><p><a href="https://medium.com/data-science/8-takeaways-from-data-science-interviews-9945aa3745b3">8 takeaways from Data Science interviews</a> was originally published in <a href="https://medium.com/data-science">TDS Archive</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Data Analysis in python: Getting started with pandas]]></title>
            <link>https://medium.com/data-science/data-analysis-in-python-getting-started-with-pandas-8cbcc1500c83?source=rss-219e4d5d0c99------2</link>
            <guid isPermaLink="false">https://medium.com/p/8cbcc1500c83</guid>
            <category><![CDATA[data-science]]></category>
            <category><![CDATA[python]]></category>
            <category><![CDATA[pandas]]></category>
            <category><![CDATA[data-analysis]]></category>
            <category><![CDATA[editors-pick]]></category>
            <dc:creator><![CDATA[Kerry Parker]]></dc:creator>
            <pubDate>Wed, 24 Jun 2020 20:53:52 GMT</pubDate>
            <atom:updated>2020-06-25T19:25:35.336Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*3gHKHFxu3d7x6Wts-bGnjQ.png" /></figure><p>Pandas is a python tool used extensively for data analysis and manipulation. Recently I’ve been using pandas with large DataFrames (&gt;50M rows) and through the <a href="https://www.youtube.com/watch?v=C1hqHk1SfrA">PyDataUK May Talks</a> and exploring <a href="https://stackoverflow.com/">StackOverflow</a> threads have discovered several tips that have been incredibly useful in optimising my analysis.</p><p>This tutorial is part 1 of a series and aims to give an introduction to pandas and some of the useful features it offers while exploring the <a href="https://allisonhorst.github.io/palmerpenguins/index.html">Palmer Penguin dataset</a>.</p><p>In this article, we will go through:</p><ul><li>How to install and import pandas</li><li>Data structures in pandas</li><li>How to input and output data</li><li>Inspecting the data</li><li>Getting started with Data Cleaning</li></ul><h3>Introducing Palmer Penguins</h3><p>The iris dataset is one that is commonly used for visualisation and pattern recognition in Data Science. Since recently discovering the author’s link with eugenics, there has been an effort to source other datasets for use. <br>That’s where the penguins come in, the <a href="https://allisonhorst.github.io/palmerpenguins/index.html">Palmer Penguins dataset</a> has been collected and published by <a href="https://www.uaf.edu/cfos/people/faculty/detail/kristen-gorman.php">Dr. Kristen Gorman</a> and <a href="https://www.allisonhorst.com/">Allison Horst</a> under the CC-0 licence as an alternative dataset to explore!</p><p>It has been published with examples for use in R, but we will be using python package pandas to explore the raw dataset that can be found on <a href="https://github.com/allisonhorst/palmerpenguins/tree/1a19e36ba583887a4630b1f821e3a53d5a4ffb76/data-raw">GitHub</a> (note the raw CSV file is no longer included in the main branch as it was when I first started looking at the dataset, so I refer here to an old commit in the repository. I will update this if the file gets readded into the main branch).</p><p>The data contains observations for three distinct penguin species on islands in the Palmer Archipelago, Antarctica and we can use the data to compare the body mass, flipper lengths or culmen dimensions between the different species or Islands.</p><h4>Let’s get started!</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*KU-V8tWWQU3nDtw12-bQ_g.png" /><figcaption><a href="https://github.com/allisonhorst/palmerpenguins/blob/master/vignettes/articles/img/lter_penguins.png">Artwork</a> by <a href="https://twitter.com/allison_horst">@allison_horst</a></figcaption></figure><h3>1. Install and import pandas</h3><p>Pandas can be installed from <a href="https://pypi.org/project/pandas/">PyPI</a> using the python package manager pip: pip install pandas</p><p>Or using conda with: conda install pandas</p><p>Once installed, we can import pandas and assign an alias of pd with:</p><pre>import pandas as pd</pre><h3>2. Data structures</h3><p>There are two data structures in pandas, Series and DataFrames. The structure I most commonly use is a DataFrame, a 2D tabular structure with labels, similar to a spreadsheet or SQL table.</p><p>The other structure is a Series which is a 1D labelled array that can hold any data type. Each row is labelled with an index.</p><p>A DataFrame can be built in many different ways including as a dictionary of Series, where each Series is a column in the DataFrame.</p><p>This article will focus on DataFrames and we will use a CSV as input to the DataFrame.</p><p>To explore data structures further check out the <a href="https://pandas.pydata.org/pandas-docs/stable/getting_started/dsintro.html">pandas documentation</a>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2rTTJJ0IhXuDB-GwVz2HxA.png" /><figcaption>Example of a pandas Series and DataFrame</figcaption></figure><h3>3. Input and output data</h3><h4>Input</h4><p>DataFrames can be created in a variety of ways:</p><p>A) Create an empty DataFrame: df = pd.DataFrame()</p><p>B) Input data: df = pd.DataFrame(data = data), where the input data can be in many different formats, making building a DataFrame flexible and convenient as the data you work with may be in any number of structures including a dictionary of Series and as represented in the diagram above and can be built with the following code:</p><pre>d = {&#39;student1&#39;: pd.Series([85., 72.], index=[&#39;maths&#39;, &#39;science&#39;]),<br>   &#39;student2&#39;: pd.Series([62., 70., 55.], index=[&#39;maths&#39;, &#39;science&#39;, &#39;english&#39;]),<br>   &#39;student3&#39;: pd.Series([45., 48., 70.], index=[&#39;maths&#39;, &#39;science&#39;, &#39;english&#39;])}<br>df = pd.DataFrame(d)<br>print(df.head())</pre><p>C) Input from a file or data source which we will focus on here looking at the <a href="https://raw.githubusercontent.com/allisonhorst/palmerpenguins/1a19e36ba583887a4630b1f821e3a53d5a4ffb76/data-raw/penguins_raw.csv">raw CSV of the Palmer Penguin data</a>.</p><p>Much like when building a DataFrame using input data, when creating a DataFrame from a file or data source, many input formats are accepted. <br>This includes:</p><ul><li>excel spreadsheets</li><li>SQL</li><li>CSV</li><li>JSON</li></ul><p>Check out the <a href="https://pandas.pydata.org/pandas-docs/stable/reference/io.html">pandas documentation</a> for the full list.</p><p>This offers a lot of flexibility in data storage and you can read in files that are stored locally, remotely and it even accepts compressed files.</p><p>The Palmer Penguin file we are interested is hosted on GitHub, you can download this file and read the CSV specifying the location on your machine, or we can provide the link to the raw file and open it with one line of code:</p><pre>df = pd.read_csv(&#39;https://raw.githubusercontent.com/allisonhorst/palmerpenguins/1a19e36ba583887a4630b1f821e3a53d5a4ffb76/data-raw/penguins_raw.csv&#39;)</pre><p>Another common data source is an SQL database. There are many different python packages to connect to the database, one example is pymysql where we can first connect to a MySQL database and then use read_sql to load the data from the query into df. This offers the flexibility to connect to remote databases quickly and easily!</p><p><strong>Note: This is just an example of how to read in SQL data and is not used in the tutorial</strong></p><pre># Example code: how to use read_sql<br>import pymysql</pre><pre>con = pymysql.connect(host=&#39;localhost&#39;, user=&#39;test&#39;, password=&#39;&#39;, db=&#39;palmerpenguins&#39;)</pre><pre>df = read_sql(f&#39;&#39;&#39;SELECT * FROM penguins&#39;&#39;&#39;, con)</pre><p>💡 <a href="https://realpython.com/python-f-strings/">Python 3’s f-strings</a> are convenient to use when inputting queries.</p><p>We might later input a condition that uses a variable we have previously defined and instead of hard-coding the condition we can include the variable directly in the f-string.</p><p>The triple quotation also allows single quotes to be used within the f-string without an escape character as in the example below. For example:</p><pre># Example code: f-string&#39;s and variables<br>region = tuple(&#39;Anvers&#39;)</pre><pre>df = read_sql(f&#39;&#39;&#39;SELECT * FROM penguins WHERE Region IN {region} AND Date Egg &gt; &#39;2007-11-11&#39; &#39;&#39;&#39;, con)</pre><h4><strong>Large DataFrames</strong></h4><p>When reading in large datasets, it is possible to iterate over the file and read in a limited number of rows per iteration by specifying the option of chunksize to read_csv , read_sql or other input functions. However, it is worth noting that this function now returns a TextFileReader instead of a DataFrame and requires a further step to concatenate the chunks into one DataFrame.</p><pre>df = read_csv(&#39;https://raw.githubusercontent.com/allisonhorst/palmerpenguins/1a19e36ba583887a4630b1f821e3a53d5a4ffb76/data-raw/penguins_raw.csv&#39;, chunksize = 10000)</pre><pre>df_list = []<br>for df in df:<br>    df_list.append(df)</pre><pre>df = pd.concat(df_list,sort=False)</pre><p>This step is not necessary to use on the Palmer Penguin dataset as it’s only a few hundred rows, but is shown here to demonstrate how you could use this on a large file to read the data in 10k rows at a time.</p><h4><strong>Output</strong></h4><p>Just as we can input the file in many formats, to output a DataFrame to a file is just as flexible and easy!</p><p>After some manipulation, we can write our DataFrame to a CSV with the option to compress the file if required:</p><pre>df.to_csv(&#39;output.csv&#39;, compression=&#39;gzip)</pre><p>If your data is stored within AWS, there is an AWS SDK for Python, <a href="https://boto3.amazonaws.com/v1/documentation/api/latest/index.html">boto3</a> that can be used to connect to your AWS services.</p><h3>4. Quick checks to inspect the data</h3><p>Before we start exploring our data, the first thing to check that it has loaded correctly and contains what we expect.</p><h4>Dimensions of DataFrame</h4><p>We can first check that the DataFrame is not empty by checking that the number of rows is greater than 0 and further check the dimensions with the following functions:</p><ul><li>Get the number of rows: len(df)</li><li>Get the number of columns: len(df.columns)</li><li>Get the number of rows and columns: df.shape</li><li>Get the number of elements (rows X columns): df.size</li></ul><pre>if len(df) &gt; 0:<br>    print(f&#39;Length of df {len(df)}, number of columns {len(df.columns)}, dimensions {df.shape}, number of elements {df.size}&#39;)</pre><pre>else:<br>    print(f&#39;Problem loading df, df is empty.&#39;)</pre><p>This returns:</p><pre>Length of df 344, number of columns 17, dimensions (344, 17), number of elements 5848</pre><p>Our dataset has loaded correctly and has 344 rows and 17 columns. What does this DataFrame contain?</p><h4>dtypes and memory</h4><p>We’ve loaded in the DataFrame but we still don’t know what type of data it contains. We can get a summary with df.info()- let&#39;s take a look at what details it returns:</p><pre>df.info()</pre><pre>&lt;class &#39;pandas.core.frame.DataFrame&#39;&gt;<br>RangeIndex: 344 entries, 0 to 343<br>Data columns (total 17 columns):<br>studyName              344 non-null object<br>Sample Number          344 non-null int64<br>Species                344 non-null object <br>Region                 344 non-null object <br>Island                 344 non-null object <br>Stage                  344 non-null object <br>Individual ID          344 non-null object <br>Clutch Completion      344 non-null object <br>Date Egg               344 non-null object <br>Culmen Length (mm)     342 non-null float64 <br>Culmen Depth (mm)      342 non-null float64 <br>Flipper Length (mm)    342 non-null float64 <br>Body Mass (g)          342 non-null float64 <br>Sex                    334 non-null object <br>Delta 15 N (o/oo)      330 non-null float64 <br>Delta 13 C (o/oo)      331 non-null float64 <br>Comments               54 non-null object <br>dtypes: float64(6), int64(1), object(10) memory usage: 45.8+ K </pre><p>df.info() returns:</p><ul><li>the index data type (dtype) and range, in this case, a pandas DataFrame with 344 entries denoted by index values 0–343,</li><li>the name and dtypes of each column, and the number of non-null values,</li><li>the memory usage</li></ul><p>The penguin data contains columns with mixed or string datatypes objects, integers int64 and floats float64. The table below summarises dtypes in pandas.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/916/1*wrXMq7iTWih7lsBBRQFxXg.png" /><figcaption>Pandas dtypes</figcaption></figure><p>Using <a href="https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.info.html">df.info()</a> the memory usage by default only gives us an estimation based on the column dtype and number of rows. <br>We can specify to use deep introspection to calculate the real memory usage which can be particularly useful when dealing with large dataframes:</p><pre>df.info(memory_usage=&#39;deep&#39;)</pre><pre><br>&lt;class &#39;pandas.core.frame.DataFrame&#39;&gt; <br>RangeIndex: 344 entries, 0 to 343 <br>Data columns (total 17 columns): <br>studyName              344 non-null object <br>Sample Number          344 non-null int64 <br>Species                344 non-null object <br>Region                 344 non-null object <br>Island                 344 non-null object <br>Stage                  344 non-null object <br>Individual ID          344 non-null object <br>Clutch Completion      344 non-null object <br>Date Egg               344 non-null object <br>Culmen Length (mm)     342 non-null float64 <br>Culmen Depth (mm)      342 non-null float64 <br>Flipper Length (mm)    342 non-null float64 <br>Body Mass (g)          342 non-null float64 <br>Sex                    334 non-null object <br>Delta 15 N (o/oo)      330 non-null float64 <br>Delta 13 C (o/oo)      331 non-null float64 <br>Comments               54 non-null object <br>dtypes: float64(6), int64(1), object(10) memory usage: 236.9 KB</pre><p>We can also check the memory usage per column with:</p><pre>print(df.memory_usage(deep=True))<br>Index                     80 <br>studyName              22016 <br>Sample Number           2752 <br>Species                31808 <br>Region                 21672 <br>Island                 21704 <br>Stage                  25800 <br>Individual ID          21294 <br>Clutch Completion      20604 <br>Date Egg               23048 <br>Culmen Length (mm)      2752 <br>Culmen Depth (mm)       2752 <br>Flipper Length (mm)     2752 <br>Body Mass (g)           2752 <br>Sex                    21021 <br>Delta 15 N (o/oo)       2752 <br>Delta 13 C (o/oo)       2752 <br>Comments               14311 <br>dtype: int64 </pre><p>Or the total memory usage with the following:</p><pre>print(df.memory_usage(deep=True).sum())</pre><pre>242622</pre><p>We can see here that the numerical columns are significantly smaller than the columns containing objects. Not only that but we aren’t interested in all the columns in our analysis.</p><p>This raw file contains all the data that has been collected. If we are to compare the body mass, flipper lengths and culmen dimensions in the different species of penguins and on the different islands, then we can clean the data and keep only the data that is relevant.</p><h3>5. Data cleaning</h3><p>To clean the data there are several steps we can take:</p><h4>Remove columns we aren’t interested in</h4><p>Let’s take a first glance at the first few rows of data:</p><pre>print(df.head())</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/801/1*RbC5QoNJO6-towYeAXzSqQ.png" /><figcaption>Output of df.head()</figcaption></figure><p>This output doesn’t look quite right. We know that there are 17 columns but we can only see 4 of them plus the index here. Depending on the size of the console you are working in, you might see a few more columns here but probably not all 17.</p><p>To view all the columns, we can set the value for display.max_columns to be None.</p><pre>pd.set_option(&#39;display.max_columns&#39;, None)<br>print(df.head())</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/588/1*PNyHQuo-70KTgLlyL9PTVA.png" /><figcaption>Output of df.head() after setting the max columns to be None</figcaption></figure><p>Looking at a sample of the data, we can identify the columns that we want to use and reassigning a new value to df by specifying only the rows and columns we want to keep. We can use df.loc(rows, cols) to do this. In the rows argument, a colon denotes all values and the columns we can specify the columns we are interested in, which are: Species, Region, Island, Culmen Length (mm), Culmen Depth (mm), Flipper Length (mm), Body Mass (g), Sex</p><pre><br>keep_cols = [&#39;Species&#39;, &#39;Region&#39;, &#39;Island&#39;, &#39;Culmen Length (mm)&#39;, &#39;Culmen Depth (mm)&#39;, &#39;Flipper Length (mm)&#39;, &#39;Body Mass (g)&#39;, &#39;Sex&#39;]</pre><pre>df = df.loc[:, keep_cols]  </pre><pre>print(df.columns)  </pre><pre>&gt;&gt;&gt; Index([&#39;Species&#39;, &#39;Region&#39;, &#39;Island&#39;, &#39;Culmen Length (mm)&#39;,        &#39;Culmen Depth (mm)&#39;, &#39;Flipper Length (mm)&#39;, &#39;Body Mass (g)&#39;, &#39;Sex&#39;],       dtype=&#39;object&#39;</pre><p>We now only have the columns of interest stored in our DataFrame.</p><h4>Replace or drop null values</h4><p>We can check again the memory usage of df and we can see it has halved by removing irrelevant columns.</p><pre>df.info(memory_usage=&#39;deep&#39;)</pre><pre>&lt;class &#39;pandas.core.frame.DataFrame&#39;&gt; <br>RangeIndex: 344 entries, 0 to 343 <br>Data columns (total 8 columns): <br>Species                344 non-null object <br>Region                 344 non-null object <br>Island                 344 non-null object <br>Culmen Length (mm)     342 non-null float64 <br>Culmen Depth (mm)      342 non-null float64 <br>Flipper Length (mm)    342 non-null float64 <br>Body Mass (g)          342 non-null float64 <br>Sex                    334 non-null object <br>dtypes: float64(4), object(4) memory usage: 104.8 KB </pre><p>Looking at the number of non-null values, the size data has 2 null values and the sex has 10. We can also see this with:</p><pre>print(df.isna().sum())  <br>Species                 0 <br>Region                  0 <br>Island                  0 <br>Culmen Length (mm)      2 <br>Culmen Depth (mm)       2 <br>Flipper Length (mm)     2 <br>Body Mass (g)           2 <br>Sex                    10 <br>dtype: int64</pre><p>We can either drop these values or replace them with another value, specifying inplace=True in the function to reassign the value. <br>In this case, we can replace the na values with Unknown for the Sex columns and we can drop the na values for the other columns.</p><pre>df[&#39;Sex&#39;].fillna(&#39;Unknown&#39;, inplace=True) </pre><pre>print(df.isna().sum())  </pre><pre>Species                0 <br>Region                 0 <br>Island                 0 <br>Culmen Length (mm)     2 <br>Culmen Depth (mm)      2 <br>Flipper Length (mm)    2 <br>Body Mass (g)          2 <br>Sex                    0 <br>dtype: int64  </pre><pre>df.dropna(inplace=True) </pre><pre>print(df.isna().sum())  </pre><pre>Species                0 <br>Region                 0 <br>Island                 0 <br>Culmen Length (mm)     0 <br>Culmen Depth (mm)      0 <br>Flipper Length (mm)    0 <br>Body Mass (g)          0 <br>Sex                    0 <br>dtype: int64</pre><p>Since there were only a few values we removed, this is unlikely to impact the memory usage but is useful to clean the data and when dealing with large DataFrames with a significant number of null values, it may reduce memory.</p><h4>Convert objects to Categorical dtypes</h4><p>The final step in cleaning our data is to check the number of unique values in each column to determine whether a categorical dtype is more suitable in place of using objects.</p><p>We already know that there are three penguin species in our data yet the dtype for this column is an object, so let&#39;s check this column first.</p><pre>print(df[&#39;Species&#39;].head())  </pre><pre>0    Adelie Penguin (Pygoscelis adeliae) <br>1    Adelie Penguin (Pygoscelis adeliae) <br>2    Adelie Penguin (Pygoscelis adeliae) <br>4    Adelie Penguin (Pygoscelis adeliae) <br>5    Adelie Penguin (Pygoscelis adeliae) <br>Name: Species, dtype: object  </pre><pre>print(df[&#39;Species&#39;].nunique())  </pre><pre>3  </pre><pre>print(df[&#39;Species&#39;].unique())  </pre><pre>[&#39;Adelie Penguin (Pygoscelis adeliae)&#39; &#39;Gentoo penguin (Pygoscelis papua)&#39;  &#39;Chinstrap penguin (Pygoscelis antarctica)&#39;]</pre><p>As expected there are only 3 unique values in this column but each row contains a string with the penguin species, taking up significant memory. We can instead convert this column to be a category dtype and check how this changes the memory.</p><pre>print(df.memory_usage(deep=True))</pre><pre>Index                   2736<br>Species                31626<br>Region                 21546<br>Island                 21575<br>Culmen Length (mm)      2736<br>Culmen Depth (mm)       2736<br>Flipper Length (mm)     2736<br>Body Mass (g)           2736<br>Sex                    21213<br>dtype: int64</pre><pre>df[&#39;Species&#39;] = df[&#39;Species&#39;].astype(&#39;category&#39;)</pre><pre>print(df.memory_usage(deep=True))</pre><pre>Index                   2736<br>Species                  702<br>Region                 21546<br>Island                 21575<br>Culmen Length (mm)      2736<br>Culmen Depth (mm)       2736<br>Flipper Length (mm)     2736<br>Body Mass (g)           2736<br>Sex                    21213<br>dtype: int64</pre><p>This has now gone from 31626 bytes to 702, reducing the size significantly! The same approach can be taken for the other object columns, Region, Island and Sex.</p><pre>for col in [&#39;Region&#39;,&#39;Island&#39;,&#39;Sex&#39;]:<br>    print(f&#39;Column: {col}, number of unique values, {df[col].nunique()}, unique values: {df[col].unique()}&#39;)</pre><pre>Column: Region, number of unique values, 1, unique values: [&#39;Anvers&#39;]<br>Column: Island, number of unique values, 3, unique values: [&#39;Torgersen&#39; &#39;Biscoe&#39; &#39;Dream&#39;]<br>Column: Sex, number of unique values, 4, unique values: [&#39;MALE&#39; &#39;FEMALE&#39; &#39;Unknown&#39; &#39;.&#39;]</pre><p>Region has only one value, this column can be removed since it doesn’t provide any value.</p><pre>df.drop(columns=[&#39;Region&#39;], inplace=True)<br>print(df.columns)</pre><pre>Index([&#39;Species&#39;, &#39;Island&#39;, &#39;Culmen Length (mm)&#39;, &#39;Culmen Depth (mm)&#39;,<br>       &#39;Flipper Length (mm)&#39;, &#39;Body Mass (g)&#39;, &#39;Sex&#39;],<br>      dtype=&#39;object&#39;)</pre><p>Island and Sex can be converted to categorical dtypes in the same way as Species. Before we do that, there is a strange value in the Sex column of a full-stop, let’s take a look at how many of these there are.</p><pre>print((df[&#39;Sex&#39;]==&#39;.&#39;).value_counts())</pre><pre>False    341<br>True       1<br>Name: Sex, dtype: int64</pre><p>Since there is only 1 value, let’s replace it with Unknown in the same way that we replaced the null values.</p><pre>df[&#39;Sex&#39;].replace(&#39;.&#39;,&#39;Unknown&#39;, inplace=True)<br>print((df[&#39;Sex&#39;]==&#39;.&#39;).value_counts())</pre><pre>False    342<br>Name: Sex, dtype: int64</pre><p>Now we are happy with the columns, let’s convert Sex and Island to categories and check the final memory usage:</p><pre>df[&#39;Sex&#39;] = df[&#39;Sex&#39;].astype(&#39;category&#39;)<br>df[&#39;Island&#39;] = df[&#39;Island&#39;].astype(&#39;category&#39;)</pre><pre>print(df.memory_usage(deep=True))</pre><pre>Index                  2736<br>Species                 702<br>Island                  613<br>Culmen Length (mm)     2736<br>Culmen Depth (mm)      2736<br>Flipper Length (mm)    2736<br>Body Mass (g)          2736<br>Sex                     610<br>dtype: int64</pre><pre>print(df.memory_usage(deep=True).sum())</pre><pre>15605</pre><p>The total memory usage has gone from 242622 to 15605.</p><pre>df.info(memory_usage=&#39;deep&#39;)</pre><pre>&lt;class &#39;pandas.core.frame.DataFrame&#39;&gt;<br>Int64Index: 342 entries, 0 to 343<br>Data columns (total 7 columns):<br>Species                342 non-null category<br>Island                 342 non-null category<br>Culmen Length (mm)     342 non-null float64<br>Culmen Depth (mm)      342 non-null float64<br>Flipper Length (mm)    342 non-null float64<br>Body Mass (g)          342 non-null float64<br>Sex                    342 non-null category<br>dtypes: category(3), float64(4)<br>memory usage: 15.2 KB</pre><p>Reducing the memory from 236.9 KB to 15.2 KB.</p><h4>Mission accomplished!</h4><p>We’ve so far covered how to get started with reading a file into pandas and cleaning the file to optimise performance. The penguin data is already well structured, with only minimal cleaning needed compared to the types of data you might come across from other sources. It is also a fairly small dataset starting at 200 KB when pandas can deal with files in the order of GBs, where these quick tips can yield significant improvements in performance.</p><p>This is part 1 of a series of tutorials. In the following parts, we will explore our data quantitively and graphically, creating data visualisations using pandas, and some additional python packages — matplotlib and seaborn and we will dive into some other features of pandas that are useful to know!</p><p>The full code from this tutorial can be found on <a href="https://github.com/kaparker/tutorials/tree/master/penguin-analysis">GitHub</a>!</p><p>Are there any pandas functions for data inspection and cleaning that you’d like to hear more about? Or any I’ve missed? <a href="https://twitter.com/_kaparker">Let me know</a>!<br> <br>If you enjoyed this article, you can <a href="https://kaparker.substack.com/">subscribe to my monthly newsletter</a> to get my latest articles, resources I use and other tips directly in your inbox!</p><p>Want to learn about web scraping or learning resources, including data science courses in python, check out some of my other articles:</p><ul><li><a href="https://towardsdatascience.com/data-science-skills-web-scraping-using-python-d1a85ef607ed">Data Science Skills: Web scraping using python</a></li><li><a href="https://towardsdatascience.com/learn-to-code-learn-python-efb037b248e8">Learn to code. Learn Python.</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=8cbcc1500c83" width="1" height="1" alt=""><hr><p><a href="https://medium.com/data-science/data-analysis-in-python-getting-started-with-pandas-8cbcc1500c83">Data Analysis in python: Getting started with pandas</a> was originally published in <a href="https://medium.com/data-science">TDS Archive</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Learn to code. Learn Python.]]></title>
            <link>https://medium.com/data-science/learn-to-code-learn-python-efb037b248e8?source=rss-219e4d5d0c99------2</link>
            <guid isPermaLink="false">https://medium.com/p/efb037b248e8</guid>
            <category><![CDATA[coding]]></category>
            <category><![CDATA[python]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[data-science]]></category>
            <dc:creator><![CDATA[Kerry Parker]]></dc:creator>
            <pubDate>Mon, 04 May 2020 21:44:06 GMT</pubDate>
            <atom:updated>2025-02-24T22:49:53.197Z</atom:updated>
            <content:encoded><![CDATA[<h3>Learning to code? Start here!</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/560/1*-jfnkT8dBbPFXgH0REfWYA.png" /></figure><p>Are you wanting to learn to code but unsure where to start? You’ve come to the right place. I’ll walk you through the reasons to learn Python to help you decide if it’s right for you and provide a list of resources to learn the basics, get your environment set up, find projects to get started with and where you can go for help and support through your coding journey.</p><h3><strong>Why learn Python?</strong></h3><p>Python is a versatile programming language that can be used for software development, data analysis, machine learning and even web development! If you’re wanting to program robots, follow a career in Data Science or make pretty visualisations, learning python is a good place to start!</p><p>If this is your first experience of learning to code then the syntax (the structure of statements) is similar to English, requires fewer lines of code and once you have the basic grasp of the logic, syntax and structure, it can be easily applied to other programming languages.</p><p>However, if you are more focused on web or app development, there may be other programming languages out there that you might want to consider instead. HTML, CSS and JavaScript are also great starting points when learning to code. Don’t stop reading just yet though, many of the resources and tips below are relevant to any new developer!</p><h3><strong>Resources</strong></h3><p>Depending on your style of learning, there are different types of courses you can follow. There are written tutorials with code examples, short videos with interactive coding problems, live-coding videos or the simple textbook. I’ve included a range of resources in this list so that you can give them a try and decide which learning style works best for you.</p><h4><strong>Learn to Code for free</strong></h4><p><strong>1. FreeCodeCamp</strong></p><p><a href="https://www.freecodecamp.org/">FreeCodeCamp</a> is a dedicated community platform for learning to code. They have courses, tutorials, videos and articles to help you get started and cover many different programming languages. The <a href="http://freecodecamp.org/learn">courses on their website</a> are mainly focussed on web development and are a great starting point if you want to learn HTML, CSS and JavaScript! <br>For python, they have put together a <a href="https://www.freecodecamp.org/news/best-python-tutorial/">comprehensive guide</a> to resources, as well as a <a href="https://www.youtube.com/watch?v=rfscVS0vtbw">YouTube course</a>.</p><p><strong>Programming languages: </strong>Python, HTML, CSS, JavaScript + more<br><strong>Level:</strong> Beginner, Intermediate, Advanced<br><strong>Content type:</strong> Articles, Videos, Interactive Tutorials</p><p><strong>2. HiPy</strong></p><p><a href="http://hipy.uk/">HiPy</a> is an open community of people dedicated to introducing anyone and everyone to coding in Python. They run regular events in Liverpool and have a series of beginner-friendly <a href="https://github.com/HiPyLiv/HiPyProject">notebooks</a> which you can work through and an <a href="https://colab.research.google.com/drive/1XpiY4CrM1bH521VNWouqx-M52QBa8XQS">Intro to Python course</a> covering how to get started. They also have a <a href="https://www.youtube.com/channel/UCwx8lBs4yUPBNvyq_VQcwJg">YouTube</a> channel and have recently streamed live-coding events that are definitely worth a watch!</p><p><strong>Programming languages: </strong>Python<br><strong>Level:</strong> Beginner, Intermediate, Advanced<br><strong>Type:</strong> Tutorials, Videos, Events</p><p>3. <strong>EdX Courses</strong></p><p>EdX has a range of <a href="https://www.edx.org/learn/python">python courses</a> available. The courses are free to complete with an option to pay for a certificate. The courses are often run by companies or Universities and you may need to explore to find a course that is the right style for you. I’ve found the courses very hit and miss!</p><p>Check out this <a href="https://www.edx.org/course/introduction-to-python-absolute-beginner-2">Microsoft course</a> for an Intro to Python for absolute beginners!</p><p><strong>Programming languages:</strong> Python, HTML, CSS, JavaScript + more<br><strong>Level: </strong>Beginner, Intermediate, Advanced<br><strong>Type:</strong> Courses</p><p><strong>4. Coursera</strong></p><p>Similar to EdX, <a href="https://www.coursera.org/">Coursera</a> has a range of different courses available for free, with payment to receive certification.</p><p>If you’re looking for an introduction to Machine Learning, I completed <a href="https://www.coursera.org/learn/machine-learning">Andrew Ng’s Machine Learning</a> course last year and highly recommend checking it out! It provides a broad overview with weekly assignments and questions alongside the course. I really enjoyed the style of teaching and the assignments were interesting and appropriately challenging! My only warning is that the assignments use a programming language called Octave which could sometimes be a little awkward — there is an intro to Octave within the course however if you are new to programming, you might find it a little tricky at times!</p><p><strong>Programming languages:</strong> Python, HTML, CSS, JavaScript + more<br><strong>Level: </strong>Beginner, Intermediate, Advanced<br><strong>Type:</strong> Courses</p><p><strong>5. Kaggle micro-courses</strong></p><p><a href="http://kaggle.com/">Kaggle</a> is a data science platform which hosts competitions and data challenges. It also provides micro-courses including an <a href="https://www.kaggle.com/learn/python">introduction to python</a> alongside a <a href="https://www.youtube.com/user/kaggledotcom">YouTube channel</a> with live-coding demonstrations including concepts in python and data science. Once you have the basics and with a foundation in Data Science, you can get involved with the community, practice your skills with the playground competitions such as the <a href="https://www.kaggle.com/c/titanic">Titanic</a> challenge or explore the <a href="https://www.kaggle.com/datasets">Kaggle datasets</a> for use in your own projects.</p><p><strong>Programming languages:</strong> Python<br><strong>Level:</strong> Intermediate, Advanced<br><strong>Type: </strong>Tutorials, Videos</p><p><strong>6. W3Schools</strong></p><p><a href="https://www.w3schools.com/">W3Schools</a> is a website for learning web technologies, containing code examples and includes interactive tutorials in Python, HTML, CSS and JavaScript. I often find myself referring back to w3 for documentation and detailed explanations with examples of how to use the function or package.</p><p><strong>Programming languages:</strong> Python, HTML, CSS, JavaScript + more<br><strong>Level:</strong> Beginner<br><strong>Type: </strong>Documentation, Tutorials</p><p><strong>7. Udemy</strong></p><p><a href="http://udemy.com/">Udemy</a><strong> </strong>offers over 100k online courses from a wide range of topics and also in different languages. There is an overwhelming number of python courses from different instructors however you can narrow this down by specifying only free courses and selecting your level and topics you are looking for. I’d recommend learning the basics with the resources above and using Udemy to dive deeper into a specific topic if you are familiar with an instructor and like their teaching style.</p><blockquote><strong>Note:</strong> Udemy also contains paid courses but they often have a sale on, reducing the price significantly so it’s best to wait for these!</blockquote><p><strong>Programming languages: </strong>Python, HTML, CSS, JavaScript + more<br><strong>Level: </strong>Beginner, Intermediate, Advanced<br><strong>Type:</strong> Course</p><p><strong>8. Automate the Boring Stuff with Python</strong></p><p>If you prefer books, <a href="https://automatetheboringstuff.com/"><em>Automate the Boring Stuff with Python</em></a> is a great place to get started and the content is also available online. It provides practical examples on how to get started and project examples you can work through at the end of each chapter.</p><p><strong>Programming languages: </strong>Python<br><strong>Level: </strong>Beginner, Intermediate<br><strong>Type:</strong> Book</p><p><strong>9. Python for Data Science</strong></p><p>If you’ve grasped the basics and are looking to explore Python with data science, <a href="https://jakevdp.github.io/PythonDataScienceHandbook/">Python for Data Science</a> is a valuable resource and again is available for free online, although also handy to have a copy to pick up off the shelf!</p><p><strong>Programming languages: </strong>Python<br><strong>Level: </strong>Intermediate, Advanced<br><strong>Type:</strong> Book</p><h4><strong>Paid Resources</strong></h4><p>There are also resources that offer subscriptions for their learning platforms</p><p><strong>1. 365DataScience</strong></p><p><a href="https://365datascience.com/">365DataScience</a> is a Data Science learning platform with an initial free tier to sample the course material. I’ve not used this resource personally, but they cover a range of topics in data science and have a free tier to give you a taster before you commit to the subscription.</p><p><strong>Programming languages: </strong>Python, SQL<br><strong>Level:</strong> Intermediate, Advanced<br><strong>Type:</strong> Interactive Tutorials</p><p><strong>2. Learn the basics with Codecademy</strong></p><p><a href="https://www.codecademy.com/learn/learn-python-3">Codecademy</a> requires a subscription to access the full course content and offers introductory and advanced courses to different programming languages. The content that is free to access has changed significantly over time. Whilst this was my go-to resource when I was first learning Python as I liked the interactive style of the courses, now with the platform, you can be mid-way through a chapter and are unable to progress unless you sign up.</p><p><strong>Programming languages:</strong> Python, HTML, CSS, JavaScript + more<br><strong>Level: </strong>Beginner, Intermediate<br><strong>Type: </strong>Interactive Tutorials</p><p><strong>3. DataQuest</strong></p><p>If you’re already familiar with the basics in Python and are looking to apply your knowledge to concepts in data science, check out <a href="https://www.dataquest.io/directory/">DataQuest</a>. Like the previous two platforms, DataQuest also requires a subscription however they do offer a free trial so if you’re interested, give it a try!</p><p><strong>Programming languages:</strong> Python, SQL, R<br><strong>Level:</strong> Intermediate, Advanced<br><strong>Type:</strong> Interactive Tutorials</p><h3><strong>Troubleshooting</strong></h3><p>One of the hardest parts when learning to code can be trying to work out what to search for when you’re stuck. This does get easier the more you practice! Here are a few common places where you might find the answers you are looking for:</p><p><strong>1. StackOverflow</strong></p><p>When searching for a programming question, the top results are usually from <a href="https://stackoverflow.com/">StackOverflow</a>. Stackoverflow is an open community where people can ask questions and other developers try to help. Chances are, the problem you’re having, others have already asked on StackOverflow with possible solutions waiting for you!</p><p><strong>2. DEV.to</strong></p><p><a href="https://dev.to/t/python">DEV</a> is a community of software developers getting together to help one another out. The platform supports collaboration and networked learning through articles, tutorials and discussions in addition to podcasts and videos shared by the development community! If you sign up, you too can share your coding journey and the things that you learn with the community and meet other people learning to code too!</p><p><strong>3. Medium</strong></p><p><a href="https://medium.com/">Medium</a> has a range of publications dedicated to learning to code. TowardsDataScience has many articles and tutorials on Data Science and Python, BetterProgramming and HackerNoon also have content around programming and you may also find company blogs such as Netflix Technology Blog who share technical articles and tutorials.</p><p><strong>4. Data Science Stack Exchange</strong></p><p>Similar to StackOverflow, <a href="https://datascience.stackexchange.com/">Data Science Stack Exchange</a> is a forum to ask technical questions, this time specific to Data Science and Machine Learning. When troubleshooting Python questions, this resource often appears in the top search results and is another site where the community may already have the answer you are looking for!</p><p><strong>5. Twitter</strong></p><p>There is a large tech community on Twitter. Many people join <a href="https://www.100daysofcode.com/">#100DaysOfCode</a>, committing to tweet every day they code over the course of 100 days, sharing what they’ve been learning and supporting others in their journeys too. If you are stuck, you can also reach out to this community and someone may be able to answer your question or point you to something that could help!</p><p><strong>6. Join a Python community</strong></p><p>There are also global networks that host meetups and code nights all over the world. There are also many meetup groups focused on putting on technical talks, tutorials and events — check out <a href="https://www.meetup.com/">Meetup</a> or <a href="http://eventbrite.com/">Eventbrite</a> for events in your local area. It’s also worth considering online communities and groups with Slack channels, Telegram groups or virtual meetups where you can join to learn, share and network.</p><h3><strong>Installing your Python environment</strong></h3><p>You’ve read this far and have a number of resources to get you started, next, let’s get Python set up on your machine!</p><p>There are several different options when installing Python depending on which OS you are using and how you’d like to get set up. For new programmers, I’d recommend installing <a href="https://docs.anaconda.com/anaconda/install/">Anaconda</a> which is quick to get started and available for Windows, MacOS and Linux.</p><h4><strong>Python 2 or Python 3?</strong></h4><p>Support for Python 2 was stopped on January 1st 2020. You may still find software written using Python 2 but I’d recommend installing/upgrading to Python 3 if possible!</p><h4><strong>What is Anaconda?</strong></h4><p>Anaconda is an open-source distribution of Python and R. This means that it installs all the necessary software and packages that you need to get started. It includes:</p><ul><li>the <strong>Python</strong> and <strong>R</strong> programming languages</li><li>pre-installed python <strong>packages</strong></li><li><strong>conda</strong>, a python package manager which enables you to easily install and update python packages. You may also see pip mentioned, conda is an alternative to pip.</li><li><strong>Spyder</strong> is an Integrated Development Environment (or IDE, for short), which includes a text editor — think Microsoft Word but for writing code — in addition to tools for testing, debugging and inspecting your program and many features to making programming easier, including autocomplete!</li><li><em>(Optional but recommended)</em><strong> PyCharm</strong> is an another IDE and you will be prompted on installation whether you’d like to install it alongside Anaconda. I’d recommend doing so! I much prefer PyCharm over Spyder, finding it easier to navigate and get started with.</li><li><strong>Jupyter Lab/Jupyter Notebooks</strong> also can be installed through the Anaconda Navigator. These allow you to write code alongside text or visualisations and can be useful when presenting projects or going through tutorials.</li></ul><p>If you already have a preferred IDE that is not included above, such as Sublime or Visual Studio Code, check out the Anaconda <a href="https://docs.anaconda.com/anaconda/user-guide/getting-started/#links-to-ide-documentation">documentation</a> to find out how to select Anaconda Python as your python interpreter within the IDE.</p><h4>Python within your browser</h4><p>You can also access Python within your browser by using <a href="https://trinket.io/features/python3">Trinket</a> where you can also set up an account if you want to save your code.</p><h4>Other ways to install Python</h4><p>If you’d prefer not to use Anaconda, you can download and install Python from the <a href="http://python.org/">Python Software Foundation</a>. <br>If you’re using Linux or MacOS, you may already have Python pre-installed but this may not be Python 3. For further installation options, follow the instructions on <a href="https://realpython.com/installing-python/">RealPython.com</a>.</p><h3><strong>What’s next?</strong></h3><p>So you’ve installed python, covered the basics and are feeling ready to get started with a project!</p><p>Here is a list of possible projects and challenges to give you some inspiration:</p><p><strong>1. CodeWars</strong></p><p><a href="https://www.codewars.com/collections/basic-python">CodeWars</a> has a number of coding katas, or challenges, where you can put your python skills to the test and compete to solve problems from beginner to incredibly advanced!</p><p><strong>2. Project Euler</strong></p><p>Feeling like a new challenge? Why not attempt the first 100 <a href="https://www.freecodecamp.org/news/projecteuler100-coding-challenge-competitive-programming/">Project Euler</a> problems using python. You can follow <a href="https://twitter.com/search?q=%23ProjectEuler100">#ProjectEuler100</a> on Twitter and join the community to solve the challenges! I started the challenge at the start of 2020 with the aim to complete all 100 by the end of the year… entering the 5th month of the year, I’m way behind target!</p><p><strong>3. Get started with a project</strong></p><p>Check out <a href="https://medium.com/">Medium</a> and <a href="http://dev.to/">DEV.to</a> for tutorials you can follow to get started on your first project, or if you are looking to get started with a Data Science challenge, check out the <a href="https://www.kaggle.com/c/titanic">Titanic Machine Learning</a> challenge on Kaggle.</p><p>Watch this space for my next articles where I will walk through a project, exploring datasets, creating visualisations and providing you with the skills and tools to continue your coding journey.</p><p>Thank you for reading! If you enjoyed my article then <a href="https://kaparker.substack.com/">subscribe</a> to my monthly newsletter where you can get my latest articles and top resources delivered right to your inbox!</p><p>You can follow me on <a href="https://medium.com/@_kaparker">Medium</a> for more articles, follow me on <a href="https://twitter.com/_kaparker">Twitter</a> or find out more about what I’m up to on my <a href="http://kaparker.com/">website</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=efb037b248e8" width="1" height="1" alt=""><hr><p><a href="https://medium.com/data-science/learn-to-code-learn-python-efb037b248e8">Learn to code. Learn Python.</a> was originally published in <a href="https://medium.com/data-science">TDS Archive</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Atomic Habits Summary: Build better habits in 4 minutes]]></title>
            <link>https://medium.com/@_kaparker/chapter-by-chapter-breakdown-atomic-habits-1ac24f5fadc?source=rss-219e4d5d0c99------2</link>
            <guid isPermaLink="false">https://medium.com/p/1ac24f5fadc</guid>
            <category><![CDATA[book-review]]></category>
            <category><![CDATA[habit-building]]></category>
            <category><![CDATA[productivity]]></category>
            <category><![CDATA[habits]]></category>
            <dc:creator><![CDATA[Kerry Parker]]></dc:creator>
            <pubDate>Fri, 20 Mar 2020 20:17:51 GMT</pubDate>
            <atom:updated>2020-05-27T22:18:41.347Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ZBRcRtvWhjaUwbGWRfFOCA.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@isaacmsmith?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Isaac Smith</a> on <a href="https://unsplash.com/s/photos/goals?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p>In 2020, my focus is on reading more non-fiction and whilst reading <a href="https://jamesclear.com/atomic-habits">Atomic Habits by James Clear</a>, I summarised each chapter with one sentence. By taking notes in this way I can easily digest and review the content and then come back to these again and again.</p><p>The book is incredibly well written with accompanying diagrams and examples to demonstrate important concepts and at the end of each chapter, James Clear summarises all the key points.</p><p>If you are looking to create new habits or break bad ones, check out the chapter by chapter breakdown below for a brief insight into the tools and techniques provided in the book.</p><h3><strong>The Fundamentals: Why Tiny Changes Make a Big Difference</strong></h3><p><strong>1. The Surprising Power of Atomic Habits<br></strong>Build a system of atomic habits by implementing regular routines that are small and easy to do to result in compound growth.</p><p><strong>2. How Your Habits Shape Your Identity (and Vice Versa)<br></strong>Shape your habits around who you want to become.</p><p><strong>3. How to Build Better Habits in 4 Simple Steps<br></strong>Your habits are shaped by the systems in your life and become automated when they take little energy and effort.<br>The Four laws of behaviour change: make it obvious, make it attractive, make it easy, make it satisfying.</p><h3><strong>The 1st Law: Make It Obvious</strong></h3><p><strong>4. The Man Who Didn’t Look Right<br></strong>Be aware of your habits as some we may do unconsciously, use the pointing and calling technique to consciously acknowledge behaviour.</p><p><strong>5. The Best Way to Start a New Habit<br></strong>Use implementation intention by setting a <em>clear time and place</em> for your habit and add on to an existing habit through habit stacking.</p><p><strong>6. Motivation is Overrated; Environment Often Matters More<br></strong>Habit cues are influenced by environments and context, make them <em>obvious</em> to trigger habits or build habits in a new environment.</p><p><strong>7. The Secret to Self-Control<br></strong>Self-control is a short term strategy; optimise your <em>environment</em> to make good habit cues obvious and bad habit cues invisible.</p><h3><strong>The 2nd Law: Make It Attractive</strong></h3><p><strong>8. How to Make a Habit Irresistible<br></strong>Temptation bundling pairs a habit you need to do with a habit you want to do to make it more attractive where the anticipation of reward is driven by dopamine.</p><p><strong>9. The Role of Family and Friends in Shaping Your Habits<br></strong>We imitate the habits of the close, the many and the powerful. Join a culture with your desired behaviour and a shared interest.</p><p><strong>10. How to Find and Fix the Casuses of Your Bad Habits<br></strong>Habits are associated with emotions, to quit a bad habit make it seem unattractive and to create a motivation ritual by doing something that evokes good feelings before a difficult habit.</p><h3><strong>The 3rd Law: Make It Easy</strong></h3><p><strong>11. Walk Slowly, but Never Backward<br></strong>Motion is useful, action will deliver an outcome and repetition makes an action more automated.</p><p><strong>12. The Law of Least Effort<br></strong>Redesign your life to create less friction to good behaviours and more friction to bad behaviours.</p><p><strong>13. How to Stop Procrastinating by Using the Two-Minute Rule<br></strong>Implement a habit that takes only 2 minutes and then over time build on it.</p><p><strong>14. How to Make Good Habits Inevitable and Bad Habits Impossible<br></strong>Future-proof your habits by using commitment devices to make bad habits difficult in the present and automating your desired habits.</p><h3><strong>The 4th Law: Make It Satisfying</strong></h3><p><strong>15. The Cardinal Rule of Behaviour Change<br></strong>If you enjoy a habit you will repeat it, link an immediate reward to the habit to initially incentivise the habit and over time it becomes your identity and the intrinsic rewards will sustain it.</p><p><strong>16. How to Stick with Good Habits Every Day<br></strong>“The first mistake is never the one that ruins you” — habit trackers can be used to measure progress and make the habit satisfying.</p><p><strong>17. How an Accountability Partner Can Change Everything<br></strong>Make a habit unsatisfying by using techniques such as an accountability partner and/or habit contracts with negative consequences for failing to put your habit into action.</p><h3><strong>Advanced Tactics: How to Go from Being Merely Good to Being Truly Great</strong></h3><p><strong>18. The Trulh About Talent (When Genes Matter and When They Don’t)<br></strong>Tailor your habits around your personality and use explore/exploit trade offs to find areas of strength.</p><p><strong>19. The Goldilocks Rule: How to Stay Motivated in Life and Work<br></strong>Work on tasks at the edge of your current ability, in this zone you can achieve a flow state and also learn to enjoy the task even when you’re bored of it.</p><p><strong>20. The Downside of Creating Good Habits<br></strong>It is important to reflect and review to prevent building mistakes into habits and to avoid holding tightly onto an identity to encourage long term growth.</p><h3><strong>Conclusion: The Secret to Results That Last</strong></h3><p>The four laws of behaviour change present a set of tools and strategies to build better systems and better habits.</p><blockquote>Small habits can compound to make remarkable changes.</blockquote><p>Thank you for reading! If you enjoyed my article then <a href="https://kaparker.substack.com/">subscribe</a> to my monthly newsletter where you can get my latest articles and top resources delivered right to your inbox!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1ac24f5fadc" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Build a Weekly Planning Dashboard in Notion]]></title>
            <link>https://medium.com/swlh/build-a-weekly-planning-dashboard-in-notion-adbea8b98d8d?source=rss-219e4d5d0c99------2</link>
            <guid isPermaLink="false">https://medium.com/p/adbea8b98d8d</guid>
            <category><![CDATA[productivity]]></category>
            <category><![CDATA[notion]]></category>
            <dc:creator><![CDATA[Kerry Parker]]></dc:creator>
            <pubDate>Wed, 29 Jan 2020 22:22:15 GMT</pubDate>
            <atom:updated>2020-01-30T14:34:04.677Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zXyhrRJnlTHfY4CAa1lCBQ.png" /></figure><p>Over the past few months, I’ve started to use <a href="https://www.notion.so/">Notion</a> for my digital organisation. Whilst I like to think that I’m quite organised and tidy, I must admit my digital organisation is <strong>not</strong> up to scratch. On discovering Notion I fully immersed myself in tutorials, articles and using different templates to find a set up that works for me. Since October I’ve been using this tool on a daily basis to monitor and track my tasks, projects, fitness as well as to save documents and articles.</p><p>One of the key reasons for using Notion is the amount of flexibility it offers. Used along with web clipping tools and expert tips from people such as <a href="https://mariepoulin.com/">Marie Poulin</a> and <a href="https://groovywink.com/">Maria Aldrey</a>, it is possible to integrate your digital resources all in one place instead of across several apps.</p><p>Getting started, I followed all of Marie Poulin’s videos and templates but have now established a workspace that works for me. I’d definitely recommend checking out <a href="https://www.crowdcast.io/notionhq">Notion Office Hours</a>, <a href="https://www.youtube.com/channel/UCKvnOhqTeEgdNt1aJB5mVng">Marie Poulin’s YouTube channel</a>, <a href="https://groovywink.com/">Maria Aldrey’s GroovyWink</a> as well as the <a href="https://praxis.fortelabs.co/the-p-a-r-a-method-a-universal-system-for-organizing-digital-information-75a9da8bfb37/">PARA method</a> from Tiago Forte as a digital organisation system.</p><p>In this tutorial I’d like to share with you how I set up my work dashboard to track daily tasks, weekly progress and meetings and I hope you can make use of the template and integrate some of the tips into your own workspaces!</p><h3><strong>Basic Work Dashboard (with Template)</strong></h3><h4>1. Getting Started with Notion</h4><p>Once you sign up for a free account at <a href="https://www.notion.so/">https://www.notion.so/</a>, create a new workspace with <strong>Add a Page</strong>.<br>Give your new workspace a name and we’re ready to go!</p><h4>2. Setting up the template</h4><p>The dashboard is made of several elements</p><ul><li>Daily Planning database</li><li>Quick Access section</li><li>Good Morning workflow</li><li>Weekly Focus section</li></ul><p>You can <a href="https://www.notion.so/kaparker/Build-a-weekly-planning-dashboard-in-Notion-ee1454057ffe4ea38f96378642790bf0">duplicate the template</a> and work straight from there or in the following steps we will go through how to create each section.</p><h4>3. Creating a Daily Planning Table</h4><p>Whilst in many of the resources linked above work from Task databases so that these can be shared with other members of a team (see <a href="https://www.notion.so/kaparker/Advanced-Build-a-weekly-planning-dashboard-in-Notion-443bff385bac42c8ade7ad119626fc1d">Advanced Dashboard</a>), I found that I like to see my meetings, tasks and weekly schedule from within one database. <br>I treat this table as time slots in a daily planner and create different views to see my daily or weekly schedule.</p><p><strong>3.1 Create a table</strong><br>Create a new page within your empty dashboard and select Database &gt; Table. This sets up a basic table for you, with a few fields already created. Give your table a name eg. Daily Planning, and add the following properties:</p><ul><li>Name</li><li>Date</li><li>Timeline</li><li>Description</li><li>Tags — configure options of Weekly Review, Task, Meeting, Recurring</li><li>Type — configure options specific to your tasks eg. Admin, Content, Coding</li><li>Day — configure options with the days of the week, as well as Weekly and Someday <br>💡<em>It is useful to index each item with a number to get the order to appear correctly in the kanban board, as shown later</em></li><li>Priority 1</li><li>Priority 2</li><li>Priority 3</li><li>Productivity — configure options of 1–5 stars</li><li>Status — configure options such as Not Started, On Hold, In Progress, Complete</li></ul><p>You might notice that there are two fields containing dates; date and timeline. For me, there are tasks I may be waiting on or may take several days to complete. To ensure that task appears in Today’s Tasks kanban board the date field needs to be the latest date and the timeline the duration that the task has been active for. This is still a work in progress and I’m open to ideas to make this easier!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/266/1*UVCn4_eRe0Ig1V1oQQTmfg.png" /></figure><p>Also there are some fields that are used exclusively for Weekly Reviews such as Priority and Productivity and have created a template for Weekly Reviews with preset values for some of the properties. You can create templates by clicking the arrow next to the blueNew button and selecting New Template. I also have set up templates for New Tasks and New Meetings again with some fields populated.</p><p><strong>3.2 Views</strong></p><p>At the moment our database looks like a table however, it is possible to add more views (by selecting Add new View) to help make organisation easier!</p><ul><li><strong>Default View:</strong> Table, as created</li><li><strong>Today Kanban</strong>: Kanban board* with Filter on Date is today and group by Status</li><li><strong>Weekly Kanban:</strong> Kanban sorted by Date descending and group by Day</li><li><strong>Weekly Reviews:</strong> Gallery with Filter on Tags contains Weekly Review and sorted by Date descending <br>You can also change the properties to be displayed on the cards to show only the fields you want to quickly see</li><li><strong>Calendar: </strong>Calendar by Date</li><li><strong>Not Complete:</strong> Table with Filter on Status not complete, Filter on tags does not contain Meeting, Filter on tags does not contain Weekly Review</li></ul><p>*Kanban refers to a style of project management where tasks are displayed in columns on a board</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*c1i8li9trApUE3zSKFC0zA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*IFPklACevXnL9YV7y-pPug.png" /><figcaption>Weekly Kanban (L) and Today Kanban (R) views</figcaption></figure><p><strong>3.3 Recurring tasks</strong></p><p>Notion currently doesn’t have the capability to handle recurring tasks. To deal with this in the table, I have addedRecurring as a tag and for these tasks specifically do not assign a date field. For the recurring task Update Tasks I have set a Day of Friday since this is a weekly recurring task. <br>For monthly tasks, you could also configure an option of 7 — Monthly as a Dayand change the date to the next day to perform the task once it has been completed each month to ensure it is added to your Today kanban.</p><p>I have been using this set up for around a month now and it is incredibly easy to maintain and I work mostly from within the Weekly kanban, unless I have a particularly busy day. It does rely on updating the tasks at the end of the week to remove the Day property but this can serve as a good reflection on your tasks for the week as you are filling in your Weekly review.</p><h4>4. Quick Access Bar</h4><p>There are some documents that I like to have easy access to and I’ve added these to the quick access bar on a different colour background. To create this box, you need to first create a toggle list in this case the list is: ✨✨✨</p><p>Within the list you can create some Template Buttons such as a New To-do or a New Meeting which creates a meeting notes document created from a Notion inbuilt template.</p><p>Finally you can create a title of My Documents and add some useful resources here.</p><figure><img alt="Change background colour of toggle section" src="https://cdn-images-1.medium.com/max/1020/1*-tzhmo63KvwR-CiLuxyxqg.png" /><figcaption>Selecting a background colour for a toggle section</figcaption></figure><p>Once this is all set up, select the three dots next to the start of the toggle and select Color and select aBackground Color of choice to make it stand out. Finally, remove the toggle arrow and your quick access bar is ready to go!</p><h4>5. Good Morning Toggle</h4><p>Again using a Toggle List you can create a drop down to-do list of tasks to check off Daily or Weekly, you can set this up with your own motivational quotes and checklists.</p><figure><img alt="Good Morning checklist" src="https://cdn-images-1.medium.com/max/305/1*W8ii_m9_6v779bFFaaGNfA.png" /><figcaption>Good Morning checklist</figcaption></figure><p>To get the checklist to align with the Quick Access bar, you can highlight the section and drag the block to the end of the row where two columns will then be created. I have also added a blank line to create a 3rd column where I have adjusted the spacing.</p><h4>6. Weekly Focus</h4><p>Finally, we create a Weekly Focus block.</p><figure><img alt="Weekly Focus block" src="https://cdn-images-1.medium.com/max/1024/1*vq4Ye4UrT29ncdrvyCrGDA.png" /><figcaption>Weekly Focus block</figcaption></figure><p>Firstly create the heading of Weekly Focus and underneath this create another toggle list, this time without a title. <br>Inside the toggle create a placeholder text such as Focus 1 and change the background colour. Duplicate this toggle list depending on how many focus points you want each week. <br>Again drag each toggle to the end of the row with the Weekly Focus title and add an extra blank line for an extra column at the end, if desired. Adjust the column widths to fit your page.</p><p>You can now get started with your own weekly dashboard! If you would prefer to use the template for this dashboard you can access that <a href="https://www.notion.so/kaparker/Build-a-weekly-planning-dashboard-in-Notion-ee1454057ffe4ea38f96378642790bf0">here</a> and duplicate into your own workspace.</p><p>I also have a more <a href="https://www.notion.so/kaparker/Advanced-Build-a-weekly-planning-dashboard-in-Notion-443bff385bac42c8ade7ad119626fc1d">advanced template</a> you can try which contains further databases such as Tasks, OKRs &amp; Projects.</p><p>Thank you for reading! If you enjoyed my article then <a href="https://kaparker.substack.com/">subscribe</a> to my monthly newsletter where you can get my latest articles and top resources delivered right to your inbox!</p><p>You can follow me on <a href="https://medium.com/@_kaparker">Medium</a> for more articles, follow me on <a href="https://twitter.com/_kaparker">Twitter</a> or find out more about what I’m up to on my <a href="http://kaparker.com/">website</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=adbea8b98d8d" width="1" height="1" alt=""><hr><p><a href="https://medium.com/swlh/build-a-weekly-planning-dashboard-in-notion-adbea8b98d8d">Build a Weekly Planning Dashboard in Notion</a> was originally published in <a href="https://medium.com/swlh">The Startup</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[TechNomads November meetup: Data Science]]></title>
            <link>https://medium.com/@_kaparker/technomads-data-science-7bd1aef21d45?source=rss-219e4d5d0c99------2</link>
            <guid isPermaLink="false">https://medium.com/p/7bd1aef21d45</guid>
            <category><![CDATA[data-science]]></category>
            <dc:creator><![CDATA[Kerry Parker]]></dc:creator>
            <pubDate>Mon, 09 Dec 2019 21:34:33 GMT</pubDate>
            <atom:updated>2019-12-09T21:41:40.748Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*MWr_GIQcnTDpSxFGXBLQxw.jpeg" /><figcaption>Image by <a href="https://pixabay.com/photos/?utm_source=link-attribution&amp;amp;utm_medium=referral&amp;amp;utm_campaign=image&amp;amp;utm_content=945444">Free-Photos</a> from <a href="https://pixabay.com/?utm_source=link-attribution&amp;amp;utm_medium=referral&amp;amp;utm_campaign=image&amp;amp;utm_content=945444">Pixabay</a></figcaption></figure><p><em>This post can also be found at </em><a href="https://kaparker.com/posts/technomads-datascience"><em>https://kaparker.com/posts/technomads-datascience</em></a></p><p>On Monday 25th November we held our monthly <a href="https://www.eventbrite.co.uk/e/tech-nomads-november-meetup-data-science-tickets-79135034017">TechNomads meetup where we focussed on Data Science</a>. Joseph Allen &amp; John Carney, Data Scientists based in Manchester, visited us at Liverpool Science Park to give an introduction to Data Science followed by a Q&amp;A session. They provided fascinating insight drawn from their experience and shared plenty of tips and advice with us. The audience was made up of a mix of people working with data, including researchers, students and analysts as well as developers, aspiring data scientists and people working on side projects.</p><h3><strong>Why do we need Data Science?</strong></h3><p>The field of Data Science is broad and constantly evolving. As the hype for data science has grown, as has the confusion of what the role of a Data Scientist involves. As experienced Data Scientists and now running a Data Consultancy <a href="https://www.pdfta.com/">PDFTA</a>, Joseph &amp; John simplified the definition of Data Science to be: converting data into value.</p><p>One point that was highlighted that there is often over-emphasis on using Machine Learning, when a project may be quicker, simpler and cleaner to use other methods.</p><blockquote>Data Science: converting data into value.</blockquote><p>There are however lots of quick ways to get started with Machine Learning projects, including:</p><p>- Image classification: is the image a cat or a dog?</p><p>- Forecasting: using a python package fbprophet</p><p>- Chatbots: integrating these into social media pages</p><h3><strong>How do we apply Data Science?</strong></h3><p>A revised version of the Data Science pyramid was introduced with the foundation of Data Science relying on good Software Engineering practices and how this is something we should all endeavour to improve.</p><blockquote>Data Science is 95% exploring data, 5% Machine Learning</blockquote><p>There are also many different paths into data science and Joe has summarised these in an article on <a href="https://medium.com/@JosephAllen1234/the-data-scientists-ive-met-c88478d3632b">Medium</a>.</p><p><a href="https://medium.com/@JosephAllen1234/the-data-scientists-ive-met-c88478d3632b">The Data Scientists i’ve met.</a></p><p>Something I took away from the talk was that Data Science can still use the concept of a Minimum Viable Product. It’s better to apply a simple model and deploy to get feedback than to risk months for no value.</p><h3><strong>What is Data Science?</strong></h3><p>Joseph and John then went through some of the key terms that you hear in Data Science such as Model, Regression, Classification and gave examples of where these can be used — check out their <a href="https://tinyurl.com/pdfta-data-science">slides</a> for details!</p><h3><strong>Case Studies</strong></h3><p>Some example projects were presented which John and Joseph have worked on and a few of which are a good first Data Science project such as sentiment analysis of WhatsApp messages!</p><p>They then introduced Case Studies in Data Science including how Recommendation Engines can be used to search for similar and interesting products for the user. For this, UX teams, particularly in e-commerce, can provide insightful feedback to get example data of how users respond to this. Either Content-based or Behaviour-based recommendation systems can be used and python packages such as prod2vec which is based around word2vec can be used.</p><h3><strong>Q&amp;A</strong></h3><p>After a short break, the audience asked John &amp; Joseph questions with some fascinating questions about:</p><ul><li>How often should I model be updated?</li><li>The ethics and bias of data</li><li>Where to get started as a Data Scientist?</li></ul><p>Overall, it was a brilliant evening, thanks to John and Joseph for coming along to TechNomads and sharing your expertise and thanks everyone for coming! I certainly learned a lot and if you couldn’t attend, be sure to check out the slides!</p><p>You can find <a href="https://twitter.com/jaspajjr">John</a>, <a href="https://twitter.com/JosephAllen1234">Joseph</a> and <a href="https://twitter.com/PDFTA_data">PDFTA</a> on Twitter. They also co-organise <a href="https://twitter.com/pydatamcr">PyDataMCR</a> where they have monthly meetups as well as monthly Code Nights to bring your questions and help others with theirs!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*xX99jksDJcSOTSSes2sroQ.png" /><figcaption>TechNomads November meetup</figcaption></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7bd1aef21d45" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Creating word clouds with python]]></title>
            <link>https://medium.com/data-science/creating-word-clouds-with-python-f2077c8de5cc?source=rss-219e4d5d0c99------2</link>
            <guid isPermaLink="false">https://medium.com/p/f2077c8de5cc</guid>
            <category><![CDATA[towards-data-science]]></category>
            <category><![CDATA[data-science]]></category>
            <category><![CDATA[python]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[machine-learning]]></category>
            <dc:creator><![CDATA[Kerry Parker]]></dc:creator>
            <pubDate>Wed, 31 Jul 2019 22:27:14 GMT</pubDate>
            <atom:updated>2020-01-27T22:06:04.966Z</atom:updated>
            <cc:license>http://creativecommons.org/licenses/by/4.0/</cc:license>
            <content:encoded><![CDATA[<figure><img alt="Game of Thrones logo" src="https://cdn-images-1.medium.com/max/1024/1*bMt1xhiVw9HEyFy-6ODNSQ.jpeg" /><figcaption>Image from <a href="https://culturacolectiva.com/movies/game-thrones-season-8-opening-map-astrolabe">culturacolectiva</a></figcaption></figure><p>During a recent NLP project, I came across an <a href="http://keyonvafa.com/inauguration-wordclouds/">article where word clouds were created in the shape of US Presidents using words from their inauguration speeches</a>. Whilst I had used word clouds to visualise the most frequent words in a document, I’d not considered using this with a mask to represent the topic or subject. This got me thinking...</p><p>Several months ago, shortly before the final series of Game Of Thrones and after having just rewatched seasons 1–7, I was eagerly awaiting the finale — so much so that I went looking for any Game Of Thrones data I could find online to create a predictor for who would survive the chaos of season 8 and what would happen within the 7 Kingdoms. Unfortunately, I was out of time but I did find plenty of <a href="https://www.reddit.com/r/datasets/comments/769nhw/game_of_thrones_datasets_xpost_from_rfreefolk/">data</a> and visualisations that people had put together. When I came across the inaugural word clouds I wondered if I could use this Game Of Thrones data, particularly scripts, with image masks of the characters to create some pretty cool visualisations. In this article, as <a href="https://github.com/kaparker/gameofthrones-wordclouds/blob/master/WordClouds_CodeUPXTechNomads_240719.pdf">presented</a> at a recent tech meet-up, I will walk through my steps to create Game Of Thrones word clouds using python.</p><h3>Getting Started</h3><p>Following a similar method to the inaugural word cloud article, there are several steps involved when dealing with text based data. The steps are:</p><ol><li>Finding relevant data</li><li>Cleaning data</li><li>Creating a mask from the image</li><li>Generating word clouds</li></ol><p>Since I will be using python in this tutorial, there are many libraries to help with the above steps, also <a href="https://towardsdatascience.com/a-practitioners-guide-to-natural-language-processing-part-i-processing-understanding-text-9f4abfd13e72">Dipanjan Sarkar’s guide to Natural Language Processing</a> provides a comprehensive introduction to techniques in text analytics if you are looking for further reading around the topic.</p><p>Before getting started with the first step, I defined the goal of the project to ensure that no important steps were missed and to have a clear vision of the target.</p><p><strong>Project goal:</strong> To create word clouds for Game Of Thrones characters masked with an image.</p><h3>1. Finding relevant data</h3><p>There is plenty of Game Of Thrones data available online — <a href="https://github.com/">GitHub</a> and <a href="https://kaggle.com/">Kaggle</a> are where I usually first search for datasets — and I quickly found a dataset containing the <a href="https://github.com/shekharkoirala/Game_of_Thrones/tree/master/Data">scripts</a>.</p><p>To achieve the project goal, the lines for each character need to be stated —the first question was: are the character lines are available?</p><figure><img alt="Snippet of Game of Thrones script" src="https://cdn-images-1.medium.com/max/492/1*mIC-irxn5-rFaD9qwsQZ2w.png" /><figcaption>Snippet of Game of Thrones script</figcaption></figure><p>Looking at a snippet from the first episode, the character data is available! However, when exploring further episodes and season, the format for character names varies.</p><p>In the case above only the character’s first name is used and this is all in uppercase, whilst in other seasons the characters full name is used with letter case. Stage directions can also be included within the character name.</p><p>Th search for all lines by the character name, a regular expressions with the character names can be used:</p><pre>re.findall(r&#39;(^&#39;+name+r&#39;.*:.*)&#39;, line, re.IGNORECASE)</pre><p>This expression searches for the start of a line (^), followed by the character name which we input as a variable, followed by any text (.*), then a colon to indicate that this is a character’s line (:) and followed by any text (.*). By containing this regular expression within brackets, the full line is returned. Finally, the case is ignored, so the character name can be upper/lower/letter case.</p><p>Using the function below will return all the lines for a character:</p><pre># final_data taken from:  <br># <a href="https://github.com/shekharkoirala/Game_of_Thrones">https://github.com/shekharkoirala/Game_of_Thrones</a></pre><pre># get data for characters<br>def get_char_lines(char):    <br>    output = []          <br>    print(&#39;Getting lines for&#39;, char)        <br><br>    with open(&#39;final_data.txt&#39;, &#39;r&#39;) as f:<br>        for line in f:<br>            if re.findall(r&#39;(^&#39;+char+r&#39;.*:.*)&#39;,line,re.IGNORECASE):<br>                output.append(line)<br>    f.close()<br>    print(char, &#39;has &#39;, len(output), &#39;lines&#39;)</pre><pre>return output</pre><pre># get lines using<br>get_char_lines(&#39;arya&#39;)</pre><h3>2. Cleaning data</h3><p>Now that we have the lines for a character, these need to be cleaned.</p><p>The following techniques are used for cleaning the lines, these same techniques are also outlined in detail in the <a href="https://towardsdatascience.com/a-practitioners-guide-to-natural-language-processing-part-i-processing-understanding-text-9f4abfd13e72">NLP Guide</a> referenced above. Again regular expressions are useful here to replace or remove characters:</p><ul><li>Remove line info eg. JON:</li></ul><pre>re.sub(r&#39;.*:&#39;, &#39;&#39;, text)</pre><ul><li>Remove brackets — remove any stage directions from the character lines</li></ul><pre>re.sub(&#39;[\(\[].*?[\)\]]&#39;, &#39; &#39;, text)</pre><ul><li>Remove accented characters and normalise using the unicodedata library</li></ul><pre>unicodedata.normalize(&#39;NFKD&#39;, text).encode(&#39;ascii&#39;, &#39;ignore&#39;).decode(&#39;utf-8&#39;, &#39;ignore&#39;)</pre><ul><li>Expand any contracted words eg. don’t → do not<br>There is a python library for this, copy contractions.py to your working directory from:<br><a href="https://github.com/dipanjanS/practical-machine-learning-with-python/blob/master/bonus%20content/nlp%20proven%20approach/contractions.py">https://github.com/dipanjanS/practical-machine-learning-with-python/</a></li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e4d19def3d290f242b35193d8aa65dc5/href">https://medium.com/media/e4d19def3d290f242b35193d8aa65dc5/href</a></iframe><ul><li>(Optional): apply lemmatisation where a word is stemmed to a root word that is in the dictionary, eg. is, are → be <br>Not currently using lemmatisation as it doesn’t handle some words well eg. Stannis → Stanni</li><li>Convert all text to lowercase</li></ul><pre>text.lower()</pre><ul><li>Remove special characters (*,.!?) with the option to remove numbers too — default is set to false</li></ul><pre>pattern = r&#39;[^a-zA-Z0-9\s]&#39; if not remove_digits else r&#39;[^a-zA-Z\s]&#39;    re.sub(pattern, &#39;&#39;, text)</pre><ul><li>Remove stop words, using stop words from the nltk library by first tokenising the text, splitting the string into a list of substrings and then removing any stop words</li></ul><pre>stopword_list = stopwords.words(&#39;english&#39;)    <br>tokens = nltk.word_tokenize(text)    <br>tokens = [token.strip() for token in tokens]    <br>&#39; &#39;.join([token for token in tokens if token not in stopword_list])</pre><p>These cleaning techniques have been based on several different sources and there are many variations of these steps as well as additional cleaning techniques that can be used. These initial cleaning steps have been used in this <a href="https://github.com/kaparker/gameofthrones-wordclouds/blob/master/gotwordcloud.py">project</a>.</p><h3>3. Create a mask from image</h3><p>Based on the inauguration word clouds, the PIL library is used to open the image, a numpy array is created from the image to create a mask.</p><pre>char_mask = np.array(Image.open(&quot;images/image.jpeg&quot;))    image_colors = ImageColorGenerator(char_mask)</pre><p>Optionally the numpy array can be used with wordcloud.ImageColorGenerator to then recolor the word cloud to represent the colours from the image, or otherwise. This will be covered in the next section.</p><p>After initially testing an image as a word cloud mask, the background in the image created too much noise that the shape of the character was not well defined. To avoid this, it can be useful to remove the image background and replace with a white background instead.</p><figure><img alt="Remove background from image and replace with white background" src="https://cdn-images-1.medium.com/max/235/1*yKQxyCc5v8ifMOz_KsmfKA.png" /><figcaption>Remove background from image and replace with white background</figcaption></figure><h3>4. Generate word clouds</h3><p>The final step is to create the word cloud using the generate() function.</p><pre>wc = WordCloud(background_color=&quot;white&quot;, max_words=200, width=400, height=400, mask=char_mask, random_state=1).generate(text)</pre><pre># to recolour the image<br>plt.imshow(wc.recolor(color_func=image_colors))</pre><p>The word cloud will be masked with an image and the size of text will be based on word frequency.</p><p>The parameters of the word cloud can be adjusted — try increasingmax_words to see some of the less frequent words included, note that this should be less than the number of unique words within your document.</p><p>As mentioned in the previous section, the recolor step is optional and here is used to represent the original image colours.</p><h3>Game of Thrones Word clouds</h3><p>Using the steps above with images of Game Of Thrones characters, the generated words clouds are presented below:</p><h4><strong>Arya</strong></h4><figure><img alt="Arya word cloud" src="https://cdn-images-1.medium.com/max/1024/1*hmp_uwkdfW2EO-mLOosf5Q.png" /><figcaption>Arya word cloud</figcaption></figure><h4><strong>Jon Snow</strong></h4><figure><img alt="Jon Snow word cloud" src="https://cdn-images-1.medium.com/max/1024/1*liuB_vfT8yHGeMNnEFOr2A.png" /><figcaption>Jon Snow word cloud</figcaption></figure><h4><strong>Daenerys</strong></h4><figure><img alt="Daenerys word cloud" src="https://cdn-images-1.medium.com/max/1024/1*jQefoqmu6zpswXLDoWo3Qg.png" /><figcaption>Daenerys word cloud</figcaption></figure><h4><strong>Ser Davos</strong></h4><figure><img alt="Ser Davos word cloud" src="https://cdn-images-1.medium.com/max/1024/1*-NjYPnJMwLii4aBPwVO4Qg.png" /><figcaption>Ser Davos word cloud</figcaption></figure><p>This has also been extended to generate word clouds based on Houses:</p><h4>House Lannister</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*02ESF7ucOaIEfRSiSIvn3g.png" /><figcaption>Lannister word cloud</figcaption></figure><h4>House Stark</h4><figure><img alt="Stark word cloud" src="https://cdn-images-1.medium.com/max/1024/1*L5PxjLDHy0Gb9gSXp1-2Ug.png" /><figcaption>Stark word cloud</figcaption></figure><p>With these word clouds the initial project goal has been reached!</p><h3>Improvements</h3><p>There are several ways in which these word clouds can be improved.</p><ul><li><strong>Common words:</strong> There are recurring words that are common in all the characters scripts. Currently the word clouds are generated based on the word frequency however, an alternative would be TFIDF which weights the terms based on the term frequency in the document and the frequency with respect to the corpus. Alternatively, a custom stop word list could be generated to remove other frequent words</li><li><strong>Lemmatisation/stemming</strong>: Lemmatisation has not been used in the examples above as some words unique to Game of Thrones were shortened when testing (Stannis → Stanni), however this does mean that words which come from the same root word are not linked and occur several times in the word cloud eg. say, said. An alternative lemmatisation method or stemming technique could be used.</li><li><strong>Text cleaning:</strong> There are further cleaning or data preparation steps that could be used</li><li><strong>Word cloud features:</strong> I have tested with different word colours, background colours and word cloud parameters, the grey colour and black background works in this case but some of the parameters could be further optimised</li><li><strong>Further text analysis:</strong> many insights can be drawn from this dataset. Much more scope for analysis!</li></ul><h3>Extension — Stranger Things</h3><p>Looking into further shows, I eventually found <a href="https://www.springfieldspringfield.co.uk/episode_scripts.php?tv-show=stranger-things-2016">Stranger Things script</a> — although they are missing character lines the data can still be used to <a href="https://github.com/kaparker/stranger-things">generate word clouds</a>….</p><figure><img alt="Stranger Things word cloud" src="https://cdn-images-1.medium.com/max/1024/1*5BhesvlDaBTXKqq37k3qhQ.png" /><figcaption>Stranger Things word cloud</figcaption></figure><h3>Summary</h3><p>In this article I have walked through the basic steps to generate word clouds which are masked with an image.</p><p>This is just the start of my experimenting with word clouds! There is a huge scope for further development and improvement in the project, I hope you can follow the steps to create your own projects with word clouds!\</p><p>Thank you for reading! If you enjoyed my article then <a href="https://kaparker.substack.com/">subscribe</a> to my monthly newsletter where you can get my latest articles and top resources delivered right to your inbox!</p><p>You can follow me on <a href="https://medium.com/@_kaparker">Medium</a> for more articles, follow me on <a href="https://twitter.com/_kaparker">Twitter</a> or find out more about what I’m up to on my <a href="http://kaparker.com/">website</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f2077c8de5cc" width="1" height="1" alt=""><hr><p><a href="https://medium.com/data-science/creating-word-clouds-with-python-f2077c8de5cc">Creating word clouds with python</a> was originally published in <a href="https://medium.com/data-science">TDS Archive</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Data Science Skills: Web scraping javascript using python]]></title>
            <link>https://medium.com/data-science/data-science-skills-web-scraping-javascript-using-python-97a29738353f?source=rss-219e4d5d0c99------2</link>
            <guid isPermaLink="false">https://medium.com/p/97a29738353f</guid>
            <category><![CDATA[web-scraping]]></category>
            <category><![CDATA[data-science]]></category>
            <category><![CDATA[python]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[web-development]]></category>
            <dc:creator><![CDATA[Kerry Parker]]></dc:creator>
            <pubDate>Thu, 08 Nov 2018 21:57:13 GMT</pubDate>
            <atom:updated>2020-06-25T19:30:25.682Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/1*8OO_rM6eZgNdDaNtzTEC3g.png" /></figure><p>There are different ways of scraping web pages using python. In my previous article, I gave an introduction to web scraping by using the libraries:requests and BeautifulSoup. However, many web pages are dynamic and use JavaScript to load their content. These websites often require a different approach to gather the data.</p><p><a href="https://towardsdatascience.com/data-science-skills-web-scraping-using-python-d1a85ef607ed">Data Science Skills: Web scraping using python</a></p><p>In this tutorial, I will present several different ways of gathering the content of a webpage that contains Javascript. The techniques used will be the following:</p><ol><li>Using selenium with Firefox web driver</li><li>Using a headless browser with phantomJS</li><li>Making an API call using a REST client or python requests library</li></ol><h4>TL;DR For examples of scraping javascript web pages in python you can find the complete code as covered in this tutorial over on <a href="https://github.com/kaparker/tutorials/blob/master/pythonscraper/websitescrapefasttrack.py">GitHub</a>.</h4><p>Update November 7th 2019: Please note, the html structure of the webpage being scraped may be updated over time and this article initially reflected the structure at the time of publication in November 2018. The article has now been updated to run with the current webpage but in the future this may again change.</p><h3>First steps</h3><p>To start the tutorial, I first needed to find a website to scrape. Before proceeding with your web scraper, it is important to always check the Terms &amp; Conditions and the Privacy Policy on the website you plan to scrape to ensure that you are not breaking any of their terms of use.</p><h3>Motivation</h3><p>When trying to find a suitable website to demonstrate, many of the examples I first looked at explicitly stated that web crawlers were prohibited. It wasn’t until reading an article about <a href="https://www.bbc.co.uk/news/health-45565364">sugar content in yogurt</a> and wondering where I could find the latest nutritional information inspired another train of thought where I could find a suitable website; online supermarkets.</p><p>Online retailers often have dynamic web pages that load content using javascript so the aim of this tutorial is to scrape the nutritional information of yogurts from the web page of an online supermarket.</p><h3>Setting up your environment</h3><p>Since we will be using some new python libraries to access the content of the web pages and also to handle the data, these libraries will need to be installed using your usual python package manager pip. If you don’t already have beautifulsoup then you will need to install this here too.</p><pre>pip install selenium<br>pip install pandas</pre><p>To use selenium as a web driver, there are a few additional requirements:</p><h4>Firefox</h4><p>I will be using Firefox as the browser for my web driver so this means you will either need to i<a href="https://www.mozilla.org/en-GB/firefox/new/">nstall Firefox</a> to follow this tutorial or alternatively you can use <a href="http://chromedriver.chromium.org/getting-started">Chromium</a> with Chrome.</p><h4>Geckodriver</h4><p>To use the web driver we need to install a web browser engine, geckodriver. You will need to download <a href="https://github.com/mozilla/geckodriver/releases">geckodriver</a> for your OS, extract the file and set the executable path location.</p><p>You can do this in several ways:<br>(i) move geckodriver to a directory of your choice and define this the executable path in your python code (see later example),</p><p>(ii) move geckodriver to a directory which is already a set as a directory where executable files are located, this is known as your environmental variable path. <br>You can find out which directories are in your $PATH by the following:</p><p><strong>Windows<br></strong>Go to:</p><p><em>Control Panel &gt; Environmental Variables &gt; System Variables &gt; Path</em></p><p><strong>Mac OSX / Linux</strong><br>In your terminal use the command:</p><pre>echo $PATH</pre><p>(iii) add geckodriver location to your PATH environment variables</p><p><strong>Windows<br></strong>Go to:</p><p><em>Control Panel &gt; Environmental Variables &gt; System Variables &gt; Path &gt; Edit<br></em>Add the directory containing geckodriver to this list and save</p><p><strong>Mac OSX / Linux<br></strong>Add a line to your .bash_profile (Mac OSX) or .bash_rc (Linux)</p><pre># add geckodriver to your PATH<br>export PATH=&quot;$PATH:/path/to/your/directory&quot;</pre><p>Restart your terminal and use the command from (ii) to check that your new path has been added.</p><h4>PhantomJS</h4><p>Similar to the steps for geckodriver, we also need to download <a href="http://phantomjs.org/download.html">PhantomJS</a>. Once downloaded, unzip the file and move to a directory of choice or add to your path executable, following the same instructions as above.</p><h4>REST Client</h4><p>In the final part of this blog, we will make a request to an API using a REST client. I will be using <a href="https://insomnia.rest/">Insomnia</a> but feel free to use whichever client you prefer!</p><h3>Scraping the web page using BeautifulSoup</h3><p>Following the standard steps outlined in my <a href="https://medium.com/@_kaparker/data-science-skills-web-scraping-using-python-d1a85ef607ed">introductory tutorial into web scraping</a>, I have inspected the <a href="https://groceries.asda.com/search/yogurt">webpage</a> and want to extract the repeated HTML element:</p><pre>&lt;div data-cid=&quot;XXXX&quot; class=&quot;listing category_templates clearfix productListing &quot;&gt;...&lt;/div&gt;</pre><p>As a first step, you might try using BeautifulSoup to extract this information using the following script.</p><pre># import libraries<br>import urllib.request<br>from bs4 import BeautifulSoup</pre><pre># specify the url<br>urlpage = &#39;<a href="https://groceries.asda.com/search/yoghurt&#39;">https://groceries.asda.com/search/yogurt&#39;</a> <br>print(urlpage)<br># query the website and return the html to the variable &#39;page&#39;<br>page = urllib.request.urlopen(urlpage)<br># parse the html using beautiful soup and store in variable &#39;soup&#39;<br>soup = BeautifulSoup(page, &#39;html.parser&#39;)<br># find product items<br># at time of publication, Nov 2018:<br># results = soup.find_all(&#39;div&#39;, attrs={&#39;class&#39;: &#39;listing category_templates clearfix productListing&#39;})</pre><pre># updated Nov 2019:<br>results = soup.find_all(&#39;div&#39;, attrs={&#39;class&#39;: &#39;co-product&#39;})<br>print(&#39;Number of results&#39;, len(results))</pre><p>Unexpectedly, when running the python script, the number of results returned is 0 even though I see many results on the web page!</p><pre><a href="https://groceries.asda.com/search/yoghurt">https://groceries.asda.com/search/yoghurt</a><br>BeautifulSoup - Number of results 0</pre><p>When further inspecting the page, there are many dynamic features on the web page which suggests that javascript is used to present these results. <br>By right-clicking and selecting View Page Source there are many &lt;script&gt; elements in use and searching for the element above containing the data we are interested in returns no matches.</p><p>The first approach to scrape this webpage is to use Selenium web driver to call the browser, search for the elements of interest and return the results.</p><h3>Scraping the web page using Selenium</h3><h4>1. Selenium with geckodriver</h4><p>Since we are unable to access the content of the web page using Beautiful Soup, we first need to set up a web driver in our python script.</p><pre># import libraries<br>import urllib.request<br>from bs4 import BeautifulSoup<br>from selenium import webdriver<br>import time<br>import pandas as pd</pre><pre># specify the url<br>urlpage = &#39;<a href="https://groceries.asda.com/search/yoghurt&#39;">https://groceries.asda.com/search/yogurt&#39;</a> <br>print(urlpage)<br># run firefox webdriver from executable path of your choice<br>driver = webdriver.Firefox(executable_path = &#39;your/directory/of/choice&#39;)</pre><p>As mentioned when installing geckodriver, if the executable file is not in an executable path, we are able to define the path in our python script. If it is in an executable path then the line above becomes:</p><pre># run firefox webdriver from executable path of your choice<br>driver = webdriver.Firefox()</pre><p>Once set up, we can now connect to the web page and find the elements of interest. When loading the webpage in a browser, results often take a while to load and also may not even load until we scroll down the page. <br>With this in mind, here we can add some javascript for the web driver to execute to perform such actions. Below is a simple example to get the page to scroll, there will be more efficient ways to do this, why not test your own javascript here and let me know in the comments what works best for you!</p><p>We also add a sleep time as another method to wait for the page to fully load.</p><pre># get web page<br>driver.get(urlpage)<br># execute script to scroll down the page<br>driver.execute_script(&quot;window.scrollTo(0, document.body.scrollHeight);var lenOfPage=document.body.scrollHeight;return lenOfPage;&quot;)<br># sleep for 30s<br>time.sleep(30)<br># driver.quit()</pre><p>If we run the script now (you can also uncommentdriver.quit() at the end to ensure the browser closes), as your python script runs Firefox will open the url specified and scroll down the page. Hopefully, you should many products load up before the script finishes running.</p><p>Next, we want to get the elements of interest. Previously, using Beautiful Soup we have tried to find all elements based on the tag and class attributes, however, in this example we will use a slightly different approach to access the product information. Instead, we can search for the elements by xpath, based on the XML structure or the css selector.</p><p>We can inspect the element of interest and within the toolbar, right-click on the highlighted element and <em>Copy &gt; Copy xpath (or Copy Selector)</em>. This is another interesting way to understand the structure of the html. In this case we will be using the xpath to find the elements, and we can then print the number of results that match:</p><pre># find elements by xpath</pre><pre># at time of publication, Nov 2018:<br># results = driver.find_elements_by_xpath(&quot;//*[<a href="http://twitter.com/id">@id</a>=&#39;componentsContainer&#39;]//*[contains(<a href="http://twitter.com/id">@id</a>,&#39;listingsContainer&#39;)]//*[<a href="http://twitter.com/class">@class</a>=&#39;product active&#39;]//*[<a href="http://twitter.com/class">@class</a>=&#39;title productTitle&#39;]&quot;)</pre><pre># updated Nov 2019:<br>results = driver.find_elements_by_xpath(&quot;//*[@class=&#39; co-product-list__main-cntr&#39;]//*[@class=&#39; co-item &#39;]//*[@class=&#39;co-product&#39;]//*[@class=&#39;co-item__title-container&#39;]//*[@class=&#39;co-product__title&#39;]&quot;)<br>print(&#39;Number of results&#39;, len(results))</pre><p>One of the main reasons for using the xpath rather than using the element as the results have a few elements where the stem of the id is listingsContainer with some additional words, so the contains function has been used to select all of the results but also to exclude any of the other div elements within the container such as for adverts.</p><pre>Firefox Webdriver - Number of results 38</pre><p>Now that we have some results from the page, we can loop over each result and save the data of interest. In this case, we can save the product name and link.</p><p><em>Note that there are actually more than 38 results on the web page. This number also may vary depending on how many results load when you connect to the page. All results can be gathered by either changing the javascript we execute as suggested above, alternatively other methods will be explored in the following sections.</em></p><pre># create empty array to store data<br>data = []<br># loop over results<br>for result in results:<br>    product_name = result.text<br>    link = result.find_element_by_tag_name(&#39;a&#39;)<br>    product_link = link.get_attribute(&quot;href&quot;)<br>    # append dict to array<br>    data.append({&quot;product&quot; : product_name, &quot;link&quot; : product_link})</pre><p>Outside of this loop, we can close the browser and as we imported the pandas library, we can make use of that by saving the data we have scraped to a dataframe. We can print the dataframe to view the content.</p><pre># close driver <br>driver.quit()<br># save to pandas dataframe<br>df = pd.DataFrame(data)<br>print(df)</pre><p>In this format, we can very simply write this data to a csv.</p><pre># write to csv<br>df.to_csv(&#39;asdaYogurtLink.csv&#39;)</pre><p>Using Selenium with geckodriver is a quick way to scrape the web pages that are using javascript but there are a few drawbacks. I have found that sometimes the page does not load (I’m sure that this could be more efficient by changing the javascript we execute as mentioned above, but I am new to JS so this might require some time), but also loading the browser and waiting for the page to load takes time.</p><p>Another option, we can use a headless browser. This should speed up the scraping as we don’t have to wait for the browser to load each time.</p><h4>2. Selenium with a headless browser</h4><p>When using PhantomJS as a headless browser instead of geckodriver, the only difference is how the web driver is loaded. This means that we can follow the method above but change the line that initialises the web driver which becomes:</p><pre># run phantomJS webdriver from executable path of your choice<br>driver = webdriver.PhantomJS(executable_path = &#39;your/directory/of/choice&#39;)</pre><p>Note here that Selenium support for PhantomJS has been depreciated and provides a warning.</p><p>It is also possible to use headless mode with geckodriver by using the headless option:</p><pre>from selenium import webdriver<br>from selenium.webdriver.firefox.options import Options</pre><pre>options = Options()<br>options.headless = True<br>driver = webdriver.Firefox(firefox_options=options, executable_path = &#39;your/directory/of/choice&#39;)</pre><p>By using the headless browser, we should see an improvement in time for the script to run since we aren’t opening a browser but not all results are scraped in a similar way to using firefox webdriver in normal mode.</p><h3>Making an API request</h3><p>The final approach we will discuss in this tutorial is making a request to an API. When inspecting the Network page XHR files, as a page loads this page displays the requests that are being made. Within this list is a /search request which calls an API endpoint to get the results that are presented on the page.</p><p>We are able to make the same request using either a REST client or with a few lines of python.</p><p>If we inspect the search file and look at the headers, the request url containing the keyword and other parameters that are needed to make the request. Below the general details are the response and request headers which we may need later.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/682/1*6shmO69CrKyId1WHMvEHTQ.png" /><figcaption>Inspect tool showing the search request headers</figcaption></figure><p>To get the response, we can take the request url and as a test enter this into the address bar of your browser. Since the parameters are added in the string we can also try to remove all but the keyword parameter to test whether any further parameters are required. In this case, the keyword query returns the results in the browser, so we can also perform the same request using a REST client or in python.</p><h4>Insomnia REST client</h4><p>Using insomnia we can enter the request url and send the request.</p><p>This returns a JSON response containing the data that we are looking for!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*OZ5iTBk3I97rZ1sZV0KMDw.png" /><figcaption>Preview of JSON response in Insomnia</figcaption></figure><p>This example is very straight forward with no headers or security tokens required. For other cases, the REST client allows you to enter any additional response parameters that you can get from the inspect tool when gathering the request details.</p><h4>Python request</h4><p>We can also make the same request from python using the urllib.request library in the same way that we connect to a web page before scraping.</p><p>The JSON response can be made more readable by adding a few parameters for indenting and sorting the keys so that we can now open the file and see the response data provided to the webpage when a search is made.</p><pre># import json library<br>import json</pre><pre># request url<br>urlreq = &#39;<a href="https://groceries.asda.com/api/items/search?keyword=yogurt&#39;">https://groceries.asda.com/api/items/search?keyword=yogurt&#39;</a></pre><pre># get response<br>response = urllib.request.urlopen(urlreq)</pre><pre># load as json<br>jresponse = json.load(response)</pre><pre># write to file as pretty print<br>with open(&#39;asdaresp.json&#39;, &#39;w&#39;) as outfile:<br>    json.dump(jresponse, outfile, sort_keys=True, indent=4)</pre><p>For now, we will keep all the data. My next tutorial will cover data structures and output in more detail so we can manipulate the JSON and find the relevant data.</p><h3>Summary</h3><p>This tutorial has outlined some of the methods we can use to scrape web pages that use javascript. These methods include:</p><h4>Using a web driver to scrape content</h4><ul><li>Using selenium web driver to connect to a web page either with Firefox web driver, PhantomJS, headless browser</li><li>Use the web driver to find the elements of interest</li><li>Loop over the results and saving variables of interest</li><li>Saving data to a dataframe</li><li>Writing to a csv file</li></ul><h4>Make a HTTP request</h4><ul><li>Inspect the web page to find HTTP request details</li><li>Make the GET request using either a browser, REST client, python</li></ul><p>Whilst the HTTP request method is quicker to implement in this tutorial and provides all the data we need from one request, this is not always the case. Not all websites will make their requests visible, additional security may be in place with expiring authentication tokens or the output data may require significant cleaning which would be more work than using a web driver with some javascript to enable loading all results and looping over all pages. This tutorial provides a few different alternatives you can try to make it possible to scrape javascript.</p><p>In my next tutorial we will explore data structures, manipulating data and writing to output files or databases.</p><p>Thank you for reading! If you enjoyed my article then <a href="https://kaparker.substack.com/">subscribe to my monthly newsletter</a> where you can get my latest articles and top resources delivered right to your inbox, or find out more about what I’m up to on my <a href="http://kaparker.com/">website</a>.</p><p>If you are new to python or want to improve, check out my article with a list of learning resources including courses in data science:</p><p><a href="https://towardsdatascience.com/learn-to-code-learn-python-efb037b248e8">Learn to code. Learn Python.</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=97a29738353f" width="1" height="1" alt=""><hr><p><a href="https://medium.com/data-science/data-science-skills-web-scraping-javascript-using-python-97a29738353f">Data Science Skills: Web scraping javascript using python</a> was originally published in <a href="https://medium.com/data-science">TDS Archive</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>