{"id":13400809,"url":"https://github.com/jacob-long/panelr","last_synced_at":"2025-12-24T17:16:26.799Z","repository":{"id":29627611,"uuid":"116761060","full_name":"jacob-long/panelr","owner":"jacob-long","description":"Regression models and utilities for repeated measures and panel data","archived":false,"fork":false,"pushed_at":"2025-12-22T13:12:45.000Z","size":8478,"stargazers_count":99,"open_issues_count":21,"forks_count":21,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-12-23T18:00:39.733Z","etag":null,"topics":["r","r-package","social-science","statistics"],"latest_commit_sha":null,"homepage":"","language":"R","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jacob-long.png","metadata":{"files":{"readme":"README.Rmd","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2018-01-09T03:27:58.000Z","updated_at":"2025-12-22T13:12:49.000Z","dependencies_parsed_at":"2023-01-16T23:45:58.530Z","dependency_job_id":"bff8eabc-b6a7-41b8-b9f2-bc7ad7ad2ce2","html_url":"https://github.com/jacob-long/panelr","commit_stats":null,"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"purl":"pkg:github/jacob-long/panelr","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jacob-long%2Fpanelr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jacob-long%2Fpanelr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jacob-long%2Fpanelr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jacob-long%2Fpanelr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jacob-long","download_url":"https://codeload.github.com/jacob-long/panelr/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jacob-long%2Fpanelr/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28005414,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-12-24T02:00:07.193Z","response_time":83,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["r","r-package","social-science","statistics"],"created_at":"2024-07-30T19:00:55.725Z","updated_at":"2025-12-24T17:16:26.775Z","avatar_url":"https://github.com/jacob-long.png","language":"R","funding_links":[],"categories":["R"],"sub_categories":[],"readme":"---\noutput: github_document\n---\n\n\u003c!-- README.md is generated from README.Rmd. Please edit that file --\u003e\n\n```{r, echo = FALSE}\nknitr::opts_chunk$set(\n  collapse = FALSE,\n  comment = \"\",\n  fig.path = \"README-\",\n  message = FALSE\n)\noptions(\"panelr.table.format\" = \"multiline\")\n```\n\n\n[![CRAN_Status_Badge](https://www.r-pkg.org/badges/version-ago/panelr)](https://cran.r-project.org/package=panelr) [![Total Downloads](https://cranlogs.r-pkg.org/badges/grand-total/panelr)](https://cran.r-project.org/package=panelr)\n [![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/github/jacob-long/panelr?branch=master\u0026svg=true)](https://ci.appveyor.com/project/jacob-long/panelr) [![Coverage Status](https://img.shields.io/codecov/c/github/jacob-long/panelr/master.svg)](https://app.codecov.io/github/jacob-long/panelr?branch=master)\n\n\n# panelr\n\nThis is an R package designed to aid in the analysis of panel data, \ndesigns in which the same group of respondents/entities are contacted/measured\nmultiple times. `panelr` provides some useful infrastructure, like a \n`panel_data` object class, as well as automating some emerging methods for\nanalyses of these data.\n\n`wbm()` automates the \"within-between\" (also known as\n\"between-within\" and \"hybrid\") specification that combines the\ndesirable aspects of both fixed effects and random effects econometric models\nand fits them using the `lme4` package in the backend. Bayesian estimation of \nthese models is supported by interfacing with the `brms` package (`wbm_stan()`)\nand GEE estimation via `geepack` (`wbgee()`). \n\nIt also automates the fairly new \"asymmetric effects\" specification described\nby [Allison (2019)](https://journals.sagepub.com/doi/10.1177/2378023119826441)\nand supports estimation via GLS for linear asymmetric effects\nmodels (`asym()`) and via GEE for non-Gaussian models (`asym_gee()`).\n\n## Installation\n\n`panelr` is now available via CRAN.\n\n```{r eval = FALSE}\ninstall.packages(\"panelr\")\n```\n\n## Usage\n\n### `panel_data` frames\n\nWhile not strictly required, the best way to start is to declare your data\nas panel data. I'll load the example data `WageData` to demonstrate.\n\n```{r, message = FALSE}\nlibrary(panelr)\ndata(\"WageData\")\ncolnames(WageData)\n```\n\nThe two key variables here are `t` and `id`. `t` is the wave of the survey the\nrow of the data refers to while `id` is the survey respondent. This is a \nperfectly balanced data set, so there are 7 observations for each of the 595\nrespondents. We will use those two pieces of information to create a \n`panel_data` object.\n\n```{r}\nwages \u003c- panel_data(WageData, id = id, wave = t)\nwages\n```\n\nWe have to tell `panel_data()` which column refers to the unique identifiers\nfor respondents/entities (the latter when you have something like countries\nor companies instead of people) and which column refers to the period/wave of\ndata collection. \n\nNote that the resulting `panel_data` object will remember which of the columns\nis the ID column and which is the wave column. It will also fight you a bit \nwhen you do things that might have the side effect of dropping those columns\nor putting them out of time order.\n`panel_data` frames are modified tibbles \n([`tibble` package](https://tibble.tidyverse.org/)) that are grouped by entity \n(i.e., the ID column).\n\n`panel_data` frames are meant to play nice with the \n[`tidyverse`](https://www.tidyverse.org). Here's a quick sample of how a tidy workflow\nwith `panelr` can work:\n\n```{r}\nlibrary(dplyr)\ndata(\"WageData\")\n# Create `panel_data` object\nwages \u003c- panel_data(WageData, id = id, wave = t) %\u003e%\n  # Pass to mutate, which will calculate statistics groupwise when appropriate\n  mutate(\n    wage = exp(lwage), # reverse transform the log wage variable\n    mean_wage_individual = mean(wage), # means calculated separately by entity\n    lag_wage = lag(wage) # mutate() will calculate lagged values correctly\n  ) %\u003e%\n  # Use `panelr`'s complete_data() to filter for entities that have\n  # enough observations\n  complete_data(wage, union, min.waves = 5) %\u003e% # drop if there aren't 5 completions\n  # You can use unpanel() if you need to do rowwise or columnwise operations\n  unpanel() %\u003e%\n  mutate(\n    mean_wage_grand = mean(wage)\n  ) %\u003e%\n  # You'll need to convert back to panel_data if you want to keep using panelr functions\n  panel_data(id = id, wave = t)\n\n```\n\n\n### `wbm()` --- the within-between model\n\nAnyone can fit a within-between model without the use of this package as it is\njust a particular specification of a multilevel model. With that said, it's \nsomething that will require some programming and could be rather prone to \nerror. In the best case, it is cumbersome and inefficient to create the \nnecessary variables. \n\n`wbm()` is the primary model-fitting function that you'll use from this package \nand it fits within-between models for you, utilizing\n[`lme4`](https://cran.r-project.org/package=lme4) as a \nbackend for estimation. \n\nA three-part model syntax is used that goes like this:\n\n`dv ~ varying_variables | invariant_variables | cross_level_interactions/random effects`\n\nIt works like a typical formula otherwise. The bars just tell `panelr` how to \ntreat the variables. Note also that you can specify random slopes using\n`lme4`-style syntax in the third part of the formula as well. A random intercept\nfor the ID variable is included by default and doesn't need to be specified\nin the formula.\n\nLagged variables are supported as well through the `lag()` function. Unlike base\nR, `panelr` lags the variables correctly --- wave 1 observations will have NA\nvalues for the lagged variable rather than taking the final wave value of the\nprevious entity. \n\nHere we will specify a model using the `wages` data. We will predict \nlogged wages (`lwage`) using two time-varying variables --- lagged\nunion membership (`union`) and contemporaneous weeks worked (`wks`) --- along \nwith a time-invariant predictor, a binary indicator for black race (`blk`).\nFor demonstrative purposes, we'll fit a random slope for `lag(union)` and a \ncross-level interaction between `blk` and `wks`.\n\n```{r message = FALSE}\nmodel \u003c- wbm(lwage ~ lag(union) + wks | blk | blk * wks + (lag(union) | id), data = wages)\nsummary(model)\n```\n\nNote that `imean()` is an internal function that calculates the individual-level\nmean, which represents the between-subjects effects of the time-varying \npredictors. The within effects are the time-varying predictors at the occasion \nlevel with the individual-level mean subtracted. If you want the model specified\nsuch that the occasion level predictors do not have the mean subtracted, use\nthe `model = \"contextual\"` argument. The \"contextual\" label refers to the way \nthese terms are normally interpreted when it is specified that way. \n\nYou may also use `model = \"between\"` to fit what econometricians call the \nrandom effects model, which does not disaggregate the within- and between-entity\nvariation.\n\n### `widen_panel()` and `long_panel()`\n\nTwo functions that should cover your bases for the tricky business of \n**reshaping** panel data are included. Sometimes, like for doing SEM-based\nanalyses, you need your data in wide format --- i.e., one row per entity.\n`widen_panel()` makes that easy and should require minimal trial and error or \nthinking.\n\nPerhaps more often, your raw data are already in wide format and you need\nto get it into long format to do cool stuff like use `wbm()`. That can be very\ntricky, but `long_panel()` (I didn't think `lengthen_panel()` or `longen_panel()`\nquite worked as names) should cover most situations. You tell it what the\nlabels for periods are (e.g., does it range from `1` to `5`, `\"A\"` to `\"E\"`,\nor something else?), where they are located (before or after the variable's\nname?), and what kinds of formatting go before/after it. Check out the\nvignette for more details and some worked examples.\n\n## Contributing\n\nI'm happy to receive bug reports, suggestions, questions, and (most of all)\ncontributions to fix problems and add features. I prefer you use the Github \nissues system over trying to reach out to me in other ways. Pull requests for\ncontributions are encouraged.\n\nPlease note that this project is released with a \n[Contributor Code of Conduct](https://github.com/jacob-long/panelr/blob/master/CONDUCT.md). By participating in this project you\nagree to abide by its terms.\n\n## License\n\nThe source code of this package is licensed under the \n[MIT License](https://opensource.org/license/mit/).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjacob-long%2Fpanelr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjacob-long%2Fpanelr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjacob-long%2Fpanelr/lists"}