Объединение таблиц
Данные часто лежат в нескольких таблицах. Например, оценки за разные месяцы могут храниться отдельно, а сведения об учениках и их результатах могут быть в разных таблицах.
В DataFrame есть два основных способа объединения:
DataFrame.Concat(...)— добавить строки одной таблицы к строкам другой;Join(...)— соединить строки разных таблиц по общему ключу.
Оба способа возвращают новый DataFrame и не изменяют исходные таблицы.
Добавить строки
Заголовок раздела «Добавить строки»Concat используется, когда у таблиц одинаковые столбцы и их нужно поставить друг под друга.
uses MLABC;
begin var september := DataFrame.FromCsvText(''' Имя,Предмет,Балл Анна,Математика,91 Борис,Математика,76 ''');
var october := DataFrame.FromCsvText(''' Имя,Предмет,Балл Вера,Математика,84 Глеб,Математика,68 ''');
var allMarks := DataFrame.Concat(september, october);
allMarks.Print;end.Вывод:
Имя Предмет Балл Анна Математика 91Борис Математика 76 Вера Математика 84 Глеб Математика 68Для Concat схемы таблиц должны совпадать: имена столбцов, порядок, типы и categorical-флаги.
Соединить по ключу
Заголовок раздела «Соединить по ключу»Join используется, когда в разных таблицах есть общий ключевой столбец. Например, в одной таблице хранятся ученики и классы, а в другой — баллы.
uses MLABC;
begin var students := DataFrame.FromCsvText(''' Имя,Класс Анна,8А Борис,8Б Вера,8А ''');
var marks := DataFrame.FromCsvText(''' Имя,Балл Анна,91 Борис,76 Глеб,68 ''');
var res := students.Join(marks, 'Имя');
res.Print;end.По умолчанию используется inner join: в результат попадают только строки, для которых ключ найден в обеих таблицах. В примере Вера есть только в таблице students, а Глеб — только в таблице marks, поэтому они не попадут в результат обычного Join.
Оставить все строки слева
Заголовок раздела «Оставить все строки слева»Если нужно сохранить все строки из первой таблицы, используется jkLeft.
uses MLABC;
begin var students := DataFrame.FromCsvText(''' Имя,Класс Анна,8А Борис,8Б Вера,8А ''');
var marks := DataFrame.FromCsvText(''' Имя,Балл Анна,91 Борис,76 Глеб,68 ''');
var res := students.Join(marks, 'Имя', jkLeft);
res.Print;end.В таком соединении все ученики из students останутся в результате. Если для ученика нет строки в marks, значения из правой таблицы будут пропущенными.
Несколько ключей
Заголовок раздела «Несколько ключей»Иногда одной колонки для соединения недостаточно. Например, оценка задаётся не только именем ученика, но и предметом.
uses MLABC;
begin var plan := DataFrame.FromCsvText(''' Имя,Предмет,Класс Анна,Математика,8А Анна,Информатика,8А Борис,Математика,8Б Борис,Информатика,8Б ''');
var marks := DataFrame.FromCsvText(''' Имя,Предмет,Балл Анна,Математика,91 Анна,Информатика,96 Борис,Математика,76 ''');
plan.Join(marks, ['Имя', 'Предмет'], jkLeft).Print;end.Здесь строка считается совпавшей только тогда, когда совпали оба ключа: Имя и Предмет.
Разные имена ключей
Заголовок раздела «Разные имена ключей»Если ключевые столбцы называются по-разному, можно указать ключи левой и правой таблицы отдельно.
uses MLABC;
begin var students := DataFrame.FromCsvText(''' Код,Имя 1,Анна 2,Борис 3,Вера ''');
var marks := DataFrame.FromCsvText(''' student_id,Балл 1,91 2,76 ''');
students.Join(marks, ['Код'], ['student_id'], jkLeft).Print;end.Такой вариант полезен, когда таблицы пришли из разных источников и в них используются разные названия одного и того же идентификатора.
Пример с продажами
Заголовок раздела «Пример с продажами»В реальных данных часто одна таблица содержит операции, а другая — справочник товаров. Объединение добавляет к продажам цену и категорию товара.
uses MLABC;
begin var sales := DataFrame.FromCsvText(''' Товар,Количество Хлеб,2 Молоко,1 Яблоки,4 ''');
var products := DataFrame.FromCsvText(''' Товар,Категория,Цена Хлеб,Продукты,45.50 Молоко,Продукты,72.90 Яблоки,Продукты,58.25 ''');
sales.Join(products, 'Товар') .WithColumnFloat('Сумма', row -> row['Количество'] * row['Цена']) .Print;end.Расширенные варианты Join
Заголовок раздела «Расширенные варианты Join»Параметр JoinKind задаёт, какие строки попадут в результат:
jkInner— только совпавшие строки из обеих таблиц; используется по умолчанию.jkLeft— все строки из левой таблицы и найденные данные из правой.jkRight— все строки из правой таблицы и найденные данные из левой.jkFull— все строки из обеих таблиц.
var inner := students.Join(marks, 'Имя');var left := students.Join(marks, 'Имя', jkLeft);var right := students.Join(marks, 'Имя', jkRight);var full := students.Join(marks, 'Имя', jkFull);Если в правой таблице есть столбец с тем же именем, что и в левой, и это не ключ, в результате он получает префикс right_.
Что важно помнить
Заголовок раздела «Что важно помнить»Concatдобавляет строки и требует одинаковую схему таблиц.Joinсоединяет таблицы по ключевым столбцам.- Обычный
Joinбез третьего параметра — этоjkInner. - Для сохранения всех строк первой таблицы используйте
jkLeft. - Ключи можно задавать одним именем, массивом имён или двумя массивами, если имена ключей в таблицах разные.
- Исходные таблицы при объединении не изменяются.