Group and count
For an orders file with customer and amount, produce one row per customer with an order count and total amount:
package main
import (
"log"
"github.com/osvik/simplecsv"
)
func main() {
orders, err := simplecsv.ReadCsvFileE("orders.csv")
if err != nil {
log.Fatal(err)
}
report, err := orders.GroupByE(
[]string{"customer"},
[]simplecsv.Agg{
{Op: simplecsv.AggCount, As: "orders"},
{Field: "amount", Op: simplecsv.AggSum, As: "total_amount"},
},
)
if err != nil {
log.Fatal(err)
}
report, ok := report.SortByFields(
[]string{"total_amount", "customer"},
[]bool{false, true},
)
if !ok {
log.Fatal("could not sort report")
}
if err := report.WriteCsvFileE("customer-summary.csv"); err != nil {
log.Fatal(err)
}
}Groups appear in first-seen order before the optional sort. This makes an unsorted report stable and keeps output changes easy to understand.
Available aggregations
| Operation | Behavior | Field |
|---|---|---|
AggCount |
Counts rows in the group. | Ignored |
AggSum |
Adds values parsed with strconv.ParseFloat. Non-numeric cells count as zero. |
Required |
AggMin / AggMax |
Uses finite numeric values only. Empty when no finite value exists. | Required |
AggFirst / AggLast |
Selects the first or last cell in group order. | Required |
AggJoin |
Joins non-empty values with a comma. | Required |
Inspect before grouping
Use Distinct when you need first-seen category values:
statuses, ok := orders.Distinct("status")
if !ok {
log.Fatal("status field not found")
}
fmt.Println(statuses)Use ValueCounts when the frequency table itself is the output:
counts, ok := orders.ValueCounts("status")
if !ok {
log.Fatal("status field not found")
}Control report order
SortByFields is stable and accepts one direction per field. An empty direction slice means ascending for every field.
sorted, ok := report.SortByFields(
[]string{"country", "city"},
[]bool{true, true},
)