Improving Performance and Readability of Proportion Calculations with Data Tables

Based on your request, here is a revised version of your code with improvements for performance and readability:

# Calculate proportions for each column except "area_ha"
myColumns <- setdiff(colnames(df)[-1], "area_ha")

for (name in myColumns) {
  # Use dcast to spread the data into columns and sum across rows
  tempdf <- data.table::dcast(df, id ~ name, fun = sum)
  
  # Calculate proportions by dividing by row sums and multiplying by 100
  tempdf[, name := tempdf[name] / rowSums(tempdf[, name], na.rm = TRUE) * 100]
  
  # Merge the temporary data frame with df_fin using the id column
  df_fin <- left_join(df_fin, tempdf, by = "id")
}

This code first defines a list of columns (myColumns) that do not include area_ha. It then iterates over each column in this list. For each column, it uses the dcast function from the data.table package to spread the data into new columns and sums across rows. After calculating the proportions for these new columns, it merges the temporary data frame (tempdf) with df_fin using the id column.

The key improvements in this code are:

  • It uses setdiff to define myColumns, which is more concise than listing each column individually.
  • It uses a for loop to iterate over the columns, which makes it easier to add or remove columns from the calculation without modifying the code.
  • It uses the left_join function instead of right_join to ensure that all observations are preserved in the final data frame.

Note: Make sure you have the data.table package installed. If not, install it with install.packages("data.table").


Last modified on 2025-01-22