<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ian Greengross</title>
    <description>The latest articles on DEV Community by Ian Greengross (@iangreengross).</description>
    <link>https://dev.to/iangreengross</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F225318%2F80db882e-651b-4a6a-b2e0-b335a1d723f0.jpg</url>
      <title>DEV Community: Ian Greengross</title>
      <link>https://dev.to/iangreengross</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/iangreengross"/>
    <language>en</language>
    <item>
      <title>You Need Data to Analyze Data</title>
      <dc:creator>Ian Greengross</dc:creator>
      <pubDate>Fri, 22 Nov 2019 05:49:59 +0000</pubDate>
      <link>https://dev.to/iangreengross/you-need-data-to-analyze-data-19bd</link>
      <guid>https://dev.to/iangreengross/you-need-data-to-analyze-data-19bd</guid>
      <description>&lt;p&gt;So, my project for the ChiPy Mentorship program is: take the universe of NFL Running Backs and try to predict their contract value for their 2nd NFL contract. The reason for only predicting the 2nd NFL contract is that their first NFL contract is based on a mostly pre-determined system, where their 2nd contract is based off their performance in the NFL.&lt;/p&gt;

&lt;p&gt;Unfortunately, this means that our number of samples to analyze in the post-2011 Collective Bargaining Agreement (CBA) era is approximately 100. (Side note - in 2011 a new 10 years CBA was negotiated which somewhat altered the system, so only contracts negotiated since then would be apples to apples).&lt;/p&gt;

&lt;p&gt;As you will see below, when you only have 100 samples, using just about any method to analyze the data in order to predict a contract from a validation sample becomes almost a fool's errand. As of this post, and the methods will be more fully discussed below, we (my mentor and I) have tried: multiple linear regression, principle component analysis, decisions trees and K nearest neighbor. In addition, just on my end, I have also tried banging my head against the wall. More than once.&lt;/p&gt;

&lt;p&gt;Ok, before I walk you through the methods we tried, you should know a little more about the data itself. For those 100 samples contracts, we have approximately 50 features of data for each one. Some are the 'normal' statistics people would associate with NFL running backs - total rushing yards for a given season, total receiving yards for a given season, total rushing touchdowns for a given season, etc. Some are 'advanced' statistics for running backs - yards per route run, yards after contact, tackles avoided and several others. Across each contract there about 50 statistical categories.&lt;/p&gt;

&lt;p&gt;Multiple Linear Regression&lt;/p&gt;

&lt;p&gt;So, before I would just willy nilly send all 50 features through linear regression, my mentor suggested just plotting a simple relationship plot with r^2 on the plot for each feature to see if that feature had any realistic chance of being relevant to the outcome. So, I did:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aLKTTnpW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/hy8a18qn2v4o4g1z5560.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aLKTTnpW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/hy8a18qn2v4o4g1z5560.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;cols_we_want is just a list of the column names that I wanted to check their relevance.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That code gave me 50 .png files that look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BAvXsEdc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/z53icygtssq0w0oahfoz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BAvXsEdc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/z53icygtssq0w0oahfoz.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And with just a little bit of code, 50 features became about 8 - all of which I could have guessed before the computer did its math because they are the features which are used in the 'real world' in which these contracts are negotiated.&lt;/p&gt;

&lt;p&gt;However, just to make sure that those features were indeed the most relevant, a little RFE (Recursive Feature Elimination - which basically ranks the features in terms of their relevance for predicting the outcome) was necessary:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IyupckQ3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/3oxk38eb3g5wr4isqb0b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IyupckQ3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/3oxk38eb3g5wr4isqb0b.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Which then gave me a listing of how relevant each feature was to the outcome - several columns rated as a '1', then '2' and so on - with a 1 being most relevant.&lt;/p&gt;

&lt;p&gt;Brimming with confidence that our most relevant features would absolutely predict outcomes that were right on the money, I wrote the code to run linear regression with the level '1' features, then the level '1' and '2' features and so on:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Z5UDce5p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/pde7hh58k6bd807ne8bl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Z5UDce5p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/pde7hh58k6bd807ne8bl.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--q40tHwhc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/ngrsegvv4z3okd82c8cy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--q40tHwhc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/ngrsegvv4z3okd82c8cy.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Unfortunately, this is when the fears of my mentor were first realized: Not having enough samples means not getting accurate predictions.&lt;/p&gt;

&lt;p&gt;However, fear not dear reader, the world of data analysis has many other methods to try. And next on the list was PCA (Principal Component Analysis) - which to use a technical term - mushes the features together into as many or as little a number you want:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zd0rBjCX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/10muc947qb8x89kpl3hz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zd0rBjCX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/10muc947qb8x89kpl3hz.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Unfortunately, once again not having enough samples means not getting accurate predictions.&lt;/p&gt;

&lt;p&gt;But, where one door closes, another opens. Welcome to decision trees:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NlLkPwV3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/q6wsotcvgtlh4vcl6ftc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NlLkPwV3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/q6wsotcvgtlh4vcl6ftc.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, I'm sure by now you have guessed the theme of this post - not having enough samples means not getting accurate predictions.&lt;/p&gt;

&lt;p&gt;Time to call in K nearest neighbor off the bench....which, funny enough should approximate what happens in the 'real world' anyway. When I negotiate a contract for a player I represent, I look at the other players at his position whom I believe to be the most statistically similar and use their contracts as a baseline for the contract I want for my player.&lt;/p&gt;

&lt;p&gt;Tune in at the final presentations on December 12 to see how it all turns out. (If you miss it, don't worry - I'll make a final post as well).&lt;/p&gt;

</description>
      <category>pca</category>
      <category>knn</category>
      <category>trees</category>
      <category>chipymentorship</category>
    </item>
    <item>
      <title>Data is now a little less hard</title>
      <dc:creator>Ian Greengross</dc:creator>
      <pubDate>Fri, 18 Oct 2019 03:53:01 +0000</pubDate>
      <link>https://dev.to/iangreengross/data-is-now-a-little-less-hard-aej</link>
      <guid>https://dev.to/iangreengross/data-is-now-a-little-less-hard-aej</guid>
      <description>&lt;p&gt;Previously I wrote about how Data is hard. Well, thanks to my mentor, Data is now a little less hard.&lt;/p&gt;

&lt;p&gt;In these last few weeks, I have become an 'expert' at culling out data by using whole columns, rather than using the good old 'for' loop. For example, in order to get the data of how successful an NFL Running Back is on first down, I used the following code:&lt;/p&gt;

&lt;p&gt;all_rbs = data.loc[(data['play_type']=='run') &amp;amp; (data['down'] == 1) &amp;amp; (data['ydstogo'] == 10)].groupby(by='rusher_player_name')[['epa', 'success','yards_gained']].mean()&lt;/p&gt;

&lt;p&gt;Which gave me some output that looked like this:&lt;br&gt;
Joe.Runningback  0.042594  0.57182   4.63&lt;/p&gt;

&lt;p&gt;Except that it output one row for each running back in the dataset of all NFL plays from an entire NFL season.&lt;/p&gt;

&lt;p&gt;However, given my newfound merge skills, I was then able to take that list of data and merge it into my main data table which has a record for each running back so that I now had 3 new columns for how a running back performed on 1st and 10: Expected Points Added (per play), Success rate, and average yards per attempt.&lt;/p&gt;

&lt;p&gt;I was able to repeat this process many times over so that my final data table had 72 points of data (or features) per running back.&lt;/p&gt;

&lt;p&gt;And, now, data was a little less hard.  That is, until we moved forward to the first step in turning that data into a model that can actually predict something.&lt;/p&gt;

&lt;p&gt;Once again, my mentor took my hand and taught me the basics so that I could start using the data.&lt;/p&gt;

&lt;p&gt;Rather than just run all of the features through regression (or any other) analysis, he suggested that I first take each feature and run a regression plot against our target to see if the feature has any meaning in the first place. Since I had no idea what to do, he sent me some links and talked me through the general idea. This led to me writing this code, all by myself:&lt;/p&gt;

&lt;p&gt;from scipy import stats&lt;br&gt;
import pandas as pd&lt;br&gt;
import seaborn as sns&lt;br&gt;
import matplotlib.pyplot as plt&lt;/p&gt;

