<?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[Hexacta Engineering - Medium]]></title>
        <description><![CDATA[Technical articles from Hexacta developers and designers - Medium]]></description>
        <link>https://engineering.hexacta.com?source=rss----a41470515491---4</link>
        <image>
            <url>https://cdn-images-1.medium.com/proxy/1*TGH72Nnw24QL3iV9IOm4VA.png</url>
            <title>Hexacta Engineering - Medium</title>
            <link>https://engineering.hexacta.com?source=rss----a41470515491---4</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Wed, 08 May 2019 14:37:33 GMT</lastBuildDate>
        <atom:link href="https://engineering.hexacta.com/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[Testing Pandas]]></title>
            <link>https://engineering.hexacta.com/testing-pandas-b65c0ea8a28e?source=rss----a41470515491---4</link>
            <guid isPermaLink="false">https://medium.com/p/b65c0ea8a28e</guid>
            <category><![CDATA[data-science]]></category>
            <category><![CDATA[testing]]></category>
            <category><![CDATA[python]]></category>
            <category><![CDATA[hypothesis-testing]]></category>
            <category><![CDATA[python-pandas]]></category>
            <dc:creator><![CDATA[Nico Gallinal]]></dc:creator>
            <pubDate>Mon, 07 Jan 2019 21:43:44 GMT</pubDate>
            <atom:updated>2019-01-07T21:43:44.050Z</atom:updated>
            <content:encoded><![CDATA[<p>Well, with such a title you may think we started hiring pandas as QA analysts.<br>I mean who wouldn’t want a little panda sitting next to them? They are so cute! Unfortunately, this is not the case, the legal team advised us against hiring them.</p><p>This story is about the “flexible and powerful data analysis / manipulation library for Python, providing labeled data structures similar to R data.frame objects, statistical functions, and much more” — p<a href="https://github.com/pandas-dev/pandas">andas github</a>.</p><p>I will not start talking about how great of a library it is. It has been out in the wild (pun intended) for quite long and the community has embraced it for many data analysis tasks.</p><p>But, what I will do is talk about some ways of testing it. The intrepid reader may think of classical unit testing, that could be one approach until one considers the magnitude of data represented by dataframes.</p><p>It is simply impossible to manually create all the many scenarios without letting the time consumed by it tend to infinity.</p><p>So, we would like some machinery to create the data for us. And, not only that, we will also like to create that data in a controlled fashion to recreate the different testing scenarios.</p><p>We would need to define some invariant of the function being tested (a property of the function that must always hold) and assert if the output is in accordance with our expectations.</p><p>Let’s say we have that, and suppose we are working with dataframes of different sizes, maybe we have 90 columns (not a large number at all) and a varying number of rows. It would be desirable that this machinery also provides a way of giving us a simple counterexample (technique known as shrinking) that violates the invariant, and a way of replicating that example.</p><p>Furthermore, this machinery could run each test many times as the data is not the same everytime and that may help us find edge cases.</p><p>What I have just described above is known as property-based testing.<br>The first of its kind was QuickCheck for Haskell a long time ago and, since then, many ports have been developed for different languages. I’ve never had the chance of using the original but I have used jsverify for javascript, cluckcheck for schemer and fscheck for c#.</p><p>All of them with different flavors and some being better than the others, as it generally occurs.<br>This held true until I met <a href="https://hypothesis.readthedocs.io/en/latest/">Hypothesis</a>: “A Python library for creating unit tests which are simpler to write and more powerful when run, finding edge cases in your code you wouldn’t have thought to look for. It is stable, powerful and easy to add to any existing test suite” and determined it is the best one I’ve used. Let me show you with a few examples why I think this and why you should start testing your code with it as well.</p><h3>Example 1: Level Beginner</h3><p>Suppose we have the following function defined in the builder.py file.</p><pre>def fix_new_boxes(raw_prog):<br>    return (<br>        raw_prog<br>        # using -1 as placeholder for mat_code in new boxes<br>        .assign(mat_code=lambda df:<br>            df.mat_code.fillna(NO_MAT_CODE).astype(&quot;int64&quot;)<br>        )<br>        .sort_values(&quot;prog_start&quot;)<br>    )</pre><p>Types annotations are not yet ready for pandas, but we can infer it receives a dataframe with at least two columns: mat_code and prog_starts. And what it does is filling the mat_codes that do not have a value with NO_MAT_CODE. Then it sorts the dataframe by prog_start, which is a date by the way.<br>So let’s write some tests for it.</p><h4>Example 1 Test 1</h4><pre>import pandas as pd</pre><pre>from hypothesis import given<br>from hypothesis import strategies<br>from hypothesis.extra.pandas import column, data_frames</pre><pre>import builder</pre><pre>@given(<br>    data_frames(<br>    columns=[<br>        column(<br>            name=&#39;prog_start&#39;,<br>            elements=strategies.datetimes(<br>                min_value=pd.Timestamp(2017, 1, 1),<br>                max_value=pd.Timestamp(2019, 1, 1)<br>            )<br>        , unique=True),<br>        column(<br>            name=&#39;mat_code&#39;, <br>            elements=strategies.just(float(&#39;nan&#39;))<br>        )<br>    ])<br>)<br>def test_fix_new_boxes_nan_replaced(raw_prog):<br>    prog = builder.fix_new_boxes(raw_prog)<br>    assert (prog.mat_code == builder.NO_MAT_CODE).all()<br>    assert prog.shape == raw_prog.shape</pre><p>Hey Nico, haven’t you just said this was “beginner level”?<br>It seems a lot of code! Don’t worry, let’s decompose it little by little.</p><p>The “given” annotation accepts strategies and … wait, what is a strategy?<br>Fair enough, suppose you want to generate datetimes, there are many ways to do that and each of those is called an strategy. Hypothesis provides one strategy for this which is called “datetimes” and it lets you define a min_value and a max_value as you see above.<br>Let’s look at a few examples from the terminal.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/818/1*Qldnw5BBITSrjeLPu5b9tw.png" /><figcaption>Cool huh? Everytime it is asked for an example it returns a datetime within the given bounds.</figcaption></figure><p>In the Test 1 example we can see that these strategies are composable, what allows to create more complex strategies.<br>Particularly the “data_frames” strategy is composed by the “datetimes” strategy we saw before.<br>Let’s go to the terminal and see some similar examples using “integers”.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/650/1*ttzgaz31msnRp-00oFxM0A.png" /><figcaption>This is getting better, look how we compose strategies and how an empty dataframe is a valid example.</figcaption></figure><p>With these examples from the terminal we are able to completely understand what data we are generating for the test except for the “just” strategy which I haven’t mentioned before. It is very simple, it always returns the value passed to it.<br>There are other strategies provided by the library such as “characters”, “booleans”, “lists”, etc; but we won’t tackle them in this post.</p><p>But let’s go back to the “given” annotation. As I was saying, it receives strategies and with them it generates the data that will be used to test the invariant.</p><p>There should be one invariant we are testing here, can you think of it? While you think let me show you a pandas image so you get some inspiration.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*i1vVm3EqqDIkyucD0079wg.jpeg" /><figcaption>Awww, it is waving at Hypothesis!!!</figcaption></figure><p>The invariant is: “no mat_codes are left as NaNs, they are replace by NO_MAT_CODE”.<br>I also added an assertion about the shape of both dataframes to make sure they are actually being replaced and not being filtered out.</p><h4>Example 1 Test 2</h4><pre>import pandas as pd</pre><pre>from hypothesis import given<br>from hypothesis import strategies<br>from hypothesis.extra.pandas import column, data_frames</pre><pre>import builder</pre><pre>@given(<br>    data_frames(columns=[<br>        column(name=&#39;prog_start&#39;,<br>        elements=strategies.datetimes(<br>            min_value=pd.Timestamp(2017, 1, 1),<br>            max_value=pd.Timestamp(2019, 1, 1)<br>        ), unique=True),<br>        column(name=&#39;mat_code&#39;,<br>        elements=strategies.one_of(<br>            strategies.just(float(&#39;nan&#39;)),<br>            strategies.integers(min_value=100))<br>        )<br>    ])<br>)<br>def test_fix_new_boxes(raw_prog):<br>    prog = builder.fix_new_boxes(raw_prog)<br>    assert prog.mat_code.notna().all()<br>    assert pd.Index(prog.prog_start).is_monotonic_increasing</pre><p>Can you tell which is the invariant we are testing? Again, let me show you an image for inspiration.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/1*XesM6UUwePMqnyS_4iUMJg.jpeg" /><figcaption>Here one of them is telling the other that the question was trickier.</figcaption></figure><p>We are actually testing two invariants:<br>1) No NaN values should be present.<br>2) It must be sorted by prog_start in a monotonic increasing manner.<br>This test should be refactored in two, because we should test one invariant at a time to have exactly one point of failure.</p><p>Have you understand how the strategy “one_of” works? If not, the following examples will make it clear.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/650/1*B_MTX8JqFT7KAaLjq0jNqQ.png" /><figcaption>It receives different strategies and returns the generated value of one picked randomly.</figcaption></figure><h3>Example 2: Level Intermediate</h3><p>Suppose we have the following function defined in the builder.py file.</p><pre>def add_dayofweek_dummies(data):<br>    return (<br>        data<br>        .assign(dayofweek=lambda df:<br>            pd.Categorical(df.prog_start.dt.weekday_name,<br>            categories=[&quot;Monday&quot;, &quot;Tuesday&quot;, &quot;Wednesday&quot;,<br>            &quot;Thursday&quot;, &quot;Friday&quot;, &quot;Saturday&quot;, &quot;Sunday&quot;])<br>        )<br>        .assign(is_weekend=lambda df: <br>            df.dayofweek.isin([&quot;Saturday&quot;, &quot;Sunday&quot;])<br>        )<br>        .pipe(pd.get_dummies, columns=[&quot;dayofweek&quot;])<br>)</pre><p>First of all, what does this function do? It takes a dataframe with a “prog_start” column, it adds a new column called “dayofweek” with the corresponding name, it adds another column called “is_weekend” which is True or False depending the day name and finally it performs one hot encoding on the “dayofweek” column.</p><p>How do we test this, Nico? Good question! Let’s see…</p><h4>Example 2 Test 1</h4><pre>import pandas as pd</pre><pre>from hypothesis import given<br>from hypothesis import strategies<br>from hypothesis.extra.pandas import series, range_indexes</pre><pre>import builder</pre><pre>def assert_is_day(df, i, day):<br>    assert df.loc[i, day] == 1<br>    assert (df.loc[i, ~df.columns.isin(<br>        [&#39;prog_start&#39;, &#39;is_weekend&#39;, day]<br>    )] == 0).all()</pre><pre>@given(<br>    series(<br>        strategies.datetimes(<br>            min_value=pd.Timestamp(2017, 1, 1),<br>            max_value=pd.Timestamp(2020, 1, 1)<br>        ),<br>        index=range_indexes(min_size=7),<br>        unique=True<br>    )<br>    .map(lambda s: s.to_frame(&#39;prog_start&#39;))<br>)<br>def test_add_dayofweek_dummies_is_day(data):<br>    iso_to_day_asserts = {<br>       1: lambda df, i: assert_is_day(df, i, &#39;dayofweek_Monday&#39;),<br>       2: lambda df, i: assert_is_day(df, i, &#39;dayofweek_Tuesday&#39;),<br>       3: lambda df, i: assert_is_day(df, i, &#39;dayofweek_Wednesday&#39;),<br>       4: lambda df, i: assert_is_day(df, i, &#39;dayofweek_Thursday&#39;),<br>       5: lambda df, i: assert_is_day(df, i, &#39;dayofweek_Friday&#39;),<br>       6: lambda df, i: assert_is_day(df, i, &#39;dayofweek_Saturday&#39;),<br>       7: lambda df, i: assert_is_day(df, i, &#39;dayofweek_Sunday&#39;)<br>    }<br>    <br>    dayofweek_dummies = builder.add_dayofweek_dummies(data)</pre><pre>    for i in dayofweek_dummies.index:<br>       iso_to_day_asserts<br>       [dayofweek_dummies.loc[i, &#39;prog_start&#39;].isoweekday()]<br>       (dayofweek_dummies, i)</pre><p>Here we are testing that the labels of the day are correctly set and that the one hot encoding was done right. I won’t go in much detail of how the test works but I will do explain the new stuff.</p><p>We have a “series” and a “range_indexes” strategy and a “map” function.<br>The “series” strategy let us create series of elements of a given strategy, in this case datetimes.<br>The “range_indexes” strategy let us create Indexes. We used it here because we don’t want series with fewer than seven elements.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/650/1*XYjsmUqlBIttvmvedaoW_w.png" /><figcaption>Some examples of range_indexes strategy and series strategy.</figcaption></figure><p>And we have the “map” function which let us transform what was generated before reaching the test according to:</p><pre>s.map(f).example() == f(s.example())</pre><p>So here we let Hypothesis generate a bunch of series and then we are mapping them to dataframes. Isn’t it awesome?</p><h4>Example 2 Test 2</h4><p>Here, we should test the invariant that the weekend days are correctly assigned, I’ll leave that as homework for the reader.</p><p>THIS LINE INTENTIONALLY LEFT BLANK</p><h3>Example 3: Level Advanced</h3><p>Suppose we have the following function defined in the builder.py file.</p><pre>def add_top_programs_dummies(df):<br>    top_programs = (<br>        df[df.selected].prog_name.value_counts()<br>        [lambda s: s &gt;= 50].index<br>    )</pre><pre>    return (<br>        df<br>        .assign(prog=lambda df: <br>            df.prog_name.where(lambda s: s.isin(top_programs), None)<br>        )<br>        .pipe(pd.get_dummies, columns=[&quot;prog&quot;])<br>    )</pre><p>This function receives a dataframe that contains information about different programs in a period of time and when they were selected.<br>It takes the ones that were selected more than fifty times, defines them as top programs and performs one hot encoding over them. One may think this example is the same as the one before, but it isn’t. The dataframes we will be generating needs to be constructed in a more specific way.</p><p>For this, we will need the help of a new and more powerful strategy. <br>Meet the “composite”.</p><p>But first, one last inspiring image!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*LIbjEPq9TXqP--i43AzB8w.jpeg" /><figcaption>Pandas composition :)</figcaption></figure><h4>Example 3 Test</h4><pre>import pandas as pd</pre><pre>from hypothesis import given<br>from hypothesis import strategies<br>from hypothesis.extra.pandas import data_frames, range_indexes</pre><pre>@strategies.composite<br>def prog_generator(draw, top_threshold):<br>    top1 = draw(data_frames(columns=[<br>        column(name=&#39;prog_name&#39;, elements=st.just(&quot;TOP1&quot;)),<br>        column(name=&#39;selected&#39;, elements=st.just(True))<br>    ], index=range_indexes(min_size=top_threshold)))</pre><pre>    top2 = draw(data_frames(columns=[<br>        column(name=&#39;prog_name&#39;, elements=st.just(&quot;TOP2&quot;)),<br>        column(name=&#39;selected&#39;, elements=st.just(True))<br>    ], index=range_indexes(min_size=top_threshold)))</pre><pre>    notop = draw(data_frames(columns=[<br>        column(name=&#39;prog_name&#39;, elements=st.text(<br>            alphabet=[&#39;a&#39;, &#39;b&#39;, &#39;c&#39;, &#39;d&#39;], min_size=2)),<br>        column(name=&#39;selected&#39;, elements=st.just(True))<br>    ], index=range_indexes(max_size=top_threshold - 1)))</pre><pre>    return pd.concat([top1, top2, notop])</pre><pre>@given(prog_generator(top_threshold=50))<br>def test_get_prog_dummies_top_become_dummies(prog):<br>    dummies = builder.add_top_programs_dummies(prog)<br>    <br>    assert (<br>        dummies[dummies.prog_name == &quot;TOP1&quot;].prog_TOP1 == 1<br>    ).all()</pre><pre>    assert (<br>        dummies[dummies.prog_name == &quot;TOP1&quot;].prog_TOP2 == 0<br>    ).all()</pre><pre>    assert (<br>        dummies[dummies.prog_name == &quot;TOP2&quot;].prog_TOP1 == 0<br>    ).all()</pre><pre>    assert (<br>        dummies[dummies.prog_name == &quot;TOP2&quot;].prog_TOP2 == 1<br>    ).all()<br>    <br>    # no dummies for no top progs<br>    assert prog_dummies.shape[1] == 4</pre><p>According to the <a href="https://hypothesis.readthedocs.io/en/latest/data.html#composite-strategies">documentation</a>: “the composite decorator lets you combine other strategies in more or less arbitrary ways. It’s probably the main thing you’ll want to use for complicated custom strategies.” which is precisely what we want to do!!!</p><p>We need to create a single dataframe containing at least a top_threshold amount of TOP1 and TOP2 programs and then many other programs with random names that should appear no more than top_threshold minus one times.</p><p>And that is exactly what we are doing thanks to the draw function.<br>The draw function is always passed as the first argument of the composite and should be thought as a function that returns one example of the strategy it was invoked with.</p><p>There is much more of Hypothesis out there but this is all for now.<br>I hope you have enjoyed reading this article as much as I have enjoyed writing it. Also hopefully the examples were clear and that takes you right away to the Hypothesis <a href="https://hypothesis.readthedocs.io/en/latest/index.html">site</a> to dive deeper and start using it.</p><p>Thanks for reading and stay tuned!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=b65c0ea8a28e" width="1" height="1"><hr><p><a href="https://engineering.hexacta.com/testing-pandas-b65c0ea8a28e">Testing Pandas</a> was originally published in <a href="https://engineering.hexacta.com">Hexacta Engineering</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Chocolatest, a sweet story of yet another testing framework.]]></title>
            <link>https://engineering.hexacta.com/chocolatest-a-sweet-story-of-yet-another-testing-framework-49b9898318bc?source=rss----a41470515491---4</link>
            <guid isPermaLink="false">https://medium.com/p/49b9898318bc</guid>
            <category><![CDATA[tools]]></category>
            <category><![CDATA[testing]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[metaprogramming]]></category>
            <dc:creator><![CDATA[Nico Gallinal]]></dc:creator>
            <pubDate>Tue, 23 Oct 2018 21:33:20 GMT</pubDate>
            <atom:updated>2018-10-23T21:33:20.847Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_8xFwtQBmLllgkOFwthFaw.png" /><figcaption>a preview of an exercise after checking the solution</figcaption></figure><p>Weeks ago, Hexacta asked me to develop an application to challenge computer-engineering students. This application was going to be used at a convention where Hexacta would had a stand. There we’d tell about us and get in touch with young people that want to do cool stuff like us :)</p><p>The idea was simple: “let’s have a web application where they can tackle some programming challenges”. The first thing that I thought of was “it would be cool if they are presented with different functions to implement, but it would be cooler if they are given some sample tests to explain how the function should work besides the specification. If we could make it so that they can add their tests and run them, that would be very neat. And what about giving them a score running some hidden tests for each exercise, that would definitely be very nice…”</p><p>I was up to the challenge and then asked how much time I had… Only a week!</p><p>It was something really cool to build so I said to myself that I would give my best in order to make it happen but there were no guarantees, there was not much time and so I began.</p><p>I started, as always, googling around to see if there was something I could make good use of. I just had to run JavaScript tests on the browser but these were not the kind of test where you have functions and assertion. These were the tests where your implementation is a string and your tests are a strings too!!!</p><p>It is very likely that you are now asking yourself what the heck is Nico talking about?! Do you remember that I said that the user would have to implement a function? Maybe using some editor as Monaco (the one that powers Visual Studio Code)? Do you also remember that I said that the user could also add more tests to the samples? Strings and strings, now you are following me, I feel better.</p><p>I had to implement a testing framework in one week that would evaluate JavaScript as strings and also make the application. Clearly there was no time to waste!!!</p><p>I had experience with Node’s vm module and I said “I need something like that”. <a href="https://github.com/browserify/vm-browserify">https://github.com/browserify/vm-browserify</a> was the answer.</p><p>Then I said, I would need some assertions but I don’t want to reinvent the wheel. Maybe I can find something like Node’s assert module, right? And again I was lucky to find <a href="https://github.com/browserify/commonjs-assert">https://github.com/browserify/commonjs-assert</a>.</p><p>I should really thank the Browserify team for the only two dependencies Chocolatest has, without them I would have ran out of time!</p><p>Now that I had the building blocks, I needed a way of intercepting the calls to the different assert methods and create a log of what was going on during the execution of the tests.</p><p>The word intercepting made me think about Aspect Oriented Programming but we all know we do not have all those fancy things in JavaScript! What we do have is meta-programming thanks to the Proxy object.</p><p>Most of the magic happens in the following lines.</p><pre>import { Assertion } from &#39;./types&#39;;<br>import * as assert from &#39;assert&#39;;<br><br>type Omit&lt;T, K extends keyof T&gt; = Pick&lt;T, Exclude&lt;keyof T, K&gt;&gt;;<br><br>const applyWrapper = (operator: string, method: (...args: any[]) =&gt; any, thisArg: any, args: any[], log: (assertion: Assertion) =&gt; void) =&gt; {<br>  try {<br>    let result = method.apply(thisArg, args);<br>    log({&#39;ok&#39;: true, &#39;operator&#39;: operator, &#39;args&#39;: args, &#39;type&#39;: &#39;assert&#39;});<br>    return result;<br>  } catch (e) {<br>    log({&#39;ok&#39;: false, &#39;operator&#39;: operator, &#39;args&#39;: args, &#39;type&#39;: &#39;assert&#39;});<br>    // we don&#39;t want to fast fail, we want to run all asserts in test<br>    // throw e; <br>  }<br>}<br><br>const generateProxy = (log: (assertion: Assertion) =&gt; void) =&gt; {<br>  return new Proxy(assert,<br>  {<br>    apply(target, thisArg, args) {<br>      return applyWrapper(&#39;assert&#39;, target, thisArg, args, log);<br>    },<br>    get(target, propKey: keyof Omit&lt;typeof assert, &#39;AssertionError&#39;&gt;) {<br>      const origMethod = target[propKey];<br>      return function (...args: any[]) {<br>        return applyWrapper(propKey, origMethod, target, args, log);<br>      };<br>    }<br>  });<br>}<br><br>export {<br>  generateProxy<br>}</pre><p>First of all, you will notice that the code is written in TypeScript. If you haven’t tried it yet I suggest you do it.</p><p>Secondly, I’m sure you noticed the creation of a Proxy of the library assert, where it says “new Proxy(assert, …” and again you probably said what the heck Nico?!</p><p>Basically, what I’m simply doing is intercepting all the calls to the methods of assert (even assert itself which is a method too) and calling the original method in isolation inside a try catch block. With this interception I’m able to log when the method is about to be called, when it was called and it threw because of an exception or when it was executed successfully.</p><p>The method “generateProxy” is called with a log as an argument, this is a collector function where I will be allocating all the events described above and some more.</p><p>Now that I explained you the framework, I’ll give you the link in case you wanna play with it <a href="https://github.com/nicoabie/chocolatest">https://github.com/nicoabie/chocolatest</a> and tell you about what happened to the application.</p><p>The application was developed on Vuejs using the Monaco editor to make a good coding experience and had some exercises ready for the convention time. The convention started at 9 AM and the last commit was about 9:20 AM or so. I will not brag about its success because in the end no student got to use it, hahaha! There were so many people walking around that it wasn’t an easy task to stop on a stand and apparently they were starting the University so they were a little bit shy unfortunately.</p><p>Anyways, we are at Hexacta thinking about having it published on our website, so you can be challenged with some exercises and test your level!!!</p><p>Thanks for reading and stay tuned!</p><p>P.S. I recently found out that around 500 modules are published each day on npm according to <a href="http://www.modulecounts.com/">http://www.modulecounts.com/</a>. I just want you to know that before I started to code I searched for quite a bit if such a framework existed to avoid polluting our environment further hahaha.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=49b9898318bc" width="1" height="1"><hr><p><a href="https://engineering.hexacta.com/chocolatest-a-sweet-story-of-yet-another-testing-framework-49b9898318bc">Chocolatest, a sweet story of yet another testing framework.</a> was originally published in <a href="https://engineering.hexacta.com">Hexacta Engineering</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Part 2: Install and Setup a 3-node Hadoop Cluster Cloudera]]></title>
            <link>https://engineering.hexacta.com/part-2-install-and-setup-a-3-node-hadoop-cluster-cloudera-29e9a62f3c78?source=rss----a41470515491---4</link>
            <guid isPermaLink="false">https://medium.com/p/29e9a62f3c78</guid>
            <category><![CDATA[hadoop]]></category>
            <category><![CDATA[big-data]]></category>
            <category><![CDATA[cloudera]]></category>
            <dc:creator><![CDATA[Mariano N. Lirussi]]></dc:creator>
            <pubDate>Fri, 21 Sep 2018 15:17:00 GMT</pubDate>
            <atom:updated>2018-09-21T15:17:00.353Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/962/1*6b9FjVE5-W4nJ_YXJegtDw.png" /></figure><p>Let’s resume with our installation of a Hadoop cluster. First, login to the site we configured in the first part of the installation: <a href="http://master.hexacta.com:7180/">http://master.hexacta.com:7180</a></p><p>Login with the default credentials</p><blockquote>user: admin</blockquote><blockquote>pass: admin</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/761/1*oNknNv68zAROCnlMMURNSQ.png" /></figure><p>It is important to read and accept the Cloud Manager License</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/991/1*7ZQfmK_g5XmZ4h378YhEGg.png" /></figure><p>Now, we arrive to the moment where we must select the edition of Cloudera that we want. For the purpose of this document, we are going to select the option “Cloudera Express”.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1015/1*JF37pCN6WQtgjuhXFRzXPQ.png" /></figure><p>Then we can receive some interesting topics and information about the versions and requirements.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/998/1*rpE0D1easJNFUCy72o2ycQ.png" /></figure><p>The time has come to for us to specify the hosts that we are going to configure as nodes for our cluster.</p><p>This specification has a relation with the configuration of /etc/hosts that we saw in the first part of the installation.</p><p>This is why we are only going to put the IPs of the Master and the nodes.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1009/1*kHXdp5xVmg53lXC92SweMQ.png" /></figure><p>Now we will see if the hosts are ready for installation and running as needed. If all is well, we continue with the configuration of the nodes.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/994/1*TVXcJFr1c6TIIS3_oj89-Q.png" /></figure><p>In the following step, we are going to select the repository method and any additional parcels we need to add to those already in the CDH suite. By default, we select the options ‘Use Parcels’.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/978/1*T1JFt5-wHhh5h5CEXYwCOw.png" /></figure><p>To continue we have to read and accept the license of Oracle JDK to be able to install and use it.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/973/1*B_nayFeByPuNhogonBMI8w.png" /></figure><p>Next, we have the option to enable ‘single user mode’. In this case, we leave it as it is without enabling.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/981/1*8Sfojc9eW-CObg61YKRLAg.png" /></figure><p>We have to configure the user and his credentials for the automatic management of the master and the nodes. Let’s configure it with a user other than root. Select ‘another user’ and put the user ‘Hadoop’.</p><p>Select ‘all host accept same private key’ and load the id_rsa.pub file of the Hadoop user that we created in the master in the first part of the installation. We load the passphrase if we configured any.</p><p>In case you don’t want to use the SSH key file you also have the option ‘All hosts accept same password’ and we complete the password field. Clearly, the Hadoop user must have the same password in all nodes.</p><p>The other parameters are left with their default values unless we have to change them.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*hhzFyXgtzPj3YV5Vfe_yeA.png" /></figure><p>In the next screen, we see the process of installation and agents.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/994/1*e-IbW7cdhJ1inQ98mRhPQw.png" /></figure><p>Once you successfully complete the installation on the cluster nodes, let’s continue with the installation.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/981/1*2W058drm_ds_aPHN3iRTQw.png" /></figure><p>Now we have to see the process of installing the parcels in each node.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/989/1*CJ4wwFyyexhIcg4P9zeX2w.png" /></figure><p>If everything went ok, we are going very well. Now we are going to inspect the installation in the nodes, this process might take some time. After this, we will have successfully finished the installation of our cluster in all the machines where we plan to run it.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*QTBRvG7QqdICw4qFyrlKCQ.png" /></figure><h4>Cluster Setup:</h4><p>Great, now we are going to start with the Cluster Service Setup. Here we can select the option that best suits our needs. We can select if we need some extra service besides those from Core Hadoop.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/995/1*ZX55QdYYeg__Y3-cHaO6Ww.png" /></figure><p>Once we know what services we are going to run in our cluster, we can configure the assignment of them within our nodes. There are several possibilities to set these preferences but in this opportunity, we are going to pass them by since they can be configured later from the options from the Cloudera manager.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*oAYdwNYbLLCjj5WHi-wDPA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*gtKxW4ULDyH6Z9D9QQWk3w.png" /></figure><p>Awesome!</p><p>Now we must configure and test the connection to the database. Some Hadoop Core services need a Posgresql to run their service (like Hive). There are two ways to run the database:</p><ul><li>In an external Postgresql: this option is the right one to run a Hadoop cluster installation in production.</li><li>The ‘Embedded Database’ option, which is the option we chose in this guide to continue without additional resources.</li></ul><p>After selecting the Embedded Database, we test the connection to Posgresql. If successful, we are ready to continue.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*6-pb09BoTfXjIx-9Vxq_4A.png" /></figure><p>We are almost finished but we still have to check and customize any additional parameters.</p><p>As like the block size of HDFS or the tolerance of failures in the volumes among others.</p><p>In general, most of these options can be configured from the system already installed, so we will continue without making changes.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*RPdEhXyWJC31Dfc33bV4qg.png" /></figure><p>Very well done!</p><p>We arrived at the process of installation and execution of each of the services we decided to install and with the preferences we selected.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*MuhFV6gLiJ-M2mzh1Sm7DA.png" /></figure><p>If we get to this point, it means that we already have our Hadoop cluster installed, configured and running successfully.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/771/1*sctNT8cR4w-I3V_nNVxrZw.png" /></figure><p>Congratulations! On the dashboard screen, we have our Hadoop cluster with cloud manager installed, working and ready to work. You can get some notifications like the Postgresql database embedded as we selected in our installation, for each of the notifications the system offers a description and documentation to know how to address the problem.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*S_Lv2LcpiF-f0y7lMU_Cow.png" /></figure><p>Good luck and enjoy the Hadoop cluster.</p><p>See you next time.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=29e9a62f3c78" width="1" height="1"><hr><p><a href="https://engineering.hexacta.com/part-2-install-and-setup-a-3-node-hadoop-cluster-cloudera-29e9a62f3c78">Part 2: Install and Setup a 3-node Hadoop Cluster Cloudera</a> was originally published in <a href="https://engineering.hexacta.com">Hexacta Engineering</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Part 1: How To install a 3-Node Hadoop Cluster on Ubuntu 16]]></title>
            <link>https://engineering.hexacta.com/part-1-how-to-install-a-3-node-hadoop-cluster-on-ubuntu-16-d057dbd4f6b7?source=rss----a41470515491---4</link>
            <guid isPermaLink="false">https://medium.com/p/d057dbd4f6b7</guid>
            <category><![CDATA[hadoop]]></category>
            <category><![CDATA[big-data]]></category>
            <category><![CDATA[deployment]]></category>
            <category><![CDATA[hadoop-cluster]]></category>
            <category><![CDATA[cloudera]]></category>
            <dc:creator><![CDATA[Mariano N. Lirussi]]></dc:creator>
            <pubDate>Tue, 21 Aug 2018 19:27:49 GMT</pubDate>
            <atom:updated>2018-08-21T19:27:49.168Z</atom:updated>
            <content:encoded><![CDATA[<p>This guide is intended to provide a quick and easy way to install Cloudera Hadoop on local servers.</p><p>For this reason, we need to prepare the infrastructure environments prior to installation.</p><p>In this way, we assume that you have some basic knowledge on networking, linux administration and Apache Hadoop.</p><p>1.-Requirements</p><p>We recommend complying with the following minimum hardware requirements:</p><blockquote><strong>Master: CPU x6 core — 12Gb Mem — 80Gb HD</strong></blockquote><blockquote><strong>Node: CPU x4 core — 4Gb Mem — 80Gb HD</strong></blockquote><p>In this case, we configured the network at each node as follows:</p><blockquote><strong>master.hexacta.com 10.0.5.1</strong></blockquote><blockquote><strong>node1.hexacta.com 10.0.5.2</strong></blockquote><blockquote><strong>node2.hexacta.com 10.0.5.3</strong></blockquote><p>Once the network is ready, we make sure we have the latest updates on each node.</p><pre><strong>-:# apt-get update &amp;&amp; apt-get upgrade -y<br>-:# apt install ssh rsync</strong></pre><p>2.- Config Hosts</p><p>The configuration of host names and their relationship to the corresponding IP addresses is a very important point to consider. These IP address will be used in the /etc/hosts file on all nodes.</p><p>On our case, we have it this way:</p><pre><strong>10.0.5.1 master.hexacta.com</strong></pre><pre><strong>10.0.5.2 node1.hexacta.com</strong></pre><pre><strong>10.0.5.3 node2.hexacta.com</strong></pre><pre><strong>127.0.0.1 localhost</strong></pre><pre><strong>127.0.1.1 localhost</strong></pre><p>3.- Create user and ssh-key</p><p>Now we must create the hadoop user on all nodes with sudo permissions. Besides, it should not ask for a password using the sudo command. For this, we use the commands to create the user:</p><pre><strong>-:# adduser hadoop</strong></pre><p>We added him to the group with sudo permissions.</p><pre><strong>-:# adduser hadoop sudo</strong></pre><p>Then in order not to require the passwd we must edit the sudo configuration with the command:</p><pre><strong>-:# visudo</strong></pre><p>Within the configuration, we must add the line for the <strong>hadoop</strong> user under the <strong>%sudo</strong> section as seen in the following line:</p><pre># Allow members of group sudo to execute any command<br> %sudo ALL=(ALL:ALL) ALL<br> <strong>hadoop ALL=(ALL) NOPASSWD: ALL</strong></pre><p>Now it is necessary to create the ssh key for the hadoop user so that the Master node can manage the Nodes securely remotely.</p><p>In the Master with the hadoop user session, we generate the key with the following command:</p><pre><strong>-:# ssh-keygen -b 4096</strong></pre><p>Then we copy the public key to the master and the nodes we want to install.</p><pre><strong>-:# ssh-copy-id -i $HOME/.ssh/id_rsa.pub hadoop@master.hexacta.com</strong></pre><pre><strong>-:# ssh-copy-id -i $HOME/.ssh/id_rsa.pub hadoop@node1.hexacta.com</strong></pre><pre><strong>-:# ssh-copy-id -i $HOME/.ssh/id_rsa.pub hadoop@node2.hexacta.com</strong></pre><p>4.- Swappiness</p><p>To avoid swappiness errors or warnings we will customize a kernel parameter.</p><p>We change it in the current execution with the command</p><pre><strong>-:# sysctl vm.swappiness=10</strong></pre><p>To persist this change in future restarts we add the configuration line at the end of the file</p><p>/etc/sysctl.conf :</p><pre><strong>-:# echo ‘vm.swappiness = 10’ &gt;&gt; /etc/sysctl.conf</strong></pre><p>NOTE: <strong>Swappiness</strong> is a Linux kernel parameter that controls the relative weight given to swapping out of runtime memory, as opposed to dropping pages from the system page cache.</p><p>So far, we have correctly configured the infrastructure for the installation of any Hadoop distribution system.</p><p>5.- Install Cloudera</p><p>Now let’s install Hadoop-Cloudera-Manager. The Cloudera Manager is an administration tool that will help you administrate the services on your Hadoop Cluster. There are a free and an Enterprise version. We used the free version to set up the whole cluster.</p><p>First, we need to download the installer of the latest version of Cloudera-manager</p><pre><strong>-:# wget http://archive.cloudera.com/cm5/installer/5.15.0/cloudera-manager-installer.bin</strong></pre><p>We have to change the installer permissions to be able to run it.</p><pre><strong>-:# chmod u+x cloudera-manager-installer.bin</strong></pre><p>Run the file with sudo to start the installation.</p><pre><strong>-:# sudo ./cloudera-manager-installer.bin</strong></pre><p>Cloudera-Manager-README:</p><p>This Readme gives useful details for the subsequent installation of Cloudera manager, such as the Linux versions it supports, let’s click on “next”.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/764/1*Qx7-_hjmfcw_LwA4ZmG0VA.png" /></figure><p>This is the Cloudera Standard License, let’s click on “Next” after reading it.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*4pEA1TdzUPQJbRXu1P5-aw.png" /></figure><p>We accept the license’s terms of use.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/356/1*QBEtEZ9fv3H6lNmPJ5-5gw.png" /></figure><p>We click “next” to accept the license of the Oracle Java SE Plataform</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*epYKdTbkQSCoezW6SCN_vA.png" /></figure><p>Accept Oracle License</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/564/1*mFn5MTV4m-5jy0lQIxeQFA.png" /></figure><p>We expect the Cloudera Manager Server installation process to be completed</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/632/1*IkEByKfPSG7E_oKhAcHNUw.png" /></figure><p>After the installation of Cloudera Manager is finished, we can continue with the second part of Cluster Setup by going to <a href="http://master.hexacta.com:7180/">http://master.hexacta.com:7180/</a> for our example, with the user name: admin and passwd admin.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*I8zo9DZLybHAQhYkx-QmqA.png" /></figure><p>Installation successfully completed</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/548/1*JHzGuujOi2jA7boXHDz1SA.png" /></figure><p>After the installation is complete, access the site <a href="http://master.hexacta.com:7180/.">http://master.hexacta.com:7180/.</a> We can continue with the installation and configuration of the Cloudera-Manager cluterization from that point onward.</p><p>On Part 2, we will be explaining how to set up the Hadoop Cluster with Cloudera Manager.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d057dbd4f6b7" width="1" height="1"><hr><p><a href="https://engineering.hexacta.com/part-1-how-to-install-a-3-node-hadoop-cluster-on-ubuntu-16-d057dbd4f6b7">Part 1: How To install a 3-Node Hadoop Cluster on Ubuntu 16</a> was originally published in <a href="https://engineering.hexacta.com">Hexacta Engineering</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[JSX can do that?]]></title>
            <link>https://engineering.hexacta.com/jsx-can-do-that-1b2666c23a32?source=rss----a41470515491---4</link>
            <guid isPermaLink="false">https://medium.com/p/1b2666c23a32</guid>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[functional-programming]]></category>
            <category><![CDATA[react]]></category>
            <category><![CDATA[algorithms]]></category>
            <category><![CDATA[javascript]]></category>
            <dc:creator><![CDATA[Rodrigo Pombo]]></dc:creator>
            <pubDate>Sun, 06 May 2018 14:37:10 GMT</pubDate>
            <atom:updated>2018-05-22T14:15:21.676Z</atom:updated>
            <content:encoded><![CDATA[<p>First I’m going to explain how JSX works and then use it in “unusual” ways. If you know how JSX works you can skip the first part. If you are here to learn something useful you can skip the second part.</p><p>Last week I tweeted this:</p><style>body[data-twttr-rendered="true"] {background-color: transparent;}.twitter-tweet {margin: auto !important;}</style><blockquote class="twitter-tweet" data-conversation="none" data-align="center" data-dnt="true"><p>This works</p><p>&#x200a;&mdash;&#x200a;<a href="https://twitter.com/pomber/status/991451257289273344">@pomber</a></p></blockquote><script src="//platform.twitter.com/widgets.js" charset="utf-8"></script><script>function notifyResize(height) {height = height ? height : document.documentElement.offsetHeight; var resized = false; if (window.donkey && donkey.resize) {donkey.resize(height); resized = true;}if (parent && parent._resizeIframe) {var obj = {iframe: window.frameElement, height: height}; parent._resizeIframe(obj); resized = true;}if (window.location && window.location.hash === "#amp=1" && window.parent && window.parent.postMessage) {window.parent.postMessage({sentinel: "amp", type: "embed-size", height: height}, "*");}if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.resize) {window.webkit.messageHandlers.resize.postMessage(height); resized = true;}return resized;}twttr.events.bind('rendered', function (event) {notifyResize();}); twttr.events.bind('resize', function (event) {notifyResize();});</script><script>if (parent && parent._resizeIframe) {var maxWidth = parseInt(window.frameElement.getAttribute("width")); if ( 500  < maxWidth) {window.frameElement.setAttribute("width", "500");}}</script><p>People loved it. You can see it in the replies: “Eww”, “what have we done”, “oh no is XML back again”, “Every day we stray further from god’s light”, “murderer”. I write this post to return the love to them (that and also I said to <a href="https://medium.com/u/b08e8937c874">Lorenzo Palmes</a> I’ll write this post if the tweet reached 100 likes, thanks for the retweet <a href="https://medium.com/u/e50c25098d37">Ken Wheeler</a>…).</p><h4>JSX</h4><p>If you used React you know JSX, that XML-like syntax for creating React elements:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/0187f0f4c1646e17f1ec1dbbd9d5ebbf/href">https://medium.com/media/0187f0f4c1646e17f1ec1dbbd9d5ebbf/href</a></iframe><p>Because browsers don’t support JSX, your code needs to be changed to normal JavaScript before a browser runs it. This transformation from developer-friendly code to browser-friendly code is done by tools like Babel. Using Babel, the getGreeting function becomes:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2c77b5e23acbcaf5847f9469dd4efe0a/href">https://medium.com/media/2c77b5e23acbcaf5847f9469dd4efe0a/href</a></iframe><p>All the tag names, attribute names, attribute values, and text content are still there, with a different syntax. But what about React.createElement?</p><p>React.createElement is the function that React uses to create elements. Babel inject that function by default because JSX is commonly used together with React, but that doesn&#39;t need to always be the case. In fact JSX is decoupled from React. JSX is a specification for defining tree structures with an XML-like syntax in JS. That tree structure could be the elements rendered by a React component or something entirely different.</p><p>In order to use JSX for something different than React, we only need to tell Babel to use another function instead of React.createElement. We do that by adding the comment /** @jsx anotherFunction */ somewhere in the file. For example:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e1fc3e6b030d477e38c08f463d7b1ba6/href">https://medium.com/media/e1fc3e6b030d477e38c08f463d7b1ba6/href</a></iframe><p>One last thing you need to know is that Babel handles JSX element names in different ways depending if they start with lowercase or with uppercase. Lowercase names are passed as string arguments, like &lt;x/&gt; in the last snippet. Titlecase names are passed as functions, like &lt;Y/&gt; in the snippet.</p><h4>JSX for Math</h4><blockquote>Disclaimer: beyond this point you probably won’t learn anything. I’m going to use JSX for things it shouldn’t be used.</blockquote><p>We can calculate the hypotenuse of a and b with Math.sqrt(a*a + b*b), but that&#39;s no fun. Let&#39;s write it with JSX:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e29f3facdcfd6477ed4532e61f636019/href">https://medium.com/media/e29f3facdcfd6477ed4532e61f636019/href</a></iframe><p>There’s also a version of hypotenuse that can receive more than two arguments:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/374700da073b0e8647a35ec17f7dcfe4/href">https://medium.com/media/374700da073b0e8647a35ec17f7dcfe4/href</a></iframe><h4>JSX for Everything</h4><p>Let’s try something more ambitious, let’s try merge sort.</p><p>We’ll use RamdaJS to have some primitives for our components. This is how FizzBuzz looks in ramda:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/633a27a903d3876b396358e10729c9f1/href">https://medium.com/media/633a27a903d3876b396358e10729c9f1/href</a></iframe><p>We can write the same code using JSX, we only need to write the function that calls the ramda function that matches the JSX element name:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/393356ba7cb49ea44b51265f2580c127/href">https://medium.com/media/393356ba7cb49ea44b51265f2580c127/href</a></iframe><p>Beautiful, right?… No.</p><p>We can make the run function smarter in order to increase the JSX “purity” of the code:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2734dd7e4872c0f528ae1346c238cfb8/href">https://medium.com/media/2734dd7e4872c0f528ae1346c238cfb8/href</a></iframe><p>Now, anything you can do with ramda you can also do it with JSX. And you can do everything with ramda, including merge sort:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zSBIHbvIoyVVhjI5MhW1XA.png" /><figcaption><a href="https://codepen.io/pomber/pen/yjzQMy?editors=0012">codepen</a></figcaption></figure><p>Thanks for reading.</p><p>Follow <a href="https://twitter.com/pomber">@pomber</a> on twitter for more (awful) stuff like this.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1b2666c23a32" width="1" height="1"><hr><p><a href="https://engineering.hexacta.com/jsx-can-do-that-1b2666c23a32">JSX can do that?</a> was originally published in <a href="https://engineering.hexacta.com">Hexacta Engineering</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Reactive Programming basics]]></title>
            <link>https://engineering.hexacta.com/reactive-programming-basics-89b7a9d664b1?source=rss----a41470515491---4</link>
            <guid isPermaLink="false">https://medium.com/p/89b7a9d664b1</guid>
            <category><![CDATA[front-end-development]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[reactive-programming]]></category>
            <category><![CDATA[angularjs]]></category>
            <dc:creator><![CDATA[Emanuel]]></dc:creator>
            <pubDate>Wed, 14 Sep 2016 00:00:00 GMT</pubDate>
            <atom:updated>2018-04-03T13:33:30.127Z</atom:updated>
            <content:encoded><![CDATA[<p><em>Like its name indicates, reactive programming is oriented to reaction, to the data flow and the principle of causality, meaning that, each cause is connected to its effects.</em></p><p>This is a paradigm, meaning that most problems that can be solved with <strong>reactive programming</strong> can also be solved by other types of programming; object-oriented, procedural, functional, etc. The most important thing is to recognize which approach is the most appropriate, because this decision impacts the elegance and the quality of the resolution obtained.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/0*m1IMbYzTxP06DC3R.jpeg" /></figure><p>Like its name indicates, reactive programming is oriented to reaction, to the data flow and the principle of causality, meaning that, each cause is connected to its effects. Perhaps the most known example is the spreadsheets’ one; where the modification of a cell (event) triggers the following modification of all cells that <em>were</em> <em>watching it</em>. And “watching” is one of the keywords because it will be easier to understand the issue if we know the <a href="https://en.wikipedia.org/wiki/Observer_pattern">GoF observer’s pattern</a>.</p><h3>A little theory</h3><p><a href="http://www.reactivemanifesto.org/">The Manifesto of the reactive programming</a> was rewritten at the end of 2014 and, according to it, the reactive systems have 4 features:</p><ul><li><strong>Responsiveness</strong>: They are focused on quick and consistent times of response. Error handling is simplified and encourages interaction with the user</li><li><strong>Resilience</strong>: systems will remain responsive even in the presence of errors. For this to be achieved, failures should be isolated and contained in components and should be able to recover without compromising its integrity.</li><li><strong>Elasticity</strong>: Because they adapt to variations in workload, allocating and freeing resources dynamically, and because they are designed so that its components do not form bottlenecks.</li><li><strong>Oriented messages</strong>: the exchange of asynchronous messages is completely trusted. Blocking communication doesn’t exist.The elasticity, faults and messages are points to consider here.</li></ul><p><em>The elasticity differs from scalability: </em>the program is not defined along with the resources; these are automatically allocated at runtime (very similar to functional programming).</p><p><em>Failures differ from mistakes: </em>failure is unexpected and is not used as flow control. You can disable the part of the system that depends directly on these.</p><p><em>The messages differ from the events: </em>in an event-based system, the components actively expect that entities change of state. Instead, the messages have an associated recipient that is activated when they are received.</p><h3>Viewing data flows</h3><p>To display the data, a <a href="https://www.google.com.ar/search?q=marble+diagrams&amp;rls=com.microsoft:es-ES:IE-Address&amp;biw=785&amp;bih=902&amp;source=lnms&amp;tbm=isch&amp;sa=X&amp;ved=0ahUKEwiYuYvFqKzMAhUHg5AKHVcTC0kQ_AUIBigB">marbles diagrams</a> is often used. You can see in them each data stream and the underlying transactions that can be applied to them:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/300/0*zZ4SMI8geEuoEc4m.jpg" /></figure><p>These diagrams are read from left to right, and each ball represents the occurrence of an event that is being observed. Intermediates rectangles indicate the operation to be applied to each. For example, in the image include the following:</p><p>• Map: It applies a transformation as a parameter passed to the emissions of a data stream.</p><p>• FlatMap: Make asynchronous applications to data flow , and then crushes emissions to a simple observable .</p><p>• Concat: concatenates emissions of two or more streams without crossing them (Note that the flows should “finish” to make it applicable).</p><p>• Merge: Combines multiple flows and interlocks emissions.</p><p>All these diagrams can be displayed interactively <a href="http://rxmarbles.com/">on this website</a>. Can you guess what these two operations make? <a href="http://rxmarbles.com/#pausableBuffered">Operation1</a>, <a href="http://rxmarbles.com/#amb">Operation2.</a></p><p>Perhaps the trickiest part of programming is not reactive programming itself; how difficult is to think about the “how” to deal with common problems. For example, if I need an action to be triggered when a user performs multiple clicks on an item, the communication flow should be approximately as follows:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/214/0*3x1IcU14mMSHPhq-.png" /></figure><p>As you can see, there are no temporary variables, buffers, promises, active checks or other traditional programming resources. Only flows, emissions and four lines of code.</p><h3>Environments and languages to use reactive programming</h3><p>We can find languages specifically reactive as Elm and R. Most frameworks that have their reactive part are available for .NET and JavaScript. In JavaScript we can find <a href="http://hat.hexacta.com/meteor-js/">MeteorJS</a>, <a href="http://proactjs.github.io/">ProActJS</a>, <a href="https://baconjs.github.io/">BaconJS</a> and <a href="https://facebook.github.io/react/">React</a>.</p><p>Perhaps the main exponent is <a href="http://reactivex.io/">Reactive Extensions</a>, or simply ReactiveX Rx (all names represent the same thing). This is an API for asynchronous programming and reactive available for Java, JavaScript (+ Angular), C # (+ Unity), Ruby, Python, PHP a<a href="https://github.com/Reactive-Extensions">nd others</a>. In total there are <a href="http://reactivex.io/documentation/operators.html#alphabetical">402 observable operations</a>, each with its corresponding diagram of marbles.</p><p>Here is an example of integration with Angular, when searching for a page on Wikipedia:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/1f2542e2c8c57898458a68e7c2b93452/href">https://medium.com/media/1f2542e2c8c57898458a68e7c2b93452/href</a></iframe><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=89b7a9d664b1" width="1" height="1"><hr><p><a href="https://engineering.hexacta.com/reactive-programming-basics-89b7a9d664b1">Reactive Programming basics</a> was originally published in <a href="https://engineering.hexacta.com">Hexacta Engineering</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Machine Learning — Classification]]></title>
            <link>https://engineering.hexacta.com/machine-learning-classification-aebcbf4ecc36?source=rss----a41470515491---4</link>
            <guid isPermaLink="false">https://medium.com/p/aebcbf4ecc36</guid>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[azure]]></category>
            <category><![CDATA[data-science]]></category>
            <dc:creator><![CDATA[Emanuel]]></dc:creator>
            <pubDate>Wed, 05 Oct 2016 00:00:00 GMT</pubDate>
            <atom:updated>2018-03-28T18:43:02.401Z</atom:updated>
            <content:encoded><![CDATA[<p><em>Learn in this article about Machine Learning and the classification of algorithms, written by one of our software engineering experts from the HAT.</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/0*2Y_lbzDRVmmXfo3P.jpg" /></figure><p>Algorithms’ classification predict the class or category for a single instance of data. For example, email filters use binary classification to determine if an email is spam. There are two forms of classification tasks. The first is binary classification, where the goal is to predict one of two outcomes.</p><p>The other is multiclass classification, where the goal is to predict one of many outcomes. The output of a classification algorithm is called a classifier, which can be used to predict the label of a new (unlabeled) instance.</p><p>This is a supervised learning algorithms make predictions based on a set of examples. For instance, historical stock prices can be used to hazard guesses at future prices. Each example used for training is labeled with the value of interest.</p><h3>Let’s start with the question: Is this A or B?</h3><p>This family of algorithms is called two-class classification.<br> It’s useful for any question that has just two possible answers. They are several algorithms for use for this question. This next image represent a two-classes support vector machine, one of the most popular used.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/0*A_eAWVhCKsfDeclj.png" /></figure><h4>Is this A or B or C or D, etc.?</h4><p>This is called multiclass classification and it’s useful when you have several — or several thousand — possible answers. Multiclass classification chooses the most likely one.<br> The next image represent a one vs. all classification.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/0*20-7V7NHXko2mizs.png" /></figure><h3>AzureML algorithms for Classification</h3><p>The category Initialize Classification Model includes the following modules:<br> To see the complete documentation of each one go <a href="https://msdn.microsoft.com/en-us/library/dn905808.aspx#Anchor_0">here!</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/560/0*IXjb8ePMfKTFi4R5.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/0*u6Reh0ln6sZR0K8M.png" /></figure><p>Example</p><p><strong>1- Selection of data set</strong><br>We use the Adult Census Incoming Binary classification data set.<br>The column income is the label.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/670/0*ffqIPpbdJIjxLffn.png" /></figure><p><strong>2- Using select column and Split data</strong><br>We select the columns that we know will be more useful for the prediction, and then we Split the data for train and score the model.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/0*B5PgLzjd3SXMOSN-.png" /></figure><p><strong>3- Using the Two-class Boosted Decision</strong><br>We drop the classification model into the canvas and leave the default parameters values.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/0*hYLcv3H4Yw1hU1w9.png" /></figure><p><strong>4- Score and evaluate model</strong><br>Run the experiment to check the score and the evaluate model results.<br>The right two columns, Scored Labels and Scored Probabilities are the prediction results. The Scored Probabilities column shows the probability that the predicted class belongs to the positive one (in this case “&gt; 50K”).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/0*5CDzYwRXi2Fyp0gN.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/0*8jzL8x-8iFNzLd3M.png" /></figure><p>To see more documentation for interpret models result <a href="https://azure.microsoft.com/en-us/documentation/articles/machine-learning-evaluate-model-performance/">see here.</a></p><p><strong>5- Finished experiment</strong><br>The image below represent the entire experiment ready to run.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/0*LeRVdfpf5udKaBde.png" /></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=aebcbf4ecc36" width="1" height="1"><hr><p><a href="https://engineering.hexacta.com/machine-learning-classification-aebcbf4ecc36">Machine Learning — Classification</a> was originally published in <a href="https://engineering.hexacta.com">Hexacta Engineering</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[TensorFlow: The open library for deep learning]]></title>
            <link>https://engineering.hexacta.com/tensorflow-the-open-library-for-deep-learning-94684466d3a8?source=rss----a41470515491---4</link>
            <guid isPermaLink="false">https://medium.com/p/94684466d3a8</guid>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[deep-learning]]></category>
            <category><![CDATA[python]]></category>
            <category><![CDATA[tensorflow]]></category>
            <category><![CDATA[data-science]]></category>
            <dc:creator><![CDATA[Emanuel]]></dc:creator>
            <pubDate>Tue, 29 Mar 2016 00:00:00 GMT</pubDate>
            <atom:updated>2018-03-28T18:33:26.976Z</atom:updated>
            <content:encoded><![CDATA[<p><em>After </em><a href="https://deepmind.com/alpha-go.html"><em>AlphaGo</em></a><em> became the first IA to beat a professional player in the GO game and having also beaten the world’s champion in the last days, it seems as if the issue of “artificial neural networks” regained relevance.</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/650/0*GSgml5oeIoxasOKX.jpg" /></figure><p>And yes, the software used by Google for most artificial intelligence needs was released a few months ago under the Apache 2.0 license and is now available for download and use by anyone (students, researchers, hackers, engineers, developers and many others).</p><p>Its name is <a href="https://www.tensorflow.org/">TensorFlow</a>, it is coded through a Python interface or C / C ++, and can run in various environments: In multi CPUs, in video plates, in cloud servers or on mobile devices with Android and IOS.</p><p>In this blog, the intention is not to enter into the code of it, but to rather make a theoretical introduction to such a deep topic that the expression <em>deep learning</em> will remain short to describe it. If what is sought is code, you can always consult <a href="https://www.tensorflow.org/versions/r0.7/get_started/index.html">TensorFlow’s quick guide</a> on their official website.</p><h3>Artificial learning?</h3><p>Artificial learning! One of the most novel and unexplored areas of computer science. However, there are already some software products that can do this sort of thing:<a href="http://caffe.berkeleyvision.org/"> Caffe</a>, <a href="http://deeplearning4j.org/">Deeplearnig4j,</a> <a href="http://opennn.cimne.com/">OpenNN</a> and <a href="http://torch.ch/">Torch</a>. In any case, if you still do not know where we stand, here is a list of concepts to help us come into topic:</p><ul><li>Artificial neural network: it is a computing paradigm that attempts to solve problems from a different approach. Usually they are made up of many input nodes, one or more layers of intermediate nodes and multiple output nodes. To keep things simple, let’s say that each input node can emit a value between 0 and 1, multiplied by a variable weight “w”. Finally a threshold “b” is defined for the output nodes and if the sum of all entries exceed that threshold, then that output would classify as positive defined.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/560/0*migN8NiFYS_VifV_.png" /></figure><ul><li>Genetic algorithm: they are algorithms that are based on feedback from their results to make improvements in design. This part is key since in artificial neural networks there are variables that are at the mercy of the algorithm: <strong>the “w” weights</strong>.</li><li>Deep learning: the process by which computers learn to perform a task, given a set of things that are defined as true and refine their neural network, to then generalize and apply them to new situations. As it can be seen, the programmer is not the one who defines how the circuit is formed, but he or she provides the necessary mechanisms to evolve it to its most optimal way through many attempts.</li></ul><h3>Where I can find TensorFlow?</h3><p>While Google has used <em>deep learning</em> almost since its beginning with technologies such as <em>prediction API</em> and <em>DistBelief</em> (TensorFlow’s previous generation) now this renowned software library is used in many popular applications (and where integration is so natural that we forget it exists).</p><p>Here are some examples:</p><ul><li>User behavior: RankBrain is one of the ways that Google directs its search results since October 2015. It can learn which sites are relevant to the user depending on what links the user clicks on; but it does not do it algorithmically, instead it learns by adjusting its neural network.</li><li>Speech recognition and natural language processing: Voice-to-text conversion obtained from thousands of samples spoken with their transcripts.</li><li>Translator: the translator learns languages from hundreds of texts with official translation. Sometimes it uses the user’s recommendations to improve their work.</li><li>Predictive text: by using the self-correction mode or writing textual keyboards on Android devices. The words that are recommended depend on the user and vocabulary.</li><li>Image recognition: Try searching for “red car” in the search for images. How can there be so many red cars on the Internet? The truth is that most of the images that are presented are not called “red_car.jpg”, but TensorFlow is doing its job by recognizing “red” and “car” abstractions by looking at the pictures.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/526/0*wFfz0KPRGTrRfzgV.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/252/0*Oy5sEXsSKybHdZjW.jpg" /></figure><h3>How does it all work?</h3><p>TensorFlow represents information as a multidimensional array (not very surprisingly called tensor). In this arrangement, the data available overturns and usually there is a dimension reserved for the number of samples with which it will train. So, if we have for example 5<a href="http://yann.lecun.com/exdb/mnist/">5,000 digits written by hand</a> to recognize images of 28×28 pixels, then we fabricate an array of 55000x28x28.</p><p>The necessary neural layers are then deployed to solve the problem and operations to be performed are determined. All these operations can be viewed using <a href="https://www.tensorflow.org/versions/r0.7/how_tos/graph_viz/index.html#tensorboard-graph-visualization">TensorBoard</a>, a tool that provides a visual interface. The more layers, the greater the need for processing; that is why each section of the graph can run on different processing units.<br> After the IA has been trained, you can get obtain very interesting displays such as the ones in following boxes that show the evidence for (blue) and against (red) that the line representing the digit shown:</p><p>And here is an example of how the source code would look like:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/606985674213d4f5a122e749ac2d9d61/href">https://medium.com/media/606985674213d4f5a122e749ac2d9d61/href</a></iframe><h4>More useful links:</h4><p>MNIST dataset Views: <a href="http://colah.github.io/posts/2014-10-Visualizing-MNIST/">http://colah.github.io/posts/2014-10-Visualizing-MNIST/</a><br> Paper on TensorFlow: <a href="http://download.tensorflow.org/paper/whitepaper2015.pdf">http://download.tensorflow.org/paper/whitepaper2015.pdf</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=94684466d3a8" width="1" height="1"><hr><p><a href="https://engineering.hexacta.com/tensorflow-the-open-library-for-deep-learning-94684466d3a8">TensorFlow: The open library for deep learning</a> was originally published in <a href="https://engineering.hexacta.com">Hexacta Engineering</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Pandas by example: columns]]></title>
            <link>https://engineering.hexacta.com/pandas-by-example-columns-547696ff78dd?source=rss----a41470515491---4</link>
            <guid isPermaLink="false">https://medium.com/p/547696ff78dd</guid>
            <category><![CDATA[python]]></category>
            <category><![CDATA[data-visualization]]></category>
            <category><![CDATA[data-science]]></category>
            <category><![CDATA[big-data]]></category>
            <category><![CDATA[machine-learning]]></category>
            <dc:creator><![CDATA[Rodrigo Pombo]]></dc:creator>
            <pubDate>Tue, 27 Feb 2018 17:18:52 GMT</pubDate>
            <atom:updated>2018-02-27T17:18:52.998Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*WlhrFbZOAf-52fh1-CtCUg.jpeg" /></figure><p>Let’s review the many ways to do the most common operations over dataframe columns using pandas.</p><pre>import pandas as pd</pre><h4>Adding columns to a dataframe</h4><p>The three most popular ways to add a new column are: indexing, loc and assign:</p><pre>df = pd.DataFrame({&quot;A&quot;: [1,2,3],<br>                   &quot;B&quot;: [2,4,8]})<br><br>df[&quot;C&quot;] = [1,2,3]<br>df.loc[:, &quot;D&quot;] = [1,2,3]<br>df = df.assign(E=[1,2,3])<br>df</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/317/1*S-30x19MN3V5UO6-KTQztw.png" /></figure><p>Indexing is usually the simplest method for adding new columns, but it gets trickier to use together with chained indexing. It may add the column to a copy of the dataframe instead of adding it to the original. When this happens pandas will show a warning:</p><pre>df = pd.DataFrame({&quot;A&quot;: [1,2,3],<br>                   &quot;B&quot;: [2,4,8]})</pre><pre>df[df[&quot;A&quot;] &lt; 3][&quot;C&quot;] = 100<br>df</pre><blockquote>SettingWithCopyWarning:<br>A value is trying to be set on a copy of a slice from a DataFrame.<br>Try using .loc[row_indexer,col_indexer] = value instead</blockquote><blockquote>See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy<br> after removing the cwd from sys.path.</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/218/1*Z4T7bKKN8eGCVBBZxE_KeQ.png" /></figure><p>To avoid those cases, it’s better to use loc:</p><pre>df = pd.DataFrame({&quot;A&quot;: [1,2,3],<br>                   &quot;B&quot;: [2,4,8]})</pre><pre>df.loc[df[&quot;A&quot;] &lt; 3, &quot;C&quot;] = 100<br>df</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/271/1*Ph1tLF_r7I67FGBYMeBTGQ.png" /></figure><p>loc has two limitations: it mutates the dataframe in-place and it can&#39;t be used with method chaining. If that&#39;s a problem for you, use assign:</p><pre>df = pd.DataFrame({&quot;A&quot;: [1,2,3],<br>                   &quot;B&quot;: [2,4,8]})</pre><pre>df = df.assign(C=[1,2,3]).assign(D=4)<br>df</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/303/1*DZAgztypjR3jCOs19D8acw.png" /></figure><p>assign is particularly useful when you want to create a new column based on a column from an intermediate dataframe. You can pass a lambda to assign to get the intermediate dataframe:</p><pre>df = pd.DataFrame({&quot;A&quot;: [1,2,3],<br>                   &quot;B&quot;: [2,4,8]})</pre><pre>df = df.assign(C=[1,2,3]).assign(D=lambda idf: idf[&quot;C&quot;] * 2)<br>df</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/341/1*vrHYBM9IFOGGnOYhd2QetQ.png" /></figure><p>In the previous examples the column name is fixed, but you can also use variable column names:</p><pre>df = pd.DataFrame({&quot;A&quot;: [1,2,3],<br>                   &quot;B&quot;: [2,4,8]})</pre><pre>my_column_name = &quot;C&quot;<br>another_name = &quot;D&quot;<br>df = df.assign(**{my_column_name: [1,2,3], another_name: 100})<br>df</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/359/1*_YdG4xnX3Q6Tv5AEtRLxnw.png" /></figure><p>Another option, when you need to insert a column in a specific location, you can use insert:</p><pre>df = pd.DataFrame({&quot;A&quot;: [1,2,3],<br>                   &quot;B&quot;: [2,4,8]})</pre><pre>df.insert(loc=1, column=&quot;C&quot;, value=[1,2,3])<br>df</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/281/1*rc-BqGGwwSIZDUp7EAs2MQ.png" /></figure><p>Finally, you can also use concat to add a new column:</p><pre>df = pd.DataFrame({&quot;A&quot;: [1,2,3],<br>                   &quot;B&quot;: [2,4,8]})</pre><pre>new_column = pd.Series([1,2,3])<br>df = pd.concat([df, new_column.rename(&quot;C&quot;)], axis=1)<br>df</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/269/1*1p7PYXIiPrrrc4j4XPrsSg.png" /></figure><p>No matter what method you use, a common mistake is adding a column with a different index:</p><pre>df = pd.DataFrame({&quot;A&quot;: [1,2,3],<br>                   &quot;B&quot;: [2,4,8]},<br>                  index=[0,1,2])</pre><pre>new_column = pd.Series([1,2,3],index=[2,3,4])<br>df[&quot;C&quot;] = new_column<br>df</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/284/1*l7u1iyIyQbhAMaw95niUsw.png" /></figure><p>If you don’t care about the indexes and just want to add the column using the current items order, you can use the values array:</p><pre>df = pd.DataFrame({&quot;A&quot;: [1,2,3],<br>                   &quot;B&quot;: [2,4,8]},<br>                  index=[0,1,2])</pre><pre>new_column = pd.Series([1,2,3],index=[2,3,4])<br>df[&quot;C&quot;] = new_column.values<br>df</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/292/1*eNA_kTMCCNmqdt_kX6YwXQ.png" /></figure><h4>Renaming columns</h4><p>The easiest way to rename columns is:</p><pre>df = pd.DataFrame({&quot;A&quot;: [1,2,3],<br>                   &quot;B&quot;: [2,4,8]})<br><br>df = df.rename(columns={&quot;A&quot;:&quot;X&quot;, &quot;B&quot;:&quot;Y&quot;})<br>df</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/248/1*h_wEWAWozi2Y13fEr4yxhw.png" /></figure><p>If you need to do something more complex with the name you can pass a lambda to rename:</p><pre>df = pd.DataFrame({&quot;A&quot;: [1,2,3],<br>                   &quot;B&quot;: [2,4,8]})</pre><pre>df = df.rename(columns=lambda cname: cname + &quot;_&quot; + cname)<br>df</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/302/1*LDhA3Uvx8w69TuAEfGLifg.png" /></figure><p>You can also manipulate columns directly:</p><pre>df = pd.DataFrame({&quot;A&quot;: [1,2,3],<br>                   &quot;B&quot;: [2,4,8]})</pre><pre>df.columns = &quot;column-&quot; + df.columns.str.lower()<br>df</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/411/1*ck5LikQbQ2S3QGErb4Dvmw.png" /></figure><h4>Changing columns order</h4><p>You can change the order of columns by explicitly listing each column:</p><pre>df = pd.DataFrame({&quot;A&quot;: [1,2,3],<br>                   &quot;B&quot;: [2,4,8],<br>                   &quot;C&quot;: [5,5,5]})<br><br>df = df[[&quot;A&quot;, &quot;C&quot;, &quot;B&quot;]]<br>df</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/255/1*0wDQ0m-fs7lM3wdkpB-o1g.png" /></figure><p>For larger dataframes is easier to use list operations to reorder the columns:</p><pre>df = pd.DataFrame({&quot;A&quot;: [1,2,3],<br>                   &quot;B&quot;: [2,4,8],<br>                   &quot;C&quot;: [5,5,5]})</pre><pre>cols = df.columns.tolist()<br>column_to_move = &quot;C&quot;<br>new_position = 1</pre><pre>cols.insert(new_position, cols.pop(cols.index(column_to_move)))<br>df = df[cols]<br>df</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/271/1*6hhyzrGfxXpdlbN1MziONA.png" /></figure><h4>Deleting columns</h4><p>You can use dict operations, like del and pop, to remove columns:</p><pre>df = pd.DataFrame({&quot;A&quot;: [1,2,3],<br>                   &quot;B&quot;: [2,4,8],<br>                   &quot;C&quot;: [5,5,5]})<br>del df[&quot;B&quot;]<br>C = df.pop(&quot;C&quot;)<br><br>df</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/213/1*Bz-HqUX1W3yMm9tFDBN_2Q.png" /></figure><p>For multiple columns (or for keeping the original dataframe intact) you can use drop:</p><pre>df = pd.DataFrame({&quot;A&quot;: [1,2,3],<br>                   &quot;B&quot;: [2,4,8],<br>                   &quot;C&quot;: [5,5,5]})</pre><pre>df = df.drop([&quot;B&quot;, &quot;C&quot;], axis=1)<br>df</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/223/1*hFWomClsWqFbvcAXBO1_Ew.png" /></figure><p>You can also use columns to select the columns to drop:</p><pre>df = pd.DataFrame({&quot;A1&quot;: [1,2,3],<br>                   &quot;B2&quot;: [2,4,8],<br>                   &quot;C2&quot;: [5,5,5]})</pre><pre>cols_to_drop = [cname for cname in df.columns if cname.endswith(&quot;2&quot;)]<br>df = df.drop(cols_to_drop, axis=1)<br>df</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/253/1*X16tyN0UtAZbnzTWfberaA.png" /></figure><p>Sometimes is easier to select the columns you want to keep:</p><pre>df = pd.DataFrame({&quot;A1&quot;: [1,2,3],<br>                   &quot;B2&quot;: [2,4,8],<br>                   &quot;C2&quot;: [5,5,5]})</pre><pre>cols_to_keep = [cname for cname in df.columns if cname.endswith(&quot;2&quot;)]<br>df = df[cols_to_keep]<br>df</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/292/1*-i65Pc-HSlWbBuxWpwxSHQ.png" /></figure><p>Thanks for reading.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=547696ff78dd" width="1" height="1"><hr><p><a href="https://engineering.hexacta.com/pandas-by-example-columns-547696ff78dd">Pandas by example: columns</a> was originally published in <a href="https://engineering.hexacta.com">Hexacta Engineering</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Infographic: Timeline of software development methodologies]]></title>
            <link>https://engineering.hexacta.com/infographic-timeline-of-software-development-methodologies-f1106d5d5c49?source=rss----a41470515491---4</link>
            <guid isPermaLink="false">https://medium.com/p/f1106d5d5c49</guid>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[agile]]></category>
            <category><![CDATA[scrum]]></category>
            <dc:creator><![CDATA[Tomas Henseler]]></dc:creator>
            <pubDate>Mon, 05 Feb 2018 00:00:00 GMT</pubDate>
            <atom:updated>2018-02-21T18:53:19.771Z</atom:updated>
            <content:encoded><![CDATA[<h4><strong><em>This is a brief </em>racconto<em> of how software development methodologies have evolved</em></strong><em> in order to understand the changes we are experiencing better.</em></h4><p>I have recently attended an Agile conference in Buenos Aires where I had a good time <strong>sharing experiences and knowledge about the Agile methodologies</strong> world in software development with some colleagues in the industry (among Scrum coaches, architects, developers, etc.).</p><p>As usual, during a coffee break, an<strong> interesting debate</strong> with one of the attendants emerged. <strong>Is Scrum better than Waterfall methodology? Are iterations actually good for learning from mistakes? Did Scrum invent the iterative methodology?</strong> Do mistakes cost more when using Waterfall methodology? What happened during the years between the birth of one methodology and another?</p><p>Certainly, these questions that came up could give rise to a long conversation; however, <strong>we concluded that one of the problems of software engineering is that, in our discipline, we forget the lessons of the past many times</strong>, conceiving everything new as good and everything old as bad.</p><p>In the article <a href="https://blog.daftcode.pl/hype-driven-development-3469fc2e9b22"><em>Hype Driven Development</em></a>, <strong>Marek Kirejczyk commented on one of the components of this problem</strong>. We could all agree that software engineering is a very dynamic discipline that requires constant updating. Nevertheless,<strong> it is important to learn from history and experience in order to avoid making the mistakes of the past</strong>. This is not for nothing;<strong> it is one of the cornerstones of Agile thinking</strong>.</p><p>With this in mind, <strong>I decided to do a small, perhaps arbitrary, <em>racconto </em>(statement) of how software methodologies have evolved</strong> in order to understand the changes we are experiencing better.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/960/0*0pZ23369yF9T3zxH.jpg" /></figure><p><strong>1910</strong> — Henry Gantt invents the diagram for project management. Along with Frederick Taylor, they intended to improve industrial efficiency by defining processes to perform repetitive tasks:</p><p><em>“It is only through enforced standardization of methods, enforced adoption of the best implements and working conditions, and enforced cooperation that this faster work can be assured.</em></p><p><em>And the duty of enforcing the adoption of standards and enforcing this cooperation rests with management alone”.</em></p><p><strong>1916:</strong> Henri Fayol introduces concepts such as division of work, unity of command, and centralization of decisions.</p><p><strong>1927–1932: </strong>Elton Mayo carries out the Hawthorne experiment, where he concludes, among other things, that the team productivity gain occurred because of the motivational effect on the workers from the interest being shown to them.</p><p><strong>1953: </strong>The word software was coined as a prank.</p><p><strong>1956:</strong> First formal description of Waterfall methodology made by Herbert D. Benington at a symposium on advanced programming methods for digital computers on June 29.</p><p><strong>1976: </strong>The earliest use of the term <em>Waterfall</em> may have been in a 1976 paper by Bell and Thayer.</p><p><strong>1985:</strong> The United States Department of Defense standardizes this methodology (Waterfall) and defines it as a standard for its software development providers. This standardization defined 6 stages: Preliminary Design, Detailed Design, Development and Unit Testing, Integration, and Testing.</p><p><strong>1986:</strong> Barry Boehm describes the process in Spiral. It introduces the iterative development concept to mitigate risks.</p><p><strong>1986:</strong> Fred Brooks publishes his paper <em>No Silver Bullet</em> where he explains the difficulties inherent in software development. His book, <em>The Mythican Man-Month,</em> becomes the foundational text for software engineering. In 1999, Brooks wins the Turing award for his contributions.</p><p><strong>1986:</strong> Takeuchi and Nonaka introduce the term Scrum for the first time in their <a href="https://hbr.org/1986/01/the-new-new-product-development-game"><strong>article</strong></a><strong>, <em>New New Product Development Game</em></strong>. In their work, the authors claim that Scrum is an approach to organizational knowledge creation, which is particularly good for bringing innovation in a continuous and incremental way.</p><p><strong>1990: </strong>Ken Schwaber used what would become Scrum at his company: Advanced Development Methods. Meanwhile, Jeff Sutherland developed a similar approach, referring to it with the single word Scrum.</p><p><strong>1995:</strong> As a result of their experience, Schawaber and Shuterland publish the paper <em>Scrum methodology</em>.</p><p><strong>1996–1998:</strong> Rational Software Company develops its unified, iterative, and incremental software process. Focused on architecture and guided by use cases, this process becomes the standard of the industry.</p><p><strong>1999:</strong> Kent Beck publishes <em>Extreme Programming Explained,</em> setting the stages of the Agile revolution.</p><p><strong>2001:</strong> The Agile Manifesto is published:</p><p><em>We are uncovering better ways of developing software by doing it and helping others do it.</em></p><p><em>Through this work we have come to value:</em></p><p><em>Individuals and interactions over processes and tools Working software over comprehensive documentation Customer collaboration over contract negotiation</em></p><p><em>Responding to change over following a plan.</em></p><p><strong>2003:</strong> Tom and Mary Poppendieck publish their book <em>Lean Software Development,</em> a translation for the software industry of Toyota’s <em>Just in Time</em> system.</p><p><strong>2008:</strong> During the Agile conference of 2008, Bob Martin proposes a fifth value to the Agile Manifesto: <em>Craftmanship over Crap</em>. A year later, the principles of the movement known as <a href="http://manifesto.softwarecraftsmanship.org/">Software Craftmanship</a> are established. The metaphor of the system professional is replaced, going from Engineer to “Medieval Artisan”.</p><p><strong>2009:</strong> The term DevOps becomes popular in a series of “<a href="https://www.devopsdays.org/">devopsdays</a>”.</p><p><strong>2010:</strong> David Anderson publishes his book <em>Kanban</em>, a methodology that is also based on Toyota’s Production System.</p><ul><li><strong>Today:</strong> DevOps is gaining more and more ground with tools like Docker, Puppet, and Chef. The borders between development and operations begin to become blurred. Agile frameworks have scalability problems, leading to new implementations such as <a href="https://less.works/">Less</a> (Large-Scale-Scrum) and <a href="http://www.scaledagileframework.com/">Safe</a> (Scaled Agile Framework).</li></ul><p>And so, we continue looking for the silver bullet in this awesome discipline.</p><h3>To Sum Up</h3><p>The software industry is very dynamic and demands constant updating. Almost by definition, it is a field that is constantly looking to the future. In this context, <strong>it is normal for the past to be overlooked and with it, the opportunity to learn from valuable lessons</strong>.</p><blockquote>“Some of the best lessons we ever learn are learned from past mistakes. The error of the past is the wisdom and success of the future”. — Dale Turner-</blockquote><p><em>Comments? </em><a href="http://www.hexacta.com/contact/"><em>Contact us</em></a><em> for more information. We’ll quickly get back to you with the information you need.</em></p><p><em>Originally published at </em><a href="http://www.hexacta.com/2018/02/05/timeline-of-software-development-methodologies/"><em>www.hexacta.com</em></a><em> on February 5, 2018.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f1106d5d5c49" width="1" height="1"><hr><p><a href="https://engineering.hexacta.com/infographic-timeline-of-software-development-methodologies-f1106d5d5c49">Infographic: Timeline of software development methodologies</a> was originally published in <a href="https://engineering.hexacta.com">Hexacta Engineering</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>