How to organise a research project folder so others can follow it
A research project that only its author can navigate is hard to review, hard to hand over and hard to reproduce. A simple, consistent folder layout fixes most of that, and it takes an afternoon to set up.
- Separate what you were given (raw data), what you wrote (code and docs) and what the code produces (results), and never edit raw data by hand.
- Consistent, sortable file names and a short README do more for readability than any clever tool.
- One entry point, such as a Makefile or a run script, lets anyone regenerate the results without guessing the order of steps.
Open an old project folder and you will often find something like this: final_analysis.R, final_analysis_v2.R, final_analysis_v2_REAL.R, a spreadsheet called data_cleaned_new.xlsx and a figure nobody remembers making. The person who wrote it might be able to rebuild the paper from it. A reviewer, a new student or the same person two years later usually cannot.
Folder structure sounds like housekeeping, but it is part of how research becomes reproducible. A clear layout tells a reader where the inputs are, which code produced which output and how to run it again. This post describes a simple layout that works for most projects, and the habits that keep it tidy.
Why does folder structure matter?
Because other people need to follow the path from data to result without asking you. Reviewers checking code, collaborators joining a project and readers trying to reuse a method all start in the same place: an unfamiliar folder. If they cannot tell which file is the real input or which script runs first, they give up or, worse, guess wrong.
A good structure also helps you. It makes it obvious where new files go, prevents accidental overwriting of data and makes the project easy to archive when the paper is done. Our checklist for reviewing research code starts with exactly these questions.
What does a good layout look like?
Here is a layout that suits most data analysis projects. Adapt the names to your field, but keep the separation.
my-project/
├── README.md
├── LICENSE
├── CITATION.cff
├── Makefile
├── environment.yml
├── data/
│ ├── raw/ # original inputs, never edited
│ └── processed/ # generated by code, safe to delete
├── src/
│ ├── 01_clean.py
│ ├── 02_model.py
│ ├── 03_figures.py
│ └── utils.py
├── results/
│ ├── figures/
│ └── tables/
├── docs/
│ └── methods-notes.md
└── tests/
└── test_utils.py
The principle behind it is short: keep apart what you were given, what you wrote and what your code produced. Each of those has different rules, and mixing them is where most confusion starts.
How should you handle raw data?
Treat it as read-only. Files in data/raw/ are exactly what you received or collected: the instrument output, the survey export, the download from a repository. Never edit them by hand, never save over them and never "just fix one cell" in a spreadsheet.
Every change to the data should happen in code that reads from raw/ and writes to processed/. That way the cleaning steps are recorded, repeatable and reviewable. If you need to correct an error in the source, write the correction in a script with a comment explaining why.
A few related habits help:
- Record where each raw file came from, when and in what version, in a short
data/README.md. - If data is too large or too sensitive for the repository, keep it out of version control and document how to obtain it.
- Set raw files to read-only on your file system if you are worried about accidents.
Where should code live?
In src/, split into scripts that each do one stage of the work. Numbered prefixes such as 01_, 02_ show the order at a glance. Shared functions go in a separate module, so that the same cleaning logic is not copied into five places.
Keep exploratory notebooks in their own folder, for example notebooks/, and move anything that the final results depend on into scripts. Notebooks are good for exploring but hard to run in order and hard to review. Our post on reproducible Jupyter notebooks covers how to keep them useful.
Use relative paths inside the project, never absolute ones. A line like read_csv("/Users/anna/Desktop/thesis/data.csv") works on exactly one computer. Writing data/raw/survey.csv, relative to the project root, works for everyone who clones the folder. If a script needs settings such as file locations or model parameters, keep them in one small configuration file rather than scattered through the code.
Put the whole project under Git from the first day. Version control replaces the _v2_final naming pattern entirely, because the history is kept for you.
What goes in results and docs?
results/ holds everything your code generates: figures, tables, model outputs. The rule is that anything in this folder can be deleted and rebuilt by running the code. If deleting a file in results/ would lose work, that file belongs somewhere else.
docs/ holds human-written material that is not code: method notes, a data dictionary, decisions and their reasons, meeting notes that affect the analysis. The top-level README.md is the front door. It should say what the project is, how to set up the environment, how to run it and where the outputs appear. See our guide to writing a README for research code for a template.
A few files at the top level are worth adding early:
| File | Purpose |
|---|---|
README.md | What this is and how to run it |
LICENSE | Terms for reuse, see choosealicense.com |
CITATION.cff | How to cite the code, in the Citation File Format |
environment.yml or requirements.txt | The software versions the project needs |
How should you name files?
So that a computer can sort them and a human can read them. Simple rules cover most cases:
- No spaces or special characters. Use lowercase letters, numbers, hyphens and underscores.
- Dates in ISO format. Write
2026-11-05, not5.11.26. ISO dates sort correctly. - Pad numbers. Use
01,02to10so the order stays right. - Describe the content.
survey-responses-wave2.csvtells a reader far more thandata2.csv. - No version words. Leave
final,newandv3out of names. Let version control track history.
Pick a convention, write it in the README, and stick to it. Consistency matters more than the exact rule.
Why have a single entry point?
Because the order of steps is knowledge, and it should be written down in a form a computer can run. A single entry point, such as a Makefile or a short shell script, means a reader can type one command and get the results. Nobody has to guess whether cleaning runs before modelling.
GNU Make is a good fit for research because it knows which outputs depend on which inputs and only reruns what changed. A minimal example looks like this:
all: results/figures/fig1.png
data/processed/clean.csv: data/raw/survey.csv src/01_clean.py
python src/01_clean.py
results/model.rds: data/processed/clean.csv src/02_model.R
Rscript src/02_model.R
results/figures/fig1.png: results/model.rds src/03_figures.py
python src/03_figures.py
clean:
rm -rf data/processed/* results/*
If Make feels like too much, a plain run_all.sh that calls each script in order still does most of the job. Workflow tools such as Snakemake or Nextflow are worth looking at for larger pipelines. The important thing is that there is one documented way to run everything from raw data to final figures.
What about projects that do not fit the template?
Adapt it, but keep the three-way split. A simulation project may have no raw data but will have parameter files, which deserve the same read-only treatment. A software package will follow the conventions of its language, with source, tests and documentation in standard places. A thesis may contain several analyses, each with its own subfolder that follows the same pattern.
When the paper is accepted, the same structure makes archiving easy. Tag a release, deposit a snapshot in a repository such as Zenodo, and add the DOI to the README and the paper. Our guide on archiving code with a DOI walks through the steps. A tidy folder is also much easier to describe in a code availability statement.
The layout is not a standard to enforce. It is a set of agreements that let other people find their way. Writing those agreements down in the README is what turns a personal habit into something a group can share.
What to do this week
Take your current project and create the four folders: data/raw, src, results and docs. Move files into them, rename the worst offenders and delete anything in results that you can regenerate. Then write a short README and a run script that rebuilds one figure from raw data. Ask a colleague to try it without your help. Whatever they get stuck on is the next thing to fix.
Questions
Should raw data go into version control?
Small, shareable raw data can. Large or sensitive data usually should not. In that case keep it out of the repository and document exactly where it comes from and how to obtain it.
Do I need to use Make?
No. Any single documented entry point works, including a plain shell script. Make is useful because it reruns only the steps whose inputs changed, which saves time on larger projects.
Where do Jupyter notebooks belong?
In their own folder for exploration. Anything the final results depend on should be moved into scripts in src so it can be run in order and reviewed.
Is there one correct layout for every project?
No. The key idea is separating raw inputs, code and generated outputs, plus clear names and one way to run everything. Adapt the details to your field and record them in the README.
Keep reading. More from the desk.
Reproducible environments for research code
Sharing your code is step one. Making sure it still runs on someone else's machine, next year, is step two. The tools are mature. The hard part is choosing the right level of effort.
Choosing a license for research code
Public code without a license is not open code. Picking one takes ten minutes once you know the trade offs, and it is the single cheapest thing you can do to make your work reusable.
Teaching researchers to code: what works
Most researchers learn to code by copying a colleague's script and hoping. There are better ways. This guide covers the teaching approaches that have proven themselves in research settings and how to start one where you work.