This is an experiment in using the Kotlin kernel for Jupyter

In [11]:
// two "supported" packages, we can skip the full dependency & import boilerplate
%use lets-plot, krangl
In [2]:
// csv is courtesy of pro-football-reference: https://www.pro-football-reference.com/years/NFL/passing.htm
val dfPassing = DataFrame.readCSV("nfl_passing.csv")
dfPassing
Out[2]:
RkYearTmsCmpAttCmp%YdsTDTD%IntInt%Y/AAY/AY/CY/GRateSkSkYdsNY/AANY/ASk%
12020322884432966.6305102185.0942.27.57.511.2250.196.527818396.626.76.0
2201932113311785363.51203017974.54102.37.27.111.4235.090.4127686106.296.26.7
3201832114621767164.91217378474.84192.47.47.311.4237.892.9128185306.426.36.8
4201732108561748862.11148707414.24302.57.06.811.3224.486.9119578106.155.96.4
5201632115261829563.01236397864.34152.37.27.011.4241.589.3111872256.376.25.8
6201532115271829863.01248438424.64362.47.37.111.5243.890.2118778506.416.36.1
7201432112001787962.61212478074.54502.57.27.011.5236.888.9121276516.356.16.3
8201332111021813661.21206268044.45022.87.16.811.6235.686.0129585516.215.96.7
9201232108331778860.91184187574.34682.67.16.711.6231.385.6116975336.255.96.2
10201132104641741060.11176017454.35062.97.26.712.0229.784.3118877296.325.96.4
11201032104911726960.81134507514.35113.07.06.511.5221.684.1113075146.175.76.1
12200932103721703360.91118517104.25253.17.06.411.5218.583.0110170666.175.66.1
13200832100811652661.01081776463.94652.86.96.511.4211.383.2103665896.165.75.9
14200732104251704561.21097227204.25343.16.96.311.2214.382.6110271526.055.56.1
1520063297961638959.81048616484.05203.26.96.211.5204.880.4116474165.975.46.6
1620053297901646459.51041686443.95063.16.86.211.4203.580.1118275535.905.36.7
1720043297721635459.81077977324.55243.27.16.511.8210.582.8119675416.145.66.8
1820033296951649358.81026286544.05383.36.66.011.3200.478.3109268395.845.26.2
19200232103141729259.61086616944.05283.16.76.111.3212.280.4117575405.885.36.4
2020013195421618159.01020806353.95453.46.86.011.5205.878.5119675595.875.26.9

... only showing top 20 rows

In [3]:
val mapPassing = dfPassing.filter { (it["Year"] lt 2020) AND (it["Year"] gt 1989) }.toMap()
mapPassing
Out[3]:
{Rk=[Ljava.lang.Integer;@ffbdb79, Year=[Ljava.lang.Integer;@67ea360f, Tms=[Ljava.lang.Integer;@3c9a8c66, Cmp=[Ljava.lang.Integer;@16abeca6, Att=[Ljava.lang.Integer;@475add19, Cmp%=[Ljava.lang.Double;@7136d1b3, Yds=[Ljava.lang.Integer;@19a78a4f, TD=[Ljava.lang.Integer;@50208b01, TD%=[Ljava.lang.Double;@41833609, Int=[Ljava.lang.Integer;@67fdcc3, Int%=[Ljava.lang.Double;@232fcbb1, Y/A=[Ljava.lang.Double;@77833456, AY/A=[Ljava.lang.Double;@2f6867d1, Y/C=[Ljava.lang.Double;@57893f3b, Y/G=[Ljava.lang.Double;@aa60438, Rate=[Ljava.lang.Double;@6469a0be, Sk=[Ljava.lang.String;@853050d, SkYds=[Ljava.lang.String;@163d83db, NY/A=[Ljava.lang.String;@2c80d2e0, ANY/A=[Ljava.lang.String;@545fb9e, Sk%=[Ljava.lang.String;@152eed56}
In [4]:
val p = lets_plot(mapPassing) { x = "Year"; y = "AY/A" } + ggsize(640, 240)
p + geom_bar(stat=Stat.identity) +
    ggtitle("Avg Adjusted Yds/Attempt per NFL regular season")
Out[4]:
In [5]:
val p = lets_plot(mapPassing) { x = "Year"; y = "Rate" } + ggsize(640, 240)
p + geom_bar(stat=Stat.identity) +
    ggtitle("Total Combined Passer Rating per NFL regular season")
Out[5]:
In [6]:
val dfPassingRanges = dfPassing
    .filter { (it["Year"] lt 2020) AND (it["Year"] gt 1989) }
    .addColumn("YearRange") { it["Year"].map<Double>{ floor(it.div(5.0)).times(5).toInt() }}
    .addColumn("Years") { it["YearRange"].map<Int>{ "$it - ${it + 4}" }}

val mapPassingRanges = dfPassingRanges
    .select({ listOf("Year", "AY/A", "Rate", "YearRange", "Years") })
    .groupBy("YearRange", "Years")
    .summarize(
        "mean_AY/A" to { it["AY/A"].mean(removeNA = true) },
        "mean_Rate" to { it["Rate"].mean(removeNA = true) }
    ).toMap()
    
val xlimits = listOf("1990 - 1994", "1995 - 1999", "2000 - 2004", "2005 - 2009", "2010 - 2014", "2015 - 2019")
In [7]:
val p = lets_plot(mapPassingRanges) { x = "Years"; y = "mean_AY/A" } + ggsize(720, 240)
p + geom_bar(stat=Stat.identity) + scale_x_discrete(limits = xlimits) +
    scale_y_continuous(limits = Pair(4.0, 8.0)) +
    ggtitle("Average Adjusted Yards/Attempt per NFL regular season")
Out[7]:
In [8]:
val p = lets_plot(mapPassingRanges) { x = "Years"; y = "mean_Rate" } + ggsize(720, 240)
p + geom_bar(stat=Stat.identity) + scale_x_discrete(limits = xlimits) +
    ggtitle("Total Combined Passer Rating per NFL regular season")
Out[8]:
In [ ]: