Skip to content

Commit

Permalink
Add SeriesList.SumSeries() to create a Sum of the series
Browse files Browse the repository at this point in the history
This can be useful when needing to understand the global statistics (for example wanting to do additional analysis on a stacked series).
  • Loading branch information
jentfoo committed Jan 31, 2025
1 parent e176420 commit 84589a5
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 19 deletions.
34 changes: 29 additions & 5 deletions series.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,13 +126,17 @@ func (sl SeriesList) init() {
func (sl SeriesList) Filter(chartType string) SeriesList {
arr := make(SeriesList, 0, len(sl))
for index, item := range sl {
if item.Type == chartType || (chartType == ChartTypeLine && item.Type == "") {
if chartTypeMatch(chartType, item.Type) {
arr = append(arr, sl[index])
}
}
return arr
}

func chartTypeMatch(expected, actual string) bool {
return expected == "" || expected == actual || (expected == ChartTypeLine && actual == "")
}

func (sl SeriesList) getYAxisCount() int {
for _, series := range sl {
if series.YAxisIndex == 1 {
Expand Down Expand Up @@ -442,12 +446,32 @@ func (sl SeriesList) Names() []string {
return names
}

// SumSeries will return a single Series which represents the sum of the entire SeriesList. This is useful for
// providing global statistics through Series.Summary().
func (sl SeriesList) SumSeries() Series {
return sl.makeSumSeries("")
}

func (sl SeriesList) makeSumSeries(chartType string) Series {
var result Series
result := Series{
Type: chartType,
}
// check for fast path result
switch len(sl) {
case 0:
return result
case 1:
if chartTypeMatch(chartType, sl[0].Type) {
return sl[0]
} else {
return result
}
}

sumValues := make([]float64, sl.getMaxDataCount(chartType))
for _, s := range sl {
if chartType == "" || s.Type == chartType || (chartType == ChartTypeLine && s.Type == "") {
result = s
if chartTypeMatch(chartType, s.Type) {
result = s // ensure other series values are set into the result
for i := range s.Data {
sumValues[i] += s.Data[i]
}
Expand All @@ -460,7 +484,7 @@ func (sl SeriesList) makeSumSeries(chartType string) Series {
func (sl SeriesList) getMaxDataCount(chartType string) int {
result := 0
for _, s := range sl {
if chartType == "" || s.Type == chartType || (chartType == ChartTypeLine && s.Type == "") {
if chartTypeMatch(chartType, s.Type) {
count := len(s.Data)
if count > result {
result = count
Expand Down
72 changes: 58 additions & 14 deletions series_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,10 @@ func TestNewSeriesListDataFromValues(t *testing.T) {
assert.Equal(t, SeriesList{
{
Type: ChartTypeBar,
Data: []float64{
1.0,
},
Data: []float64{1.0},
},
}, NewSeriesListBar([][]float64{
{
1,
},
{1},
}))
}

Expand All @@ -41,6 +37,58 @@ func TestSeriesLists(t *testing.T) {
assert.InDelta(t, float64(1), min, 0)
}

func TestSumSeries(t *testing.T) {
t.Parallel()

t.Run("empty", func(t *testing.T) {
var sl SeriesList
result := sl.SumSeries()

assert.Equal(t, "", result.Type)
assert.Empty(t, result.Data)
})

t.Run("single", func(t *testing.T) {
sl := SeriesList{
{
Type: ChartTypeLine,
Data: []float64{1.5, 2.5},
Name: "SingleLine",
YAxisIndex: 1,
Radius: "50%",
},
}

result := sl.SumSeries()

assert.Equal(t, sl[0], result)
})

t.Run("multiple", func(t *testing.T) {
sl := NewSeriesListLine([][]float64{
{1, 2, 3},
{4, 5, 6},
})

result := sl.SumSeries()

assert.Equal(t, ChartTypeLine, result.Type)
assert.Equal(t, []float64{5, 7, 9}, result.Data)
})

t.Run("unequal_data_length", func(t *testing.T) {
sl := NewSeriesListLine([][]float64{
{1, 2},
{3, 4, 5},
})

result := sl.SumSeries()

assert.Equal(t, ChartTypeLine, result.Type)
assert.Equal(t, []float64{4, 6, 5}, result.Data)
})
}

func TestSeriesSummary(t *testing.T) {
t.Parallel()

Expand Down Expand Up @@ -128,13 +176,9 @@ func TestSeriesSummary(t *testing.T) {
func TestFormatter(t *testing.T) {
t.Parallel()

assert.Equal(t, "a: 12%", labelFormatPie([]string{
"a",
"b",
}, "", 0, 10, 0.12))
assert.Equal(t, "a: 12%",
labelFormatPie([]string{"a", "b"}, "", 0, 10, 0.12))

assert.Equal(t, "10", labelFormatValue([]string{
"a",
"b",
}, "", 0, 10, 0.12))
assert.Equal(t, "10",
labelFormatValue([]string{"a", "b"}, "", 0, 10, 0.12))
}

0 comments on commit 84589a5

Please sign in to comment.