Работа с данными
На этой странице описано, как агрегировать, форматировать, сортировать, фильтровать и предварительно обрабатывать данные в Pivot. Инструкции по загрузке и экспорту данных см. в разделах Загрузка данных и Экспорт данных.
Определение полей
Используйте свойство fields, чтобы объявить поля, которые Pivot может размещать в строках, столбцах и значениях. Каждый элемент массива fields описывает одно поле — его идентификатор, метку и тип данных.
Следующий фрагмент кода инициализирует Pivot с пятью полями:
const table = new pivot.Pivot("#root", {
fields: [
{ id: "year", label: "Year", type: "number" },
{ id: "continent", label: "Continent", type: "text" },
{ id: "form", label: "Form", type: "text" },
{ id: "oil", label: "Oil", type: "number" },
{ id: "balance", label: "Balance", type: "number" }
],
data,
config: {...}
});
Применение форматов к полям
Pivot применяет формат по умолчанию к числовым полям и полям дат на основе текущей локали. Подробнее см. в разделах Форматирование дат и Форматирование чисел.
Чтобы переопределить формат по умолчанию для конкретного поля, задайте параметр format свойства fields.
Форматирование числовых полей
Используйте prefix и suffix, чтобы добавить текст вокруг числовых значений, и maximumFractionDigits, чтобы управлять точностью десятичных знаков. Например, чтобы отображать 12.345 как "12.35 EUR", задайте суффикс " EUR" и maximumFractionDigits равным 2:
const fields = [
{ id: "sales", type: "number", format: { suffix: " EUR", maximumFractionDigits: 2 } },
];
Форматирование по умолчанию ограничивает числовые поля тремя знаками после запятой и применяет разделение групп к целой части. Чт обы полностью отключить форматирование, задайте format значение false:
const fields = [
{ id: "year", label: "Year", type: "number", format: false },
];
В примере ниже поля marketing, profit и sales помечены как денежные с префиксом $ и фиксированными двумя десятичными знаками:
// инициализация Pivot с предопределённым набором данных и полями
new pivot.Pivot("#pivot", {
data,
config: {
rows: ["state", "product_type"],
columns: [],
values: [
{ field: "marketing", method: "sum" },
// другие значения
],
},
fields:[
// пользовательский формат
{ id: "marketing", label: "Marketing", type:"number", format:{
prefix: "$", minimumFractionDigits: 2, maximumFractionDigits: 2 }
}
]
});
Форматирование полей дат
Чтобы переопределить общий dateFormat локали для отдельного поля, задайте параметр format свойства fields в виде строки формата даты.
Следующий фрагмент кода задаёт "%M %d, %Y" в качестве формата для поля date:
const fields = [
{ id: "date", type: "date", format: "%M %d, %Y" },
];
В примере ниже строковые даты преобразуются в объекты Date, после чего Pivot инициализируется с форматом "%d %M %Y %H:%i" для поля date. Значения поля отображаются в виде меток, например "24 April 2025 14:30".
// преобразование строковых дат в объекты Date
const dateFields = fields.filter(f => f.type === "date");
dataset.forEach(item => {
dateFields.forEach(f => {
const v = item[f.id];
if (typeof v === "string") {
item[f.id] = new Date(v);
}
});
});
// инициализация Pivot с полевым форматом даты
new pivot.Pivot("#pivot", {
data,
config: {
rows: ["state"],
columns: ["product_type"],
values: [
{ field: "date", method: "min" },
{ field: "profit", method: "sum" },
{ field: "sales", method: "sum" }
]
},
fields:[
// пользовательский формат: День Месяц Год Часы:Минуты
{ id: "date", label: "Date", type: "date", format: "%d %M %Y %H:%i" }
]
});
Для формата экспорта xlsx Pivot экспортирует поля дат и числовые поля как необработанные значения с форматом по умолчанию (или форматом, заданным через свойство fields). Если для поля задан шаблон (см. свойство tableShape), Pivot экспортирует отрисованное значение, полученное этим шаблоном. Если заданы и template, и format, шаблон имеет приоритет над форматом.
Определение структуры Pivot
Используйте свойство config, чтобы объявить, какие поля отображаются как строки, столбцы и а грегированные значения, а также как фильтруются данные. Свойство config не имеет предопределённых значений — вы должны задать его для отображения любых данных. Полный список параметров см. в справочнике config.
Следующий фрагмент кода помещает continent и name в строки, year — в столбцы, три агрегации — в значения и добавляет фильтр по name:
const table = new pivot.Pivot("#root", {
fields,
data,
config: {
rows: ["continent", "name"],
columns: ["year"],
values: [
"count(oil)",
{ field: "oil", method: "sum" },
{ field: "gdp", method: "sum" }
]
},
fields,
filters: {
name: {
contains: "B"
}
}
});
Сортировка данных
Pivot поддерживает сортировку во всех трёх областях (значения, столбцы, строки) в процессе агрегации. В интерфейсе пользователи нажимают на заголовок столбца для сортировки.
Чтобы задать сортировку по умолчанию, используйте параметр sort свойства fields. Параметр принимает "asc", "desc" или пользовательскую функцию сравнения.
В примере ниже над Pivot отображаются кликабельные метки полей, и при нажатии направление сортировки переключается:
const bar = document.getElementById("bar");
let sorted = ["studio", "genre"];
setFields();
bar.addEventListener('click', (e) => switchSort(e.target.id), false);
function setFields(){
let html = "";
let sortedFields = fields.filter(f => (sorted.indexOf(f.id) != -1));
sortedFields.forEach((f) =>{
const order = f.sort || "asc";
html += `<div className="field" id="${f.id}">
${f.label}<i className="icon wxi-${order}" ></i>
</div>`;
});
bar.innerHTML = html;
}
function switchSort(id){
fields.forEach(f => {
if(f.id == id){
f.sort = f.sort != "desc" ? "desc" : "asc";
}
});
// обновление полей Pivot
table.setConfig({ fields });
// обновление иконок
setFields(bar, fields);
}
const table = new pivot.Pivot("#root", {
fields,
data: dataset,
config: {
rows: [
"studio",
"genre"
],
values: [
{
field: "title",
method: "count"
},
{
field: "score",
method: "max"
}
]
}
});
Сортировка в интерфейсе включена по умолчанию. Чтобы отключить её, задайте параметр sort свойства columnShape равным false.
Следующий фрагмент кода отключает сортировку в интерфейсе:
const table = new pivot.Pivot("#root", {
fields,
data,
config: {
rows: ["studio", "genre"],
columns: [],
values: [
{
field: "title",
method: "count"
},
{
field: "score",
method: "max"
}
]
},
columnShape: {
sort: false
}
});
Фильтрация данных
Pivot поддерживает фильтры, привязанные к типам данных полей. Фильтры задаются через интерфейс Pivot после инициализации или декларативно через объект filters свойства config.
В интерфейсе фильтры отображаются в виде выпадающих списков для каждого поля.
Типы фильтров
Pivot поддерживает следующие условия фильтрации по типам данных:
- текстовые поля —
equal,notEqual,contains,notContains,beginsWith,notBeginsWith,endsWith,notEndsWith,includes - числовые поля —
equal,notEqual,greater,greaterOrEqual,less,lessOrEqual,contains,notContains,beginsWith,notBeginsWith,endsWith,notEndsWith - поля дат —
equal,notEqual,greater,greaterOrEqual,less,lessOrEqual,between,notBetween,includes
Правило includes ограничивает фильтр конкретным набором допустимых значений.
Добавление фильтра
Чтобы объявить фильтр, добавьте объект filters в свойство config, используя идентификатор поля в качестве ключа. Каждое значение — объект с условиями фильтрации.
Следующий фрагмент кода применяет два фильтра — один по genre (значения, содержащие "D", ограниченные значением "Drama") и один по title (значения, содержащие "A"):
const table = new pivot.Pivot("#root", {
fields,
data: dataset,
config: {
rows: ["studio", "genre"],
values: [
{
field: "title",
method: "count"
},
{
field: "score",
method: "max"
}
],
filters: {
genre: {
contains: "D",
includes: ["Drama"]
},
title: {
// фильтр для другого поля ("title")
contains: "A"
}
}
}
});
Чтобы фильтровать данные через API виджета Table, получите экземпляр Table с помощью метода getTable и используйте событие filter-rows.
Ограничение загружаемых данных
Чтобы предотвратить зависание компонента на очень больших наборах данных, ограничьте количество строк и столбцов в итоговом наборе с помощью свойства limits. Pivot прерывает отрисовку по достижении лимита. По умолчанию лимит составляет 10000 строк и 5000 столбцов.
Лимиты применяются к большим наборам данных. Числа приблизительны — Pivot не гарантирует точного количества строк/столбцов.
Следующий фрагмент кода ограничивает набор данных 10 строками и 3 столбцами:
const table = new pivot.Pivot("#root", {
fields,
data: dataset,
config: {
rows: ["studio"],
columns: ["genre"],
values: [
{
field: "title",
method: "count"
},
{
field: "score",
method: "max"
}
]
},
limits: { rows: 10, columns: 3 }
});
Применение математических методов
Методы по умолчанию
Pivot включает следующие встроенные методы агрегации:
sum(только числовые значения) — суммирует все выбранные значения; игнорирует пустые ячейки, логические значения вродеTRUEи текстmin(числовые значения и даты) — возвращает минимальное значение; игнорирует пустые ячейки, логические значения и текст. Возвращает0, если во входных данных нет чиселmax(ч исловые значения и даты) — возвращает максимальное значение; игнорирует пустые ячейки, логические значения и текст. Возвращает0, если во входных данных нет чиселcount(числовые, текстовые значения и даты) — считает непустые ячейки; это метод по умолчанию, назначаемый каждому вновь добавленному полюcountunique(числовые и текстовые значения) — считает количество уникальных значений во входных данныхaverage(только числовые значения) — вычисляет среднее арифметическое; игнорирует пустые ячейки, логические значения и текст. Включает ячейки со значением нольcounta(числовые, текстовые значения и даты) — считает все непустые значения, включая числа, даты и текстmedian(только числовые значения) — возвращает медиану входных данныхproduct(только числовые значения) — возвращает произведение всех чисел во входных данныхstdev(только числовые значения) — стандартное отклонение, при котором входные данные рассматриваются как выборка из большей совокупностиstdevp(только числовые знач ения) — стандартное отклонение, при котором входные данные рассматриваются как вся генеральная совокупностьvar(только числовые значения) — дисперсия, при которой входные данные рассматриваются как выборка из большей совокупностиvarp(только числовые значения) — дисперсия, при которой входные данные рассматриваются как вся генеральная совокупность
Следующий фрагмент кода показывает определения встроенных методов:
const defaultMethods = {
sum: { type: "number", label: "sum" },
min: { type: ["number", "date"], label: "min" },
max: { type: ["number", "date"], label: "max" },
count: {
type: ["number", "date", "text"],
label: "count",
branchMath: "sum"
},
counta: {
type: ["number", "date", "text"],
label: "counta",
branchMath: "sum"
},
countunique: {
type: ["number", "text"],
label: "countunique",
branchMath: "sum"
},
average: { type: "number", label: "average", branchMode: "raw" },
median: { type: "number", label: "median", branchMode: "raw" },
product: { type: "number", label: "product" },
stdev: { type: "number", label: "stdev", branchMode: "raw" },
stdevp: { type: "number", label: "stdevp", branchMode: "raw" },
var: { type: "number", label: "var", branchMode: "raw" },
varp: { type: "number", label: "varp", branchMode: "raw" }
};
Применяйте метод по умолчанию через параметр values свойства config. См. раздел Определение значений.
Следующий фрагмент кода назначает count полю title и max полю score:
const table = new pivot.Pivot("#root", {
fields,
data,
config: {
rows: ["studio", "genre"],
columns: [],
values: [
{
// идентификатор поля
field: "title",
// метод
method: "count"
},
{
id: "score",
method: "max"
}
]
}
});
Определение значений
Каждую запись в values можно задать в одной из двух равнозначных форм:
- строка вида
"operation(fieldID)" - объект
{ field: string, method: string }(оба поля обязательны)
Следующий фрагмент кода использует обе формы в одном массиве values:
values: [
"sum(sales)", // первый вариант
{ field: "sales", method: "sum" } // второй вариант
]
Переопределение метода по умолчанию
Для каждого вновь добавленного поля Pivot назначает первый доступный метод для данного типа данных. Чтобы изменить это поведение, перехватите событие add-field с помощью метода api.intercept.
В примере ниже выполняется перехват add-field и принудительно устанавливается метод max при добавлении числового поля:
const table = new pivot.Pivot("#root", {
fields,
data: dataset,
config: {
rows: ["studio", "genre"],
columns: [],
values: [
{
field: "title",
method: "count",
},
{
field: "score",
method: "max",
},
],
},
});
// переопределение метода по умолчанию для вновь добавляемых числовых полей
table.api.intercept("add-field", (ev) => {
const { fields } = table.api.getState();
const type = fields.find((f) => f.id == ev.field).type;
if (ev.area == "values" && type == "number") {
ev.method = "max";
}
});
Добавление пользовательских математических методов
Чтобы добавить пользовательский метод агрегации, используйте свойство methods. Каждая запись связывает имя метода (ключ) с объектом конфигурации, содержащим фу нкцию handler и метаданные. Функция handler принимает массив значений и возвращает одно агрегированное значение.
В примере ниже добавляются два метода, специфичных для дат. countunique_date считает уникальные даты по их числовым меткам времени. average_date возвращает среднюю дату путём усреднения меток времени:
function countUnique(values, converter) {
const valueMap = {};
return values.reduce((acc, d) => {
if (converter) d = converter(d);
if (!valueMap[d]) {
acc++;
valueMap[d] = true;
}
return acc;
}, 0);
}
const methods = {
countunique_date: {
handler: values => countUnique(values, v => new Date(v).getTime()),
type: "date",
label: "CountUnique",
},
average_date: {
type: "date",
label: "Average",
branchMode: "raw",
handler: values => {
if (!values.length) return null;
const sum = values.reduce((acc, d) => acc + d.getTime(), 0);
const avgTime = sum / values.length;
return new Date(avgTime);
}
}
};
// показывать целые числа для результатов "count" и "unique count"
const templates = {};
fields.forEach(f => {
if (f.type == "number")
templates[f.id] = (v, method) =>
v && method.indexOf("count") < 0 ? parseFloat(v).toFixed(3) : v;
});
// преобразование строковых дат в объекты Date
const dateFields = fields.filter(f => f.type == "date");
if (dateFields.length) {
dataset.forEach(item => {
dateFields.forEach(f => {
const v = item[f.id];
if (typeof v == "string") item[f.id] = new Date(v);
});
});
}
const table = new pivot.Pivot("#root", {
fields,
data: dataset,
tableShape: { templates },
methods: { ...pivot.defaultMethods, ...methods },
config:{
rows: ["state"],
columns: [
"product_line",
"product_type"
],
values: [
{
field: "sales",
method: "sum"
},
{
field: "sales",
method: "count"
},
{
field: "date",
method: "countunique_date"
},
{
field: "date",
method: "average_date"
}
]
}
});
Обработка данных с помощью предикатов
Предикаты — это функции предварительной обработки, которые преобразуют исходные данные полей до того, как Pivot использует их в строках или столбцах. Например, предикат может группировать даты по месяцам перед агрегацией.
Следующий фрагмент кода показывает встроенные предикаты дат, применяемые Pivot по умолчанию:
const defaultPredicates = {
year: { label: "Year", type: "date", filter: { type: "number" } },
quarter: { label: "Quarter", type: "date", filter: { type: "tuple" } },
month: { label: "Month", type: "date", filter: { type: "tuple" } },
week: { label: "Week", type: "date", filter: { type: "tuple" } },
day: { label: "Day", type: "date", filter: { type: "number" } },
hour: { label: "Hour", type: "date", filter: { type: "number" } },
minute: { label: "Minute", type: "date", filter: { type: "number" } }
};
Чтобы добавить пользовательский предикат, настройте свойство predicates. Каждая запись связывает идентификатор предиката (ключ) с объектом конфигурации:
type— типы полей, которые принимает предикат ("number","date","text"или массив)label— метка предиката, отображаемая в выпадающем списке GUI для строки/столбцаhandler— функция, преобразующая значение и возвращающая обработанное значениеtemplate— необязательная функция, управляющая отображением обработанного значенияfield— необязательная функция, ограничивающая предикат конкретными полямиfilter— необязательная конфигурация фильтра, если тип фильтра должен отличаться отtypeили формат данных должен отличаться отtemplate
Чтобы использовать пользовательский предикат, задайте его идентификатор как method строки или столбца, к которым предикат долже н применяться.
Следующий фрагмент кода регистрирует два пользовательских предиката (monthYear и profitSign) и применяет их в конфигурации columns:
const predicates = {
monthYear: {
label: "Month-year",
type: "date",
handler: (d) => new Date(d.getFullYear(), d.getMonth(), 1),
template: (date, locale) => {
const months = locale.getRaw().calendar.monthFull;
return months[date.getMonth()] + " " + date.getFullYear();
},
},
profitSign: {
label: "Profit Sign",
type: "number",
filter: {
type: "tuple",
format: (v) => (v < 0 ? "Negative" : "Positive"),
},
field: (f) => f === "profit",
handler: (v) => (v < 0 ? -1 : 1),
template: (v) => (v < 0 ? "Negative profit" : "Positive profit"),
},
};
// преобразование строковых дат в объекты Date
const dateFields = fields.filter((f) => f.type == "date");
if (dateFields.length) {
dataset.forEach((item) => {
dateFields.forEach((f) => {
const v = item[f.id];
if (typeof v == "string") item[f.id] = new Date(v);
});
});
}
const table = new pivot.Pivot("#pivot", {
fields,
data: dataset,
predicates: { ...pivot.defaultPredicates, ...predicates },
tableShape: { tree: true },
config: {
rows: ["product_type", "product"],
columns: [
{ field: "profit", method: "profitSign" },
{ field: "date", method: "monthYear" },
],
values: ["sales", "expenses"],
},
});
Добавление столбцов и строк с итоговыми значениями
Используйте свойство tableShape, чтобы отрисовать итоговый столбец справа (totalColumn: true) или итоговую строку-футер (totalRow: true).
Следующий фрагмент кода включает и итоговый столбец, и итоговую строку:
const table = new pivot.Pivot("#root", {
tableShape: {
totalRow: true,
totalColumn: true
},
fields,
data,
config: {
rows: ["studio"],
columns: ["type"],
values: [
{
field: "score",
method: "max"
},
{
field: "episodes",
method: "count"
},
{
field: "rank",
method: "min"
},
{
field: "members",
method: "sum"
}
]
}
});
Пример
Фрагмент ниже применяет пользовательские математические операции:
Связанные примеры: