*! version 0.1.4 29Dec2022
help panelview

Title

panelview -- Visualizing Panel Data

Syntax

panelview Y [D X]
[if] [in]
, i(varname) t(varname numeric) type(string)
[options]

Main
Y D X varlist of outcome variable, treatment variable, and covariates, respectively. Including covariates may change the look of the plot due to missing values in these covariates.
Variables appearing in the if/in clause should be included in the varlist

i(varname) specifies the unit (group) indicator

t(varname) specifies the time indicator

type(string) can be treat, outcome, bivariate, and missing.
type(treat) plots treatment assignment using a heatmap; type(outcome) plots a variable in a time-series fashion;
type(bivariate) plots the outcome and treatment against time in the same graph; type(missing) plots the missing data status of a variable.

Advanced
continuoustreat presents the treatment variable D in a continuous fashion

discreteoutcome when a variable is discrete, make sure panelview respects its discreteness in type(outcome) plots

bytiming sorts units by when they first receive the treatment; if the timing is the same, then by the total number of periods exposed to the treatment

ignoretreat omits the treatment indicator, that is, any variables after Y will be interpreted as covariates

ignoreY shows treatment status of the first variable in the varlist instead of the second (e.g., D in formula is D X, instead of X).
It needs to be combined with type(treat) or type(missing). If there is only one variable in the varlist, the option is turned on by default

mycolor(string) changes the color schemes; click here for sequential colors (3-9 colors)

prepost distinguishes the pre- and post-treatment periods for treated units

xlabdist(integer) changes the gap between labels on the x-axis; default is 1

ylabdist(integer) changes the gap between labels on the y-axis; default is 1

bygroup puts each unit into different treatment groups, then plot them separately in a column when type(outcome) is invoked

style() determines the style of the elements in a plot. The first and second entries define the style of the outcome and treatment, respectively.
connected or c for connected lines, line or l for lines, and bar or b for bars

byunit plots the outcome and treatment variables against time by each unit when type(bivariate) is invoked

theme(bw) uses the black and white theme (default when specified type(bivar))

lwd() sets the line width in type(bivar). Default is medium

leavegap keeps the time gap as an white bar if time is not evenly distributed (possibly due to missing data)

bygroupside arranges subfigures of bygroup in a row rather than in a column

displayall shows all units if the number of units is more than 500, otherwise we randomly select 500 units to present

bycohort plots the average outcome lines based on unique treatment history

collapsehistory plots only the unique treatment histories,
including figures alongside the plot for the number of units whose histories are characterized by each pattern

* Common graph options, such as title, ytitle, xtitle, xlabel, ylabel, and legend, can be applied in panelview as well.

Description

panelview has three main functionalities:

(1) it plots the treatment status and missing values in a panel dataset;

(2) it visualizes variables of interest in a time-series fashion;

(3) it depicts the bivariate relationships between a treatment variable and an outcome variable either by unit or in aggregate.

Examples

Load example data (the turnout dataset)

. sysuse turnout, clear

Basic syntax

. panelview turnout policy_edr policy_mail_in policy_motor, i(abb) t(year) type(treat) xtitle("Year") ytitle("State") title("Treatment Status", size(medium))

In this plot, turnout is the outcome, policy_edr is the treatment, policy_mail_in and policy_motor are the covariates.
Here we change the texts and sizes of titles using xtitle, ytitle, and title. For more choice of text size style, click here.

For panel data with a staggered adoption design, we can distinguish the pre- and post-treatment periods for treated units by specifying prepost:

. panelview turnout policy_edr policy_mail_in policy_motor, i(abb) t(year) type(treat) prepost

Use bytiming to sort units by the timing of receiving the treatment. We also use label and size options inside legend to specify label and size of the legend:

. panelview turnout policy_edr policy_mail_in policy_motor, i(abb) t(year) type(treat) bytiming legend(label(1 "No EDR") label(2 "EDR") size(vsmall))

If the number of units is too much, we can use collapsehistory to plot only the unique treatment histories, including figures alongside the plot for the number of units whose histories are characterized by each pattern:

. Load example data (the state capacity dataset)

. sysuse capacity, clear

. panelview lnpop demo lngdp, i(country) t(year) type(treat) xlabdist(3) collapsehistory title("Unique Treatment Histories")

Change the color schemes for the controls and treated using the mycolor option. For example, PuBu indicates light purple to blue:

. panelview turnout policy_edr policy_mail_in policy_motor, i(abb) t(year) type(treat) bytiming mycolor(PuBu)

Treatment: missing & switch on and off

. sysuse capacity, clear

. panelview lnpop demo lngdp , i(country) t(year) type(treat) mycolor(Reds) xlabdist(3) ylabdist(10)

demo is a binary indicator of regime type. Use the xlabdist and ylabdist options to change the gaps between labels on the x- and y-axes.

Ignoring the Treatment Indicator

When we omit the treatment variable, the plot will show missing (the white area) and non-missing values only. This is essentially a plot for missing data:

. panelview demo, i(ccode) t(year) type(treat) mycolor(Reds) xlabel(none) ylabel(none) ignoretreat

Another way to achieve this goal is to set type(missing):

. panelview demo, i(ccode) t(year) type(missing) mycolor(Reds) xlabel(none) ylabel(none)

More than Two Treatment Conditions

panelview supports panel data with more than 2 treatment levels. For example, we create a measure of regime type with three treatment levels:

. gen demo2 = 0

. replace demo2 = -1 if polity2 < -0.5

. replace demo2 = 1 if polity2 > 0.5

. panelview Capacity demo2 lngdp, i(ccode) t(year) type(treat) xlabdist(3) ylabdist(11)

If the number of treatment levels is greater than 5, then the treatment indicator will be regarded as a continuous variable. We can plot the continuous treatment variable by specifying continuoustreat.

Plotting Outcomes

Continuous Outcomes

. sysuse turnout, clear

. panelview turnout policy_edr, i(abb) t(year) type(outcome) prepost ylabel(0 (25) 100, labsize(small)) xlabel(, labsize(small))

The three different colors represent the pure control units, treated units in the pre-treatment periods, and treated units in the post-treatment period.

Different from a treatment status plot, an outcome plot does not allow xlabdist and ylabdist. Instead, xlabel and ylabel can be used to adjust looks of axis labels.

. panelview turnout policy_edr, i(abb) t(year) type(outcome) bygroup xlabel(1920 (20) 2000)

Because bygroup is invoked, panelview analyzes the data and automatically put each unit into different groups based on the changes of their treatment statuses,
e.g. (1) units always being treated, (2) units always under control, (3) units whose treatment status has changed.

Discrete Outcomes

. sysuse simdata, clear

. panelview Y D, type(outcome) i(id) t(time) discreteoutcome xlabel(8 (2) 15) ylabel(0 (1) 2)

Accommodate discrete variables by setting discreteoutcome.

Plotting any variable in a panel dataset

. sysuse turnout, clear

. panelview turnout, i(abb) t(year) type(outcome) ylabel(0 (25) 100) legend(off)

When we ignore the treatment status and apply type(outcome), panelview can plot an outcome variable or an arbitrary variable in a panel dataset.

Plotting Y and D against time in the same graph

Plot average time series for all units

. panelview turnout policy_edr, i(abb) t(year) xlabdist(7) type(bivariate) msize(*0.5) style(c b) ytitle("turnout") ytitle("policy_edr", axis(2)) legend(label(1 "turnout") label(2 "policy_edr"))

Visualize the average outcome and average treatment status against time simultaneously by specifying type(bivariate).
style(c b) means that, for the continuous outcome, we use a connected line plot; for the discrete treatment, we use a bar plot. We can specify the symbol size by msize() for connected line.
The left y axis indicates outcome label; the right y axis indicates treatment label.

Plot by each unit

. panelview turnout policy_edr if abb >= 1 & abb <= 12, i(abb) t(year) xlabdist(10) type(bivar) byunit

Plot D and Y for each unit against time in the same graph.

Use a line plot to represent (discrete) treatment status:

. panelview turnout policy_edr if abb >= 1 & abb <= 12, i(abb) t(year) xlabdist(10) style(l l) type(bivar) byunit l1title("Y") r1title("D")

To better visualize a discrete treatment whose value is sometimes zero, we use style(l l) to invoke line plots instead of bar plots.
Instead of using ytitle, we use l1title and r1title to label the left and right axes, respectively.

Authors

Hongyu Mou (Maintainer), hongyumou@g.ucla.edu
University of California, Los Angeles

Yiqing Xu, yiqingxu@stanford.edu
Stanford University

Please do not hesitate to send your comments or suggestions to the maintainer.

Citation

Hongyu Mou, Licheng Liu, and Yiqing Xu. "Panel Data Visualization in R (panelView) and Stata (panelview)." Journal of Statistical Software, 107(7), 1-20, 2023. doi:10.18637/jss.v107.i07.

For more examples, click https://github.com/xuyiqing/panelview_stata.