Series Hack
Edit pageLast modified: 07 December 2023Sometimes you have several sources of data, and you want to visualize them by displaying color mapping from a group (i.e., color of plot objects corresponds to their group).
Let's assume we have three samples with different y-values and the same x-values
val xs = listOf(1, 2, 3, 4, 5)
val ysA = listOf(1.0, 2.5, 3.0, 3.5, 5.0)
val ysB = listOf(0.5, 1.5, 3.0, 1.5, 0.0)
val ysC = listOf(3.0, 5.0, 2.0, 3.0, 5.0)
So you can try something like that:
plot {
x(xs)
line {
y(ysA)
color = Color.RED
}
line {
y(ysB)
color = Color.GREEN
}
line {
y(ysC)
color = Color.BLUE
}
}
But unfortunately, "lets-plot" doesn't support it — legend is not displayed (because of Lets-Plot limitations). So you need to gather them into one layer. You need to change your data - add grouping variable (so now each point has exactly three parameters: x and y coordinates and its group).
plot {
line {
x(xs + xs + xs)
y(ysA + ysB + ysC)
color(xs.map { "A" } + xs.map { "B" } + xs.map { "C" })
}
}
DataFrame solution
In case a similar situation occurred with a dataframe, it is even easier to solve it with the gather
function
val df = dataFrameOf(
"xs" to xs,
"ysA" to ysA,
"ysB" to ysB,
"ysC" to ysC,
)
df
xs | ysA | ysB | ysC |
---|---|---|---|
1 | 1 | 0.5 | 3 |
2 | 2.5 | 1.5 | 5 |
3 | 3 | 3 | 2 |
4 | 3.5 | 1.5 | 3 |
5 | 5 | 0 | 5 |
For example, we cant to build several bars:
// Doesn't work - bars are overlapped, and we can't change that
df.plot {
x(xs)
bars {
y(ysA)
fillColor = Color.RED
}
bars {
y(ysB)
fillColor = Color.GREEN
}
bars {
y(ysC)
fillColor = Color.BLUE
}
}
val gatheredDF = df.gather {
ysA and ysB and ysC
}
.mapKeys { it.drop(2) } // Take group name as a key
.into(keyColumn = "group", valueColumn = "ys")
gatheredDF.head()
xs | group | ys |
---|---|---|
1 | A | 1 |
1 | B | 0.5 |
1 | C | 3 |
2 | A | 2.5 |
2 | B | 1.5 |
gatheredDF.plot {
bars {
x(xs)
y(ys)
fillColor(group)
}
}