*! version 5.0 12jun2026

Title

wxsum -- A command for processing temperature and precipitation data

Syntax

wxsum
stubname
,
type(rain|temp)
ini_month(month)
fin_month(month)
[options]

Required
type(rain|temp) Specify rain for rainfall data or temp for temperature data.

ini_month(month) Initial month of the season (e.g., 05 for May)

fin_month(month) Final month of the season (e.g., 10 for October)

General
ini_day(day) Start day of the season. Default is 01.

fin_day(day) End day of the season. Defaults to the last day of the final month.

lr_years(#) Number of strictly preceding years used to calculate rolling deviations and Z-scores. Default is 10. Max is 50.

rain_threshold(#) Threshold for defining a rainy day. Defaults to 1. Missing rainfall values are excluded from rain-day and dry-spell calculations.

gdd_lo(#) Lower bound for growing degree days calculation (required if type(temp) is used).

gdd_hi(#) Upper bound for growing degree days calculation (required if type(temp) is used).

kdd_base(#) Temperature threshold for calculating Killing Degree Days (KDD) (required if type(temp) is used).

gdd_bin(#) Width of fixed-interval seasonal GDD categories.

gdd_binlo(#) Lower endpoint for regular GDD intervals. Default 0.

gdd_binhi(#) Upper endpoint for regular GDD intervals; values at or above are top-coded.

tmp_bin(#) Total number of daily temperature bin count variables per season. Integer from 1 to 42.

tmp_binlo(#) Lower bound of the temperature range for bin construction. Required with tmp_bin().

tmp_binhi(#) Upper bound of the temperature range for bin construction. Required with tmp_bin().

shape(wide|long) Shape of the final output. Default is wide.

keep(varlist) Variables to keep in the final dataset along with the generated wxsum variables.

save(filename) File path to save the resulting dataset.

Description

wxsum processes remote sensing rainfall and temperature data and outputs useful seasonal statistics. It can be used with either rainfall or temperature data from any source.

Remarks

Data format requirements

The data must be wide, where each location is a row and each column is a daily reading. Daily weather variable names must be the user-supplied prefix followed by yyyymmdd. For example, if the prefix is rf_, the variable for May 15, 1979 would be rf_19790515.

Command syntax

The general syntax of the command requires specifying a prefix, a data type, and the season's start and end months.

- After the command name, one has to define what variables contain the rain/temperature information by providing their common prefix (stub). For example, if the data contain variables named rf_19790101, rf_19790102, and so on, the prefix supplied to the command is rf_. Variables not beginning with the specified prefix are ignored unless they are retained by using the keep() option.

- Next, one needs to tell the command whether the data is type(rain) or type(temp).

- One then has to select a season to study using the options ini_month(month), fin_month(month), ini_day(day), and fin_day(day). If the day options are not specified, the command dynamically defaults to the true last calendar day of the final month. For example, to choose a season from the middle of March to the middle of June, you would set ini_month(03), fin_month(06), ini_day(15), fin_day(15). The command seamlessly handles seasons that span across calendar years, such as November to February, keeping the data associated with the year the season starts.

- The keep(varlist) option tells the command to keep the variables it creates plus some of the original variables in order to match them with other datasets.

- The save(filename) option tells the program to save the dataset in a given location with a given name.

Long-run averages

Z-scores and deviations from long-run averages are computed strictly against the specified number of preceding lr_years. If there is not enough historical preceding data to satisfy the user-defined lr_years constraint, deviations and z-scores are skipped for those initial years, though standard variables are still generated.

Options

type(temp) processes temperature variables to generate:

- mean daily in a season

- median daily in a season

- variance of daily in a season

- standard deviation of daily in a season

- skew of daily in a season

- max daily in a season

- gdd in a season

- deviations from long run average gdd in a season

- z-score of gdd in a season

- GDD category variable gddcat_YEAR (when gdd_bin() is specified)

- kdd in a season

- deviations from long run average kdd in a season

- z-score of kdd in a season

- daily temperature bin count variables tmpbinXX_YEAR (when tmp_bin() is specified)

type(rain) processes rainfall variables to generate:

- mean daily in a season

- median daily in a season

- variance of daily in a season

- standard deviation of daily in a season

- skew of daily in a season

- mean of monthly rainfall totals in a season

- deviation from long run average of mean monthly rainfall in a season

- z-score of mean monthly rainfall in a season

- total seasonal

- deviation from long run average of total seasonal

- z-score of total seasonal

- number of observed days with rain in a season

- deviation from long run average of rainy days in a season

- z-score of rainy days in a season

- number of observed days without rain in a season

- deviation from long run average of days without rain in a season

- z-score of days without rain in a season

- percentage of days with rain in a season

- deviation from the long run average of percentage of days with rain in a season

- z-score of percentage of days with rain in a season

- length of leading dry spell at the start of a season

- longest mid-season dry spell

- length of trailing dry spell at the end of a season

ini_month(month) specifies the starting month of the season.

fin_month(month) specifies the ending month of the season. Seasons can span across calendar years (e.g., November to February).

ini_day(day) specifies the day the season begins. If not specified, it defaults to 01.

fin_day(day) specifies the day the season ends. If not specified, it dynamically defaults to the exact last day of the final month in the given season, correctly accounting for leap years.

lr_years(#) Sets the rolling window history size for calculating deviations from the long run average. Defaults to 10.

rain_threshold(#) allows the user to define what counts as a rainy day. Default is 1. Missing rainfall values are excluded from rain-day, no-rain-day, percentage, and dry-spell calculations.

gdd_lo(#) specifies the lower temperature threshold for calculating Growing Degree Days.

gdd_hi(#) specifies the upper temperature threshold for calculating Growing Degree Days.

kdd_base(#) specifies the threshold temperature above which to calculate Killing Degree Days.

gdd_bin(#) specifies the fixed width of seasonal GDD categories. When specified, wxsum creates one integer categorical variable gddcat_YYYY for each generated GDD season. The categories are defined over fixed-width intervals of the seasonal GDD total, following the approach used in Deschênes and Greenstone-style specifications. The user can then use Stata's factor-variable notation (e.g., i.gddcat_1993) to generate dummies in estimation commands. The command assigns Stata value labels to each category so that tabulate gddcat_1993 displays the GDD intervals. The bin width is specified in the same units as the generated GDD variable. Requires type(temp).

gdd_binlo(#) specifies the lower endpoint at which regular fixed-width GDD intervals begin. Default is 0 when gdd_bin() is specified. If any seasonal GDD total falls below this value, a bottom-coded category "GDD < #" is created. Requires gdd_bin().

gdd_binhi(#) specifies the upper endpoint at which regular fixed-width GDD intervals end. Values at or above this endpoint are assigned to a top-coded category "GDD >= #". When omitted, the command automatically extends the regular intervals to cover the empirical maximum. Requires gdd_bin(). Must be greater than gdd_binlo(). The range (gdd_binhi() - gdd_binlo()) must be evenly divisible by gdd_bin().

tmp_bin(#) specifies the total number of daily temperature bin count variables to create per season. Must be a positive integer from 1 to 42. Requires type(temp) and both tmp_binlo() and tmp_binhi().

These are daily temperature bin counts based on one observed daily temperature reading per day, in the spirit of Schlenker-Roberts. When only one daily reading is available, the entire day is assigned to the bin containing that reading.

The command is unit agnostic: the user must supply tmp_binlo() and tmp_binhi() in the same units as the daily temperature data.

Missing daily temperatures are not counted in any bin. If all daily temperatures for a location-season are missing, all tmpbinXX_YYYY variables for that location-season are set to missing. Otherwise, the sum of all tmpbinXX_YYYY equals the number of nonmissing daily temperature readings in that season.

For tmp_bin(J) with J >= 3, the bins are constructed as follows. Let lo = tmp_binlo(), hi = tmp_binhi(), and w = (hi - lo) / (J - 2). Then:

tmpbin01 counts days with T < lo (lower tail)

tmpbin02 counts days with lo <= T < lo + w

tmpbin03 counts days with lo + w <= T < lo + 2w

...

tmpbinJJ counts days with T >= hi (upper tail)

Formally:

tmpbin_it^(1) = sum_d 1{T_id < lo}

tmpbin_it^(j) = sum_d 1{lo + (j-2)w <= T_id < lo + (j-1)w}, j = 2,...,J-1

tmpbin_it^(J) = sum_d 1{T_id >= hi}

where w = (hi - lo) / (J - 2)

Interior bins are lower-closed and upper-open. The lower tail is strictly below lo. The upper tail is at or above hi.

Schlenker-Roberts-style lower-tail/interior/upper-tail bins are obtained with tmp_bin(3) or larger. Common fine-bin specifications use values such as tmp_bin(15) or tmp_bin(42).

Special cases for small J:

- tmp_bin(1): Creates a single variable counting all nonmissing daily temperature readings. tmp_binlo() and tmp_binhi() are required for syntax consistency but are not used for assignment.

- tmp_bin(2): Splits at the midpoint m = (lo + hi) / 2. tmpbin01 counts T < m, tmpbin02 counts T >= m.

tmp_binlo(#) specifies the lower bound of the temperature range for bin construction. Required when tmp_bin() is specified. Must be in the same units as the daily temperature data.

tmp_binhi(#) specifies the upper bound of the temperature range for bin construction. Required when tmp_bin() is specified. Must be greater than tmp_binlo() and in the same units as the daily temperature data.

shape(wide|long) specifies the shape of the final output. The default is wide, producing one row per spatial/analytic unit with year-suffixed variable names (e.g., mean_1993, tmpbin01_1993).

When shape(long) is specified, the final output is stacked long with one row per retained unit-year. A variable named year is created to identify the season year. Generated variables have their _YYYY suffixes stripped (e.g., mean, tmpbin01). Variables specified in keep() are repeated across years.

It is strongly recommended to use keep(id ...) or keep() with whatever merge keys are needed when shape(long) is requested. If keep() is empty, a note is printed but no error occurs.

shape(long) is a final-output stacking operation; the wide input requirement is unchanged. It can make panel workflows easier and can reduce the final number of variables when many years or temperature bins are generated, although it does not yet reduce the peak number of variables created internally.

If a variable named year is included in keep(), the command exits with an error to prevent naming conflicts.

keep(varlist) specifies variables to keep in the final output (e.g., location identifiers).

save(filename) saves the output dataset.

Growing degree days are calculated as capped degree accumulation: min(max(temp - gdd_lo, 0), gdd_hi - gdd_lo), summed over the season.

Variance requires at least 2 non-missing observations. Skewness is calculated as the adjusted Fisher-Pearson sample skewness. It requires at least 3 non-missing observations.

Dry spells are calculated strictly from non-missing rainfall data. A dry day is defined as rainfall strictly less than rain_threshold(#). A rainy day is rainfall greater than or equal to rain_threshold(#). Missing daily rainfall values are excluded from dry counts and break consecutive dry spells.

- dry_start_YYYY captures the length of the leading dry spell before the first rainy day or missing value.

- dry_YYYY captures the longest mid-season dry spell strictly after the first observed rainy day and strictly before the last observed rainy day.

- dry_end_YYYY captures the trailing dry spell after the last rainy day or missing value.

GDD categories are constructed over the seasonal GDD total, not over daily temperatures. Let tau_0 < tau_1 < ... < tau_J be fixed cutpoints generated from gdd_bin(), gdd_binlo(), and either gdd_binhi() or the automatic endpoint. Then gddcat_it = j if tau_ <= GDD_it < tau_j. If a bottom-coded category is needed, gddcat_it = 1 when GDD_it < tau_0. If a top-coded category is requested, gddcat_it = J+1 when GDD_it >= tau_J.

Examples

. use rain.dta, clear

. wxsum rf_, type(rain) ini_month(05) fin_month(10) ini_day(15) fin_day(15)

. use temp.dta, clear

. wxsum tmp_, type(temp) ini_month(11) fin_month(02) gdd_lo(8) gdd_hi(32) kdd_base(32) keep(hhid)

. * GDD categories example

. wxsum tmp_, type(temp) ini_month(04) ini_day(01) fin_month(09) fin_day(15) gdd_lo(18) gdd_hi(30) kdd_base(32) gdd_bin(100) gdd_binlo(50) gdd_binhi(950) keep(hhid)

. * Daily temperature bin counts example

. wxsum tmp_, type(temp) ini_month(04) ini_day(01) fin_month(09) fin_day(15) gdd_lo(18) gdd_hi(30) kdd_base(32) tmp_bin(15) tmp_binlo(0) tmp_binhi(39) keep(hhid)

. * Changing the long-run benchmark

. use rain.dta, clear

. wxsum rf_, type(rain) ini_month(05) fin_month(10) lr_years(20) keep(hhid)

. * Long output for panel workflows

. use rain.dta, clear

. wxsum rf_, type(rain) ini_month(05) fin_month(10) ini_day(15) fin_day(15) rain_threshold(1) keep(hhid) shape(long)

Authors

Jeffrey D. Michler

Anna Josephson

Oscar Barriga-Cabanillas

Aleksandr Michuda

Jeffrey C. Oliver