All Projects → globeandmail → Startr

globeandmail / Startr

Licence: mit
A template for data journalism in R

Programming Languages

r
7636 projects

Projects that are alternatives of or similar to Startr

Openrefine
OpenRefine is a free, open source power tool for working with messy data and improving it
Stars: ✭ 8,531 (+12263.77%)
Mutual labels:  journalism, data-analysis, data, data-visualization
Volbx
Graphical tool for data manipulation written in C++/Qt
Stars: ✭ 187 (+171.01%)
Mutual labels:  data-analysis, data, data-visualization
Cjworkbench
The data journalism platform with built in training
Stars: ✭ 244 (+253.62%)
Mutual labels:  journalism, data-analysis, data-visualization
Homeless Arrests Analysis
A Los Angeles Times analysis of arrests of the homeless by the LAPD
Stars: ✭ 53 (-23.19%)
Mutual labels:  news, journalism, data-analysis
Data Science Resources
👨🏽‍🏫You can learn about what data science is and why it's important in today's modern world. Are you interested in data science?🔋
Stars: ✭ 171 (+147.83%)
Mutual labels:  data-analysis, data, data-visualization
Graphia
A visualisation tool for the creation and analysis of graphs
Stars: ✭ 67 (-2.9%)
Mutual labels:  data-analysis, data, data-visualization
Data Forge Ts
The JavaScript data transformation and analysis toolkit inspired by Pandas and LINQ.
Stars: ✭ 967 (+1301.45%)
Mutual labels:  data-analysis, data, data-visualization
California Coronavirus Data
The Los Angeles Times' independent tally of coronavirus cases in California.
Stars: ✭ 188 (+172.46%)
Mutual labels:  news, journalism, data
kobe-every-shot-ever
A Los Angeles Times analysis of Every shot in Kobe Bryant's NBA career
Stars: ✭ 66 (-4.35%)
Mutual labels:  news, journalism, data-analysis
Datagear
数据可视化分析平台,使用Java语言开发,采用浏览器/服务器架构,支持SQL、CSV、Excel、HTTP接口、JSON等多种数据源
Stars: ✭ 266 (+285.51%)
Mutual labels:  data-analysis, data, data-visualization
Notebooks
All of our computational notebooks
Stars: ✭ 292 (+323.19%)
Mutual labels:  news, journalism, data-analysis
Data Science Hacks
Data Science Hacks consists of tips, tricks to help you become a better data scientist. Data science hacks are for all - beginner to advanced. Data science hacks consist of python, jupyter notebook, pandas hacks and so on.
Stars: ✭ 273 (+295.65%)
Mutual labels:  data-analysis, data, data-visualization
Metabase
The simplest, fastest way to get business intelligence and analytics to everyone in your company 😋
Stars: ✭ 26,803 (+38744.93%)
Mutual labels:  data-analysis, data, data-visualization
Drugs Recommendation Using Reviews
Analyzing the Drugs Descriptions, conditions, reviews and then recommending it using Deep Learning Models, for each Health Condition of a Patient.
Stars: ✭ 35 (-49.28%)
Mutual labels:  data-analysis, data-visualization
Data Science Lunch And Learn
Resources for weekly Data Science Lunch & Learns
Stars: ✭ 49 (-28.99%)
Mutual labels:  data-analysis, data-visualization
Metrotwitter
What Twitter reveals about the differences between cities and the monoculture of the Bay Area
Stars: ✭ 52 (-24.64%)
Mutual labels:  data-analysis, data-visualization
Apogee
Tools for dealing with APOGEE data
Stars: ✭ 34 (-50.72%)
Mutual labels:  data-analysis, data
Vue Data Board
A Data Analysis Board in Vue.
Stars: ✭ 1,046 (+1415.94%)
Mutual labels:  data-analysis, data-visualization
Muze
Composable data visualisation library for web with a data-first approach now powered by WebAssembly
Stars: ✭ 1,153 (+1571.01%)
Mutual labels:  data, data-visualization
Pycm
Multi-class confusion matrix library in Python
Stars: ✭ 1,076 (+1459.42%)
Mutual labels:  data-analysis, data

startr

A template for data journalism projects in R.

This project structures the data analysis process, reducing the amount of time you'll spend setting up and maintaining a project. Essentially, it's an "opinionated framework" like Django, Ruby on Rails or React, but for data journalism.

