*! version 1.6 2022-09-20

Title

bunchfilter -- removes friction errors from data generated by a mixed continuous-discrete distribution with one mass point plus a continuously distributed friction error
according to the procedures of Bertanha, McCallum, and Seegert (2022).
The distribution of the data with friction error is continuous and does not have a mass point.
This type of data is common in bunching applications in economics.
For example, the distribution of taxable income usually has a hump around the kink where marginal tax rate changes, instead of a mass point at the kink.

Syntax

bunchfilter
depvar
[if] [in]
[weight]
,
kink(#)
deltam(#)
deltap(#)
generate(varname)
[
binwidth(#)
nopic
pctobs(#)
polorder(#)
]

Required
depvar must be one dependent variable (the response variable in logs in many applications)

kink(#) is the location of the kink point and must be a real number in the same units as the response variable

deltam(# real) is the distance between the kink point and the lower bound of the support of the friction error to be filtered;
it must be a real number in the same units as the response variable

deltap(# real) is the distance between the kink point and the upper bound of the support of the friction error to be filtered;
it must be a real number in the same units as the response variable

generate(varname) generates the filtered variable with a user-specified name of varname

Optional
if | in like in any other Stata command, to restrict the working sample

weight follows Stata's weight syntax and only allows frequency weights, fweight

nopic suppresses displaying graphs; the default is to display graphs

binwidth(#) is the width of the bins for the histograms; it must be a strictly positive real number;
the default value is half of what is automatically produced by the command histogram

pctobs(# real) for better fit, the polynomial regression uses observations in a symmetric window around the kink point that contains pctobs percent of the sample;
default value is 40 ( integer, min = 1, max = 99)

polorder(# integer) order of polynomial for the filtering regression; default value is 7 (min = 2; max = 7)

Description

The user enters the variable to be filtered (for example, the log of income),
the location of the kink,
and size of a region around the mass point that contains the hump (in other words, kink - deltam, kink + deltap).
bunchfilter fits a polynomial regression to the empirical CDF of the variable observed with error.
This regression excludes points in the hump window and has a dummy for observations on the left or right of the kink.
The fitted regression is used to predict values of the empirical CDF in the hump window with a jump discontinuity at the mass point.
The filtered variable is then recovered from the inverse of the predicted CDF evaluated at the empirical CDF value for each observation in the sample.

This procedure works well for cases where the friction error has bounded support and only affects observations that would be at the kink in the absence of error.
A proper deconvolution theory still needs to be developed for a filtering procedure with general validity.

Note: You need to have a dataset with one variable drawn from a continuous distribution whose PDF clearly exhibits a hump around what would
be a mass point in the absence of friction errors.

(Go up to Syntax)

Example

The package includes the sample data file "bunching.dta". The income data in logs (i.e., "y")
were simulated using a middle-censored model with an elasticity of 0.5.
The budget constraint has a kink at ln(8) with log slopes of ln(1.3) and ln(0.9), respectively, to the left and right of the kink.
These correspond to tax rates to the left and right of the kink of -30 and 10 percent,
respectively.
The data also include randomly generated frequency weights "w".
We introduce nonsharp bunching by adding a random error to the income of bunching
individuals.
Such error term is a truncated normal with support [-ln(0.9), ln(1.1)],
which implies that deltam is 0.1054 and deltap is 0.0953.
The income variable with error is "yfric."

Load the test data file included in the package:

. use bunching

Run bunchfilter with pctobs and polorder options:

. bunchfilter yfric , generate(yfilter) kink(2.0794) deltam(0.1054) deltap(0.0953) pctobs(30) polorder(7)

(Go up to Syntax)

Stored results

bunchfilter stores the following in r():

Scalars

r(filter_Bhat) estimated bunching mass

r(filter_R2) R-squared of polynomial regression

r(filter_vars_dropped) number of variables dropped out of the polynomial regression
in case the initial set of explanatory variables had perfect collinearity

r(binwidth) value of bin width used in histograms; this is not stored if option nopic is stated

(Go up to Syntax)

Authors

Marinho Bertanha, mbertanha@nd.edu, University of Notre Dame

Andrew McCallum, andrew.h.mccallum@frb.gov, Federal Reserve Board

Nathan Seegert, nathan.seegert@eccles.utah.edu, University of Utah.

Reference

Bertanha, M., McCallum, A., Seegert, N. (2022), "Better Bunching, Nicer Notching". Working paper SSRN 3144539.

Bertanha, M., McCallum, A., Payne, A., Seegert, N. (2022), "Bunching Estimation of Elasticities Using Stata".
Stata Journal, forthcoming.