library(tidyverse)
gpfg <- read_csv("data/gpfg.csv")6 Data Analysis
Wrangling prepares the table. Analysis uses that table to answer a question. In this part, we begin with one year and then extend the same workflow across time.
6.1 Learning objectives
By the end of this chapter, you should be able to:
- recognize descriptive, ranking, comparison, relationship, and trend questions;
- calculate totals, means, medians, minimums, and maximums;
- create a ranking;
- compare grouped totals and shares; and
- turn a calculation into a carefully worded finding.
6.2 Types of questions in data journalism
A large dataset does not automatically produce a story. Data journalists begin with questions that the available evidence can answer. Many questions fall into five broad types:
| Question type | What it asks | Example using the GPFG data |
|---|---|---|
| Description | What is present, how much is there, or what is typical? | What is the total reported market value? What is the median holding value? |
| Ranking | Which observations are largest, smallest, highest, or lowest? | Which individual company holdings have the largest market values? |
| Comparison | How do categories or groups differ? | Which countries or industries account for the largest total values? |
| Relationship | Do two variables appear to vary together? | Do holdings with higher ownership percentages also tend to have larger market values? |
| Trend | How does a measure change over time? | How has the reported market value associated with China changed over ten years? |
A question can belong to more than one type. Ranking countries by total market value, for example, first requires a comparison among countries and then an ordering of the results.
This chapter focuses on description, ranking, and comparison using one annual snapshot. Later chapters introduce relationships through visualization and trends through the multi-year data.
6.3 A question-to-answer workflow
Before writing code, use this workflow:
- State what one row represents.
- Write a precise question that names the measure, group, and time period.
- Identify the columns needed to answer it.
- Check their types, missing values, and definitions.
- Choose functions that match the type of question.
- Inspect and verify the result, especially surprising values.
- Write a finding that says exactly what the data support.
The previous chapter covered step 4. We will now move from a checked table to questions and findings.
Open djr.Rproj and create 04-data-analysis.Rmd. Reuse data/gpfg.csv from the earlier chapters.
One row represents one reported equity holding at the end of the year.
6.4 Ask a descriptive question
We will begin with:
What are the total and typical market values of individual holdings at the end of 2025?
summarise() can calculate several statistics in one row. In the code below, sum() adds all values, mean() calculates the arithmetic average, median() finds the middle value after sorting, and min() and max() find the smallest and largest values:
holding_summary <- gpfg |>
summarise(
total_market_value_nok = sum(market_value_nok),
average_market_value_nok = mean(market_value_nok),
median_market_value_nok = median(market_value_nok),
smallest_market_value_nok = min(market_value_nok),
largest_market_value_nok = max(market_value_nok)
)
holding_summaryFinancial values are often uneven: a few very large observations can pull the mean upward. Compare the mean and median before calling either one “typical.” The median is often easier to interpret when the distribution is strongly skewed.
6.5 Ask a ranking question
Next, ask:
Which ten individual holdings had the largest reported market values at the end of 2025?
We already know how to order rows and keep the first few:
largest_holdings <- gpfg |>
select(company, country, industry, market_value_nok) |>
arrange(desc(market_value_nok)) |>
slice_head(n = 10)
largest_holdingsA ranking answers “which rows have the largest values?” It does not explain why they are large. Verify important rows against the source before using them in a story.
6.6 Ask a comparison question
A comparison question repeats the same calculation for different groups. For example:
Which investment markets accounted for the largest total market values at the end of 2025?
group_by() tells R which rows belong together. summarise() then reduces each group to one summary row. Used together, they change the meaning of one row in the result.
Group the holdings by market, add their values, and order the totals:
country_summary <- gpfg |>
group_by(country) |>
summarise(market_value_nok = sum(market_value_nok)) |>
mutate(share_percent = market_value_nok / sum(market_value_nok) * 100) |>
arrange(desc(market_value_nok))
country_summary |>
slice_head(n = 10)One row now represents one investment market. share_percent uses the full market value as the denominator, so the column answers: “What percentage of the reported total is associated with this market?”
The sequence is:
group_by(country)forms one group for each investment market;summarise()adds the market values within each group;mutate()calculates each market’s share of the full total; andarrange()places the largest total first.
The market with the most holding records is not necessarily the market with the largest market value. Decide whether the question is about the number of rows or the amount represented by those rows.
Compare the two measures:
gpfg |>
count(country) |>
arrange(desc(n)) |>
slice_head(n = 10)6.7 Compare industries
The same group-and-summarise pattern can answer another comparison question:
Which industries accounted for the largest total market values at the end of 2025?
industry_summary <- gpfg |>
group_by(industry) |>
summarise(
holding_records = n(),
market_value_nok = sum(market_value_nok),
median_holding_nok = median(market_value_nok)
) |>
arrange(desc(market_value_nok))
industry_summaryThis table contains three different measures. Use a column name and chart title that make clear which one supports the finding.
We can also narrow a question with filter(). For example, the following pipeline asks which industries had the largest total market values among holdings that NBIM classifies under China:
china_industries <- gpfg |>
filter(country == "China") |>
group_by(industry) |>
summarise(market_value_usd = sum(market_value_usd)) |>
arrange(desc(market_value_usd)) |>
slice_head(n = 5)
china_industriesRead the pipeline from top to bottom: narrow the rows, form the groups, calculate one value for each group, order the results, and keep the first five.
6.8 Questions for later chapters
The annual file cannot answer every kind of question by itself.
A relationship question might ask whether ownership percentage and market value tend to vary together. A scatterplot can reveal a possible pattern, but it cannot by itself show that one variable caused the other.
A trend question requires comparable observations from several dates. The multi-year chapter will ask how totals and shares changed over time and will explain why a change in year-end holdings is not necessarily an investment return or purchase.
6.9 From a result to a finding
A useful finding says what was measured, for whom or where, and at what time. Compare these statements:
- Too broad: “The United States received the most Norwegian investment.”
- Better: “The United States had the largest reported market value in NBIM’s year-end equity-holdings file.”
The second sentence matches the data. The file contains year-end holdings, not transactions, so it cannot show how much money was sent or received during the year.
Use this simple reporting ladder:
| Type of statement | What the data need |
|---|---|
| Description | A correctly calculated value |
| Comparison | Comparable groups and a clear measure |
| Trend | Several comparable time points |
| Explanation | Additional evidence about why the pattern occurred |
6.10 Practice
Choose either country, region, or industry and write one precise comparison question. Then create a summary containing:
- the number of holding records;
- total market value in Norwegian kroner;
- median holding value; and
- percentage share of the full market value.
Order the table by total market value. Write three sentences:
- Identify whether your question is descriptive, ranking, or comparison.
- State one finding that the table supports.
- State one explanation that would require more reporting and evidence.
6.11 Takeaways
| Function | What it does |
|---|---|
sum() |
Calculates a total |
mean() |
Calculates an arithmetic average |
median() |
Finds the middle value |
min() and max() |
Find the smallest and largest values |
arrange(desc(...)) |
Creates a ranking from largest to smallest |
group_by() + summarise() |
Calculate statistics separately for each group |
filter() |
Narrows an analysis to rows that meet a condition |
mutate() |
Adds a share or another derived measure |
The official dplyr function reference contains more summary and ranking tools. Add them only when a reporting question requires them.