Broadly, startr does a few things:

  • Standardizes your projects: Eliminates the need to think about project structure so you can focus on the analysis.
  • Breaks analysis into discrete steps: Supports a flexible analysis workflow with clearly-defined steps which can be shared easily across a team.
  • Helps you catch mistakes: With structure and workflow baked in, you can focus on writing analysis code, reducing the opportunities for mistakes.
  • Bakes in flexibility: Has a format that works for both large (multi-month) and small (single-day) projects.
  • De-clutters your code: Improves the painstaking data verification/fact-checking process by cutting down on spaghetti code.
  • Improves communication: Documents the analysis steps and questions to be answered for large, multi-disciplinary teams (say, developers, data journalists and traditional reporters).
  • Simplifies the generation of charts and reports: Generates easily updatable RMarkdown reports, Adobe Illustrator-ready graphics, and datasets during analysis.

Table of contents

Installation

This template works with R and RStudio, so you'll need both of those installed. To scaffold a new startr project, we recommend using our command-line tool, startr-cli, which will copy down the folder structure, rename some files, configure the project and initialize an empty Git repository.

Using startr-cli, you can scaffold a new project by simply running create-startr in your terminal and following the prompts:

startr-cli interface GIF

Alternatively, you can run:

git clone https://github.com/globeandmail/startr.git <your-project-name-here>

(But, if you do that, be sure to rename your startr.Rproj file to <project-name>.Rproj and set up your settings in config.R manually.)

Once a fresh project is ready, double-click on the .Rproj file to start a scoped RStudio instance.

You can then start copying in your data and writing your analysis. At The Globe, we like to work in a code editor like Atom or Sublime Text, and use something like r-exec to send code chunks to RStudio.

Philosophy on data analysis

This analysis framework is designed to be flexible, reproducible and easy to jump into for a new user. startr works best when you assume certain coding standards:

  • Your raw data is immutable: Treat the files in data/raw as read-only. This means you only ever alter them programmatically, and never edit or overwrite files in that folder. If you need to manually rewrite certain columns in a raw data file, do so by creating a new spreadsheet with the new values, then join it to the original data file during the processing step.
  • Your outputs are disposable: Treat all project outputs (everything in data/processed, data/out/, data/cache and plots/) as disposable products. By default, this project's .gitignore file ignores those files, so they're never checked into source management tools. Unless absolutely necessary, do not alter .gitignore to check in those files — the analysis pipeline should be able to reproduce them all from your raw data files.
  • Shorter is not always better: Your code should, as much as possible, be self-documenting. Keep it clean and as simple as possible. If an analysis chain is becoming particularly long or complex, break it out into smaller chunks, or consider writing a function to abstract out the complexity in your code.
  • Only optimize your code for performance when necessary: It's easy to fall into a premature optimization rabbit hole, especially on larger or more complex projects. In most cases, there's no need to optimize your code for performance — only do this if your analysis process is taking several minutes or longer.
  • Never overwrite variables: No variables should ever be overwritten or reassigned. Same goes for fields generated via mutate().
  • Order matters: We only ever run our R code sequentially, which prevents reproducibility issues resulting from users running code chunks in different orders. For instance, do not run a block of code at line 22, then code at line 11, then some more code at line 37, since that may lead to unexpected results that another journalist won't be able to reproduce.
  • Wipe your environment often: If using RStudio (our preferred tool for work in R), restart and clear the environment often to make sure your code is reproducible.
  • Use the tidyverse: For coding style, we rely on the tidyverse style guide.

Workflow

The heart of the project lies in these three files:

  • process.R: Import your source data, tidy it, fix any errors, set types, apply upfront manipulations and save out a file ready for analysis. We recommend saving out a .feather file, which will retain types and is design to read extremely quickly — but you can also use a .CSV, shapefile, .RDS file or something else if you'd prefer.

  • analyze.R: Here you'll consume the data files saved out by process.R. This is where all of the true "analysis" occurs, including grouping, summarizing, filtering, etc. If your analysis is complex enough, you may want to split it out into additional analyze_step_X.R files as required.

  • visualize.R: Draw and save out your graphics.

There's also an optional (but recommended) RMarkdown file (notebook.Rmd) you can use to generate an HTML codebook – especially useful for longer-term projects where you need to document the questions you're asking.

Step 1: Set up your project

The bulk of any startr project's code lives within the R directory, in files that are sourced and run in sequence by the run.R at the project's root.

Many of the core functions for this project are managed by a specialty package, upstartr. That package is installed and imported in run.R automatically.

Before starting an analysis, you'll need to set up your config.R file.

That file uses the initialize_startr() function to prepare the environment for analysis. It will also load all the packages you'll need. For instance, you might want to add the cancensus library. To do that, just add 'cancensus' to the packages vector. Package suggestions for GIS work, scraping, dataset summaries, etc. are included in commented-out form to avoid bloat. The function also takes several other optional parameters — for a full list, see our documentation.

Once you've listed the packages you want to import, you'll want to reference your raw data filenames so that you can read them in during process.R. For instance, if you're adding pizza delivery data, you'd add this line to the filenames block in config.R:

pizza.raw.file <- dir_data_raw('Citywide Pizza Deliveries 1998-2016.xlsx')

Our naming convention is to append .raw to variables that reference raw data, and .file to variables that are just filename strings.

Step 2: Import and process data

In process.R, you'll read in the data for the filename variables you assigned in config.R, do some clean-up, rename variables, deal with any errors, convert multiple files to a common data structure if necessary, and finally save out the result. It might look something like this:

pizza.raw <- read_excel(pizza.raw.file, skip = 2) %>%
  select(-one_of('X1', 'X2')) %>%
  rename(
    date = 'Date',
    time = 'Time',
    day = 'Day',
    occurrence_id = 'Occurrence Identification Number',
    lat = 'Latitude',
    lng = 'Longitude',
    person = 'Delivery Person',
    size = 'Pizza Size (in inches)',
    price = 'Pizza bill \n after taxes'
  ) %>%
  mutate(
    price = parse_number(price),
    year_month = format(date, '%Y-%m-01'),
    date = ymd(date)
  ) %>%
  filter(!is.na(date))

write_feather(pizza.raw, dir_data_processed('pizza.feather'))

When called via the run_process() function in run.R, variables generated during processing will be removed once the step is completed to keep the working environment clean for analysis.

We prefer to write out our processed files using the binary .feather format, which is designed to read and write files extremely quickly (at roughly 600 MB/s). Feather files can also be opened in other analysis frameworks (i.e. Jupyter Notebooks) and, most importantly, embed column types into the data so that you don't have to re-declare a column as logicals, dates or characters later on. If you'd rather save out files in a different format, you can just use a different function, like the tidyverse's write_csv().

Output files are written to /data/processed using the dir_data_processed() function. By design, processed files aren't checked into Git — you should be able to reproduce the analysis-ready files from someone else's project by running process.R.

Step 3: Analyze

This part's as simple as consuming that file in analyze.R and running with it. It might look something like this:

pizza <- read_feather(dir_data_processed('pizza.feather'))

delivery_person_counts <- pizza %>%
  group_by(person) %>%
  count() %>%
  arrange(desc(n))

deliveries_monthly <- pizza %>%
  group_by(year_month) %>%
  summarise(
    n = n(),
    unique_persons = n_distinct(person)
  )

Step 4: Visualize

You can use visualize.R to consume the variables created in analyze.R. For instance:

plot_delivery_persons <- delivery_person_counts %>%
  ggplot(aes(x = person, y = n)) +
  geom_col() +
  coord_flip()

plot_delivery_persons

write_plot(plot_delivery_persons)

plot_deliveries_monthly <- deliveries_monthly %>%
  ggplot(aes(x = year_month, y = n)) +
  geom_col()

plot_deliveries_monthly

write_plot(plot_deliveries_monthly)

Step 5: Write a notebook

TKTKTKTK

Helper functions

startr's companion package upstartr comes with several functions to support startr, plus helpers we've found useful in daily data journalism tasks. A full list can be found on the reference page here. Below is a partial list of some of its most handy functions:

  • simplify_string(): By default, takes strings and simplifies them by force-uppercasing, replacing accents with non-accented characters, removing every non-alphanumeric character, and simplifying double/mutli-spaces into single spaces. Very useful when dealing with messy human-entry data with people's names, corporations, etc.

    pizza_deliveries %>%
      mutate(customer_simplified = simplify_string(customer_name))
    
  • clean_columns(): Renaming columns to something that doesn't have to be referenced with backticks (`Column Name!`) or square brackets (.[['Column Name!']]) gets tedious. This function speeds up the process by forcing everything to lowercase and using underscores – the tidyverse's preferred naming convention for columns. If there are many columns with the same name during cleanup, they'll be appended with an index number.

    pizza_deliveries %>%
      rename_all(clean_columns)
    
  • convert_str_to_logical(): Does the work of cleaning up your True, TRUE, true, T, False, FALSE, false, F, etc. strings to logicals.

    pizza_deliveries %>%
      mutate(was_delivered_logi = convert_str_to_logical(was_delivered))
    
  • calc_index(): Calculate percentage growth by indexing values to the first value:

    pizza_deliveries %>%
      mutate(year = year(date)) %>%
      group_by(size, year) %>%
      summarise(total_deliveries = n()) %>%
      arrange(year) %>%
      mutate(indexed_deliveries = calc_index(total_deliveries))
    
  • calc_mode(): Calculate the mode for a given field:

    pizza_deliveries %>%
      group_by(pizza_shop) %>%
      summarise(most_common_size = calc_mode(size))
    
  • write_excel(): Writes out an Excel file to data/out using the variable name as the file name. Useful for quickly generating summary tables for sharing with others. By design, doesn't take any arguments to keep things as simple as possible. If should_timestamp_output_files is set to TRUE in config.R, will append a timestamp to the filename in the format %Y%m%d%H%M%S.

    undelivered_pizzas <- pizza_deliveries %>%
      filter(!was_delivered_logi)
    
    write_excel(undelivered_pizzas)
    
  • write_plot(): Similar to write_excel(), designed to quickly save out a plot directly to /plots. Takes all the same arguments as ggsave().

    plot_undelivered_pizzas <- undelivered_pizzas %>%
      group_by(year) %>%
      summarise(n = n()) %>%
      ggplot(aes(x = year, y = n)) +
      geom_col()
    
    write_plot(plot_undelivered_pizzas)
    
  • read_all_excel_sheets(): Combines all Excel sheets in a given file into a single dataframe, adding an extra column called sheet for the sheet name. Takes all the same arguments as readxl's read_excel().

    pizza_deliveries <- read_all_excel_sheets(
        pizza_deliveries.file,
        skip = 3,
      )
    
  • combine_csvs(): Read all CSVs in a given directory and concatenate them into a single file. Takes all the same arguments as read_csv()

    pizzas <- combine_csvs(dir_data_raw())
    
  • combine_excels(): Read all Excel spreadsheets in a given directory and concatenate them.

    pizzas_in_excel <- combine_excels(dir_data_raw())
    
  • unaccent(): Remove accents from strings.

    unaccent('Montréal')
    
  • remove_non_utf8(): Remove non-UTF-8 characters from strings.

    non_utf8 <- 'fa\xE7ile'
    Encoding(non_utf8) <- 'latin1'
    remove_non_utf8(non_utf8)
    
  • %not_in%: The opposite of the %in% operator.

    c(1, 2, 3, 4, 5) %not_in% c(4, 5, 6, 7, 8)
    
  • not.na(): The opposite of the is.na function.

  • not.null(): The opposite of the is.null function.

Tips

  • You don't always need to process your data: If your processing step takes a while and you've already generated your processed files during a previous run, you can tell startr to skip this step by setting should_process_data to FALSE in config.R's initialize_startr() function. Just be sure to set it back to TRUE if your processing code changes!
  • Consider timestamping your output files: If you're using upstartr's write_excel() helper, you can automatically timestamp your filenames by setting should_timestamp_output_files to TRUE in initialize_startr().
  • Use the functions file: Reduce repetition in your code by writing functions and putting them in the functions.R file, which gets source()'d when run_config() is run.
  • Help us make startr better: Using this package? Find yourself wishing the structure were slightly different, or have an often-used function you're tired of copying and pasting between projects? Please send us your feedback.

Directory structure

├── data/
│   ├── raw/          # The original data files. Treat this directory as read-only.
│   ├── cache/        # Cached files, mostly used when scraping or dealing with packages such as `cancensus`
│   ├── processed/    # Imported and tidied data used throughout the analysis.
│   └── out/          # Exports of data at key steps or as a final output.
├── R/
│   ├── process.R     # Data processing including tidying, processing and manupulation.
│   ├── analyze.R     # The primary analysis steps.
│   ├── visualize.R   # Generate plots as png, pdf, etc.
│   └── functions.R   # Project-specific functions.
├── plots/            # Visualizations saved out plot files in standard formats.
├── reports/          # Generated reports and associated files.
├── scrape/
│   └── scrape.R      # Scraping scripts that save collected data to the `/data/raw/` directory.
│   └── notebook.Rmd  # Standard notebook to render reports.
├── config.R          # Global project variables including packages, key project paths and data sources.
├── run.R             # Wrapper file to run the analysis steps, either inline or sourced from component R files.
└── startr.Rproj      # Rproj file for RStudio

An .nvmrc is included at the project root for Node.js-based scraping. If you prefer to scrape with Python, be sure to add venv and requirements.txt files, or a Gemfile if working in Ruby.

See also

startr is part of a small ecosystem of R utilities. Those include:

  • upstartr, a library of functions that support startr and daily data journalism tasks
  • tgamtheme, The Globe and Mail's graphics theme
  • startr-cli, a command-line tool that scaffolds new startr projects

Version

1.1.0

License

startr © 2020 The Globe and Mail. It is free software, and may be redistributed under the terms specified in our MIT license.

Get in touch

If you've got any questions, feel free to send us an email, or give us a shout on Twitter:

Tom Cardoso Michael Pereira
Tom Cardoso
@tom_cardoso
Michael Pereira
@__m_pereira
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].