Документация Engee

Работа с большими данными через WorkspaceArray

Назначение WorkspaceArray

WorkspaceArray — это структура для работы с большими временными рядами (например, результатами симуляции). Она реализует методы, позволяющие осуществлять итерации без полной выгрузки данных в память. Это достигается разделением данных на части (чанки, chunks), которые могут быть обработаны независимо от остальных.

Большие данные (Big Data) — это большие массивы данных, работа с которыми с помощью обычных методов зачастую неэффективна. Объем таких данных может значительно превышать максимальный объем оперативной памяти Engee. Структура WorkspaceArray помогает не заполнить оперативную память, разбивая массивы больших данных на части.

WorkspaceArray делит данные на части размером не более 200 Мб, и работает единовременно только с одной из них, что позволяет не бояться переполнения памяти Engee. WorkspaceArray создается после симуляции модели с блоком To Workspace или вручную пользователем.

Факт того, что при работе с данными вы можете создать WorkspaceArray, еще не значит, что эти данные являются большими. Одна из задач WorkspaceArray — это удобное представление данных, полезное и в работе с массивами данных обычного размера.

Поэтому, даже если массивы ваших данных не являются большими, вы можете работать со структурой WorkspaceArray в следующих сценариях:

  1. Экспортируйте WorkspaceArray в CSV формат.

  2. Используйте функции для управления WorkspaceArray в зависимости от ваших задач.

  3. Используйте WorkspaceArray в моделировании с помощью блоков To Workspace и From Workspace.

Создание WorkspaceArray

Создание WorkspaceArray возможно как напрямую, через DataFrame, так и из CSV-файла. Для этого в Engee используются два конструктора:

  • Конструктор DataFrame — записывает WorkspaceArray через структуру DataFrame.

  • Конструктор CSV — записывает WorkspaceArray с помощью CSV-файла.

Конструкторы в Julia — это специальные функции, которые используются для создания новых объектов определенных типов. Конструкторы определяют, каким образом объекты должны быть инициализированы при создании.

Расскажем об этих конструкторах подробнее, но сперва создадим DataFrame.

Создание DataFrame

DataFrame — это структура данных, предоставляемая пакетом DataFrames.jl и является таблицей с метками строк и столбцов. DataFrame используется для организации и обработки данных в виде таблицы, где каждый столбец представляет собой переменную или признак, а каждая строка — отдельное наблюдение или запись (например, значение в момент времени). DataFrame обеспечивает удобный доступ к данным и может быть обработан различными методами в Julia.

Создадим DataFrame, задав столбцы time (значения времени) и value (значения):

using DataFrames # подключаем модуль DataFrames
times = [2 ^ i for i in LinRange(1, 3, 1000)]
values = [sin(i ^ 2 + 1) * 2 + cos(i) for i in times]
data_frame = DataFrame(time = times, value = values) # создадим DataFrame с двумя столбцами — time и value

Разберем код создания DataFrame:

  1. Создается массив times, который содержит 1000 элементов. Значения элементов генерируются с помощью функции 2 ^ i, где i изменяется в диапазоне от 1 до 3 с равными интервалами. Следовательно, LinRange(1, 3, 1000) создает равномерно распределенный диапазон от 1 до 3 с 1000 элементами, а затем для каждого значения из этого диапазона вычисляется значение .

  2. Создается массив values, который содержит 1000 элементов. Значения элементов вычисляются на основе значений из массива times. Для каждого значения i из массива times вычисляется синус от квадрата этого значения, к результату добавляется 1, затем полученное число умножается на 2 и добавляется к косинусу значения i.

  3. Массивы используются для создания DataFrame с двумя столбцами: time (время) и value (значение), где каждый столбец — это значения массивов times и values соответственно.

Структура WorkspaceArray содержит несколько пользовательских полей:

  • :time и :value — предоставляют новую структуру WorkspaceArray с соответствующей пометкой времени и значения. Поле value может быть не только скаляром, но и многомерным массивом.

  • :name — идентификатор, который помогает определить, к какому прогону относится переменная в случае, если WorkspaceArray получен из блока To Workspace.

Получив DataFrame, используем его конструктор, чтобы создать WorkspaceArray. Рассмотрим его подробнее.

Создание WorkspaceArray из конструктора DataFrame

Перед началом работы с WorkspaceArray нам необходимо создать структуру данных DataFrame, представленную в виде таблицы.

Данный конструктор невозможно использовать без создания DataFrame.

Конструктор DataFrame предназначен для записи WorkspaceArray через DataFrame. Два столбца time и value должны удовлетворять условиям:

  • time — не должен содержать значения типа Any.

  • value — не должен быть типа Any.

  • value — должен быть наследником одного из поддерживаемых типов данных: Matrix{<:Number}, Vector{<:Number}, или Number.