&lt;p&gt;all_rb = pd.read_excel('rb_all_data_a.xlsx')&lt;br&gt;
all_rb.set_index('Index', inplace=True)&lt;br&gt;
cols_we_want = []&lt;/p&gt;

&lt;p&gt;for a in range(18,90):&lt;br&gt;
    col_name = all_rb.columns[a]&lt;br&gt;
    cols_we_want.append(col_name)&lt;/p&gt;

&lt;p&gt;for col in cols_we_want:&lt;br&gt;
    def r2(x, y):&lt;br&gt;
        return stats.pearsonr(x, y)[0] ** 2&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sns.jointplot(x=col, y='Average_Salary', kind="reg", stat_func=r2, data=all_rb)
plt.savefig(f'{col}.png')
plt.close()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And, bingo, bango, bongo, in 20 lines of code, I had 72 regression plots with r^2 listed on each plot so that I could start to weed out those features which would likely prove insignificant.&lt;/p&gt;

&lt;p&gt;Now that the features have been cut down, I'm excited to learn the next step and steps so that we can build a prediction model.&lt;/p&gt;

&lt;p&gt;Principal Component Analysis, here we come....&lt;/p&gt;

&lt;p&gt;To be continued.....&lt;/p&gt;

</description>
      <category>datamerging</category>
      <category>datacleaning</category>
      <category>seaborn</category>
      <category>python</category>
    </item>
    <item>
      <title>Data is hard.</title>
      <dc:creator>Ian Greengross</dc:creator>
      <pubDate>Tue, 17 Sep 2019 19:12:00 +0000</pubDate>
      <link>https://dev.to/iangreengross/data-is-hard-5b3f</link>
      <guid>https://dev.to/iangreengross/data-is-hard-5b3f</guid>
      <description>&lt;p&gt;I understand data. I spent my late teens and early 20's programming in the languages associated with some of the first DOS based relational databases - Paradox and DBase IV.&lt;/p&gt;

&lt;p&gt;So I understand data structure and what data looks like.&lt;/p&gt;

&lt;p&gt;But, when you're trying to merge together data from 4 or 5 different sources, where the only key across all of them is a person's name and that person's name can be used differently in each set (Ian Greengross, I. Greengross, IG 01, etc) - then you need to find a way to get those keys unified.&lt;/p&gt;

&lt;p&gt;And while my project only involves 32 individuals, I didn't want to do it the "cheap way" and just add column and put in my own key manually.&lt;/p&gt;

&lt;p&gt;So - I actually had to think about the data and how to automate giving each individual one unifying key so that when the data is merged, the right data gets assigned to the right individual.&lt;/p&gt;

&lt;p&gt;And, guess what? I did it. It wasn't eloquent, but as Zax says, the first rule is - if it works, then that's good enough (or he tells me something to that effect.)&lt;/p&gt;

&lt;p&gt;Then after I finally had a way to make sure that each person's data would be properly merged into their "record", I then had to deal with the fact that I would be assigning the same info types/column names into each individual's record, but for different years AND those years varied from individual to individual.&lt;/p&gt;

&lt;p&gt;I again wrote another ineloquent script, which again worked. But I would have to rewrite dozens of lines for each script to cover the varying years and rewrite each script every time I moved on to different data tables.&lt;/p&gt;

&lt;p&gt;This is where I had left off when I had my first meeting with my mentor, Matt.&lt;/p&gt;

&lt;p&gt;In all of about 30 minutes, Matt showed me a much more efficient way to join the data and to do it in a way where I really didn't have to re-write anything to cover the shift in year and only had to rewrite some column labels when I moved on to the next data set I wanted to merge.&lt;/p&gt;

&lt;p&gt;In those 30 minutes, Matt saved me from a few hours of rewriting and also helped me to see and think of the data and its structure in a new light.&lt;/p&gt;

&lt;p&gt;Which makes data just a little less hard. &lt;/p&gt;

&lt;p&gt;For now.&lt;/p&gt;

</description>
      <category>chipyproject</category>
    </item>
  </channel>
</rss>
