I’ve got some sports data in a dataframe I’m playing with that has data on teams throughout a season and I have a number of performance measures I’d like to create cumulative sums for. I found some great suggestions for how to do this here, but I’m struggling with how to conveniently iterate through the columns I want to create because 1) the colon in the name indexing of columns makes things tricky and 2) I’m not sure how to iterate over a list of column names and use those column names to dynamically create new column names for the cumulative sums. Lastly - I would love to do these cumulative sums so that they were lagged by one time period (i.e. the value for the current row is not included in the running total). Here’s what I’ve got so far:
#To Pull the Data
using HTTP, CSV, DataFrames
url = "https://projects.fivethirtyeight.com/nfl-api/nfl_elo.csv"
f38 = CSV.read(HTTP.get(url).body)
For creating just one column of cumulative sums, this works great:
f38[:, :cumul_elo1_pre] .= 0.0
for subdf in groupby(f38,[:team1, :season])
subdf[:, :cumul_elo1_pre] .= cumsum(subdf.elo1_pre)
But if I’d like to do the same thing for all these columns, how can I do it without writing everything out, but iterating?
This works great - just two (hopefully) quick follow-ups on this:
I did this successfully for team 1, but I’d like to do it as well for their opponent (team 2), but modifying the code for team2 would produce the same variable names (it’s iterating over the same column set, just for different grouped dfs). I know I can add another => to the transform statement to specify a new column name, but that doesn’t seem to be possible for a list of variables like I have in cumul_vars here. Any suggestions for how to modifying the resulting column names and be able to execute this for the opposing team as well?
To do the lag, I went simple and just subtracted the current observation’s value from the cumulative variable with the following code, which works just fine but issues a syntax warning and is definitely a very Stata way of doing things. So in the interest of retraining my brain and to learn better coding practices, I wonder if you have advice on a better way to write it.
for var in cumul_vars
full_data["$(var)_cumsum"] = full_data[!, "$(var)_cumsum"] .- full_data[!, "$(var)"]
Please read the syntax warning! You are getting it from the first indexing, you need a [:,"$(var)_cumsum"], notice the new :.
I’m not sure I have a better way of doing that cumsun thing. You could certainly write a small function and use transform, but then you have to have an input like [[:x1, :x2], [:y1, :y2]] .=> f which is complicated.
The indexing behavior is definitely a bit ugly… perhaps that can be fixed with metaprogramming.