Multiline axis labels allow better visualization of long categorical values. Instead of overcrowding the axis, labels can now be formatted across multiple lines, enhancing readability.
import kotlin.random.Random
%useLatestDescriptors
%use dataframe
%use lets-plot
// Create a DataFrame with artificial income and expenses
val years = listOf(2022, 2023, 2024)
val quarters = listOf("Q1", "Q2", "Q3", "Q4")
val quarterYears = mutableListOf<String>()
val types = mutableListOf<String>()
val amounts = mutableListOf<Int>()
for (year in years) {
val baseIncome = Random.nextInt(5000, 15000)
val baseExpenses = baseIncome * Random.nextDouble(0.6, 0.9)
for (quarter in quarters) {
val income = baseIncome + Random.nextInt(-2000, 2000)
val expenses = baseExpenses + Random.nextInt(-1500, 1500)
val quarterYear = "$quarter-$year"
quarterYears.add(quarterYear)
types.add("Income")
amounts.add(income.toInt())
quarterYears.add(quarterYear)
types.add("Expenses")
amounts.add(expenses.toInt())
}
}
val df = dataFrameOf("Quarter_Year" to quarterYears, "Type" to types, "Amount" to amounts)
df.head(4)
DataFrame: rowsCount = 4, columnsCount = 3
Quarter_Year | Type | Amount |
---|---|---|
Q1-2022 | Income | 15425 |
Q1-2022 | Expenses | 7232 |
Q2-2022 | Income | 13012 |
Q2-2022 | Expenses | 8337 |
// Multiline labels for X-axis
val xLabelsMapping = years.flatMap { year ->
quarters.map { quarter -> if (quarter == "Q1") "$quarter\n$year" else quarter }
}
letsPlot(df.toMap()) {
x = "Quarter_Year"
y = "Amount"
color = "Type"
} +
geomLine(size = 1.5) +
geomPoint(size = 4.0) +
scaleXDiscrete(labels = xLabelsMapping) +
ggtitle("Quarterly Income vs Expenses") +
xlab("Quarters") +
ylab("Amount ($)") +
theme(axisTextX = elementText(angle = 30))