Применим DataFrame конструктор для создания WorkspaceArray через переменную my_workspacearray:

my_workspacearray = WorkspaceArray("my_data_frame", data_frame)
Вывод
WorkspaceArray("my_data_frame")

Рассмотрим код конструктора:

  • Создается переменная my_workspacearray типа WorkspaceArray.

  • Переменная содержит данные из data_frame (созданный нами DataFrame).

  • Массив данных из data_frame стал доступен в рабочем пространстве Engee под именем "my_data_frame".

В результате выполнения кода, данные из data_frame будут доступны в рабочей области Engee под именем "my_data_frame", что позволит обращаться к этим данным с помощью переменной my_workspacearray.

Создание WorkspaceArray из конструктора CSV

Конструктор CSV предназначен для создания WorkspaceArray из файла формата CSV. Рассмотрим этот конструктор:

workspacecsv = WorkspaceArray("workspacearray_csv", "/user/workspacearray_csv.csv") # где "/user/workspacearray_csv.csv" — путь до CSV-файла, а "workspacearray_csv" — его имя
Вывод
WorkspaceArray("workspacearray_csv")

В коде создается новый WorkspaceArray с именем workspacecsv, в который загружаются данные из CSV файла workspacearray_csv.csv.

CSV файл, из которого создается WorkspaceArray, должен содержать разделители, указанные в разделе Экспорт WorkspaceArray в CSV.

Использование WorkspaceArray

Экспорт WorkspaceArray в CSV

Для экспорта WorkspaceArray в файл формата CSV используем структуру DataFrame (наш data_frame) следующим образом:

using CSV # подключаем модуль CSV
CSV.write("/user/workspacearray_csv.csv", delim="\t", data_frame)
Использование параметра delim="\t (создание разделителя с табуляцией) является обязательным условием для создания CSV файла из WorkspaceArray. Отсутствие параметра выдаст ошибку Ошибка при создании WorkspaceArray из csv: BoundsError и создаст пустой CSV файл.

Рассмотрим код:

  • Функция CSV.write() записывает данные из data_frame (названный нами DataFrame) в файл формата CSV с именем "workspacearray_csv.csv".

  • Параметр delim="\t" указывает, что в качестве разделителя столбцов будет использоваться табуляция.

Экспорт данных из WorkspaceArray в файл формата CSV может быть полезен по нескольким причинам:

  • Обмен данными — экспорт данных в CSV позволяет передавать информацию из WorkspaceArray другим пользователям или программам, которые могут обрабатывать этот формат.

  • Резервное копирование — экспорт данных в CSV формат может служить для создания резервной копии данных в случае сбоя работы программы.

Выгрузка данных в память

Вы можете сохранить все данные из WorkspaceArray в оперативную память Engee с помощью процедуры collect.

Использование процедуры collect не рекомендуется при работе с большими данными, так как это может привести к переполнению памяти в Engee.

В зависимости от указанных параметров, collect возвращает объект типа DataFrame со столбцами time и value (поля времени и значения). Также можете указать возвращение только одного из столбцов через вызов поля time или value. Для этого привяжите все данные WorkspaceArray к переменной. Например:

workspace_collected = collect(my_workspacearray)

После инициализации переменной с данными WorkspaceArray становятся доступны следующие команды:

collect(workspace_collected) # выводит WorkspaceArray с двумя столбцами time и value

collect(workspace_collected.time) # выводит один столбец time (время)

collect(workspace_collected.value) # выводит один столбец value (значение)

collect(workspace_collected.time[1]) # выводит первое значение из столбца time

collect(workspace_collected.value[1]) # выводит первое значение из столбца value

collect(pairs(workspace_collected)) # возвращает DataFrame с двумя столбцами индекс-значение

Функции WorkspaceArray

В структуре WorkspaceArray реализованы функции, описанные в AbstractVector. Рассмотрим основные функции взаимодействия с WorkspaceArray:

length — возвращает количество элементов в коллекции.

Функция length в Julia принимает в качестве аргумента коллекцию, для которой нужно определить длину.

Если вы хотите узнать длину строковой переменной, массива или любой другой коллекции, вы передаете эту коллекцию как аргумент функции length.

Использует конструкцию индексирования lastindex для получения последнего допустимого индекса коллекции.

Пример:

length(my_workspacearray) # my_workspacearray — переменная, содержащая данные о WorkspaceArray
Коллекции в Julia — это структуры данных, содержащие набор элементов, объединенных в одну сущность. Коллекции в Julia могут быть различных типов и предназначены для хранения, организации и управления данными. В зависимости от вида коллекции, она может быть либо изменяемой, либо неизменяемой.
size — определяет размерности массивов и других коллекций.

Возвращает кортеж, содержащий измерения my_workspacearray. По желанию можно указать измерение, чтобы получить длину только этого измерения.

Обратите внимание, что size может быть не определен для массивов с нестандартными индексами.

Для индекса size используется стиль индексации IndexStyle = IndexLinear().

Пример:

size(my_workspacearray) # my_workspacearray — переменная, содержащая данные о WorkspaceArray
axes — получает диапазоны индексов.

Возвращает кортеж, в котором каждый элемент представляет диапазон индексов для соответствующего измерения массива.

Пример:

axes(my_workspacearray) # my_workspacearray — переменная, содержащая данные о WorkspaceArray
getindex — возвращает подмножество.

Используется для доступа к элементам контейнеров (массивы, кортежи, словари и т. д.) по их индексу или ключу.

Пример:

getindex(my_workspacearray.time[1]) # выдаст значение времени первого time в WorkspaceArray
IndexStyle — задает собственный стиль индексирования.

При определении нового типа AbstractArray можно реализовать либо линейное индексирование (с помощью IndexLinear), либо декартово индексирование (с помощью IndexCartesian).

Если вы решили реализовать только линейное индексирование, вы должны указать этот момент для типа массива как = IndexLinear():

Пример:

Base.IndexStyle(my_workspacearray) = IndexLinear() # указание линейного индексирования

Стиль индексации всегда IndexLinear (структура, которая используется для представления линейных индексов элементов массива).

Внутренний механизм индексирования в Julia автоматически пересчитает все операции индексирования в предпочтительный стиль. Это позволит вам получить доступ к элементам массива, используя любой стиль индексирования, даже если явные методы не были предоставлены.

Пример:

IndexStyle(my_workspacearray) # выведет IndexLinear() (использует линейные индексы для доступа элементам)

IndexStyle(typeof(my_workspacearray)) # выведет IndexCartesian() (использует декартовы индексы для доступа к его элементам)
sizeof — получение размера объекта в памяти.

Используется для получения размера (в байтах) объекта в памяти. Размер объекта может быть полезной информацией при работе с большими данными или при оптимизации использования памяти.

Пример:

sizeof(collect(my_workspacearray))
iterate — продолжает выполнение итератора.

Продолжает выполнение итератора, чтобы получить следующий элемент. Если элементов не осталось, возвращается nothing. В ином случае возвращается двойной кортеж следующего элемента и новое состояние итерации. Дополнительные сведения об определении пользовательского итерируемого типа см. в разделе руководства, посвященном интерфейсу итерации.

Пример:

iterate(my_workspacearray, 5)
empty! — удаляет все элементы из collection.

Удаляет все элементы из collection:

Пример:

empty!(my_workspacearray) # создаст пустой упорядоченный словарь с ключами из целых чисел(Int64) и значений из массивов (Array)

Вывод

OrderedCollections.OrderedDict{Int64, Array}()
copy — создает поверхностную копию.

Создает поверхностную копию. Копируется внешняя структура, но не внутренние значения. Например, при копировании массива создается массив с теми же элементами, что и у исходного.

Пример:

copy(my_workspacearray)
similar — создание нового массива.

Используется для создания нового массива с такими же размерами, типом и, при необходимости, теми же свойствами распределения памяти, что и у существующего массива или другого подобного объекта.

Пример:

my_workspacearray1 = similar(my_workspacearray) # создает переменную my_workspacearray1, аналогичную my_workspacearray

WorkspaceArray для моделирования

WorkspaceArray также используется для передачи данных между моделью и рабочей областью. Для этого в модели можно использовать блоки:

  • Блок To Workspace записывает данные входного сигнала в рабочую область Engee. Результатом записи данных является переменная с типом WorkspaceArray. Имя переменной задается параметром Variable name в настройках блока, а сам блок поддерживает только числа скалярных и многомерных данных.

  • Блок From Workspace считывает данные из рабочей области и представляет их в виде сигнала. Блок From Workspace считывает данные из рабочей области только с типом WorkspaceArray. В зависимости от загружаемых данных выходной сигнал может быть скалярным, векторным или многомерным. Блок From Workspace поддерживает загрузку скалярных и многомерных данных, как и блок To Workspace. From Workspace также используется для передачи данных в любую модель или подсистему в рабочей области, доступной данной модели или подсистеме.

Отдельно отметим переменную simout, которая хранит результаты симуляции модели и имеет тип данных SimulationResult. В этом типе данных хранятся пары "ключ-значение", где ключом является путь по типу "модель/система/блок/номер порта", а значением – WorkspaceArray. Такие пары создаются для каждого залогированного сигнала и формируют структуру данных DataFrame, автоматически заполненную данными результатов симуляции. Подробнее о переменной simout читайте здесь.

Блоки To Workspace и From Workspace работают только с переменными типа WorkspaceArray (считывают данные только из этого конкретного типа).

Пример использования WorkspaceArray с блоками To Workspace и From Workspace смотрите здесь.