Работа с WorkspaceArray в Engee
WorkspaceArray — это специальный тип данных в среде моделирования Engee, предназначенный для хранения и обработки временных рядов. Он реализует интерфейс AbstractArray языка Julia, но в отличие от стандартных массивов подгружает данные лениво (Lazy Loading).
WorkspaceArray не хранит данные целиком в оперативной памяти, а подгружает их по мере необходимости: например, при итерировании, обращении по индексу или преобразовании в таблицу. Это позволяет эффективно работать с очень большими наборами данных, которые не умещаются в память или поступают из внешних источников (например, из базы данных или файла).
WorkspaceArray в Engee используется в следующих сценариях:
-
Как результат симуляции — для хранения записываемых сигналов. Например, в переменной
simout(подробнее см. Программная обработка результатов симуляции в Engee); -
Для передачи данных между моделями через блоки В рабочую область и Из рабочей области;
-
Для импорта пользовательских временных рядов из CSV-файлов или таблиц (
DataFrame), которые затем можно использовать в моделях Engee.
Так, WorkspaceArray обеспечивает единый и удобный интерфейс доступа к временным данным на протяжении всего моделирования — от подготовки входных данных до анализа результатов.
Создание WorkspaceArray
Обычно WorkspaceArray формируется автоматически в процессе симуляции — например, при записи сигналов через блок В рабочую область или при сохранении результатов в переменную simout.
Однако его также можно создать вручную — например, чтобы загрузить внешние данные или протестировать модель на заранее подготовленных входах. В этом случае WorkspaceArray создается одним из следующих способов:
-
Из CSV-файла. Чтобы загрузить данные из CSV-файла, достаточно указать путь к файлу:
my_wa = WorkspaceArray("my_wa", "/user/path_to_csv.csv")здесь
"my_wa"— это имя, под которым массив будет сохранен в Окно переменных
Engee. Оно используется для последующей ссылки на массив в моделях, скриптах и других приложениях.CSV-файл должен содержать два столбца: один обязательно с именем
time, второй — со значениями сигнала. Пример структуры CSV-файла:time,value 0.1,1 0.2,2 0.3,3 -
Из таблицы
DataFrame. Если вы уже работаете с табличными данными в Julia, можно создатьWorkspaceArrayнапрямую из объектаDataFrame. Это особенно удобно при генерации входных сигналов программно, во время анализа или трансформации данных.DataFrame— это табличная структура из пакетаDataFrames.jl, аналогичная таблицам в Excel или DataFrame в Python (pandas). Каждая колонка имеет имя и тип, а данные хранятся по строкам. Пример создания:using DataFrames df = DataFrame(time = [0.1, 0.2, 0.3], value = [1, 2, 3]) wa = WorkspaceArray("my_wa", df)Таблица должна содержать два столбца:
time(типFloat64) иvalue(может быть скаляром, вектором или массивом чисел).
Работа с WorkspaceArray
WorkspaceArray реализует интерфейс AbstractArray, что позволяет обращаться к нему как к обычному массиву в Julia — индексировать, итерировать, выполнять срезы и т.д. Однако помимо базового поведения массивов, WorkspaceArray содержит внутреннюю структуру и дополнительные поля, которые обеспечивают его связь с источниками данных, поддерживают ленивую загрузку и позволяют удобно работать с временными рядами.
Каждый WorkspaceArray — это не просто набор чисел, а объект с «метаданными»: он знает, где лежат его данные, как они связаны со временем, откуда загружаются, и как были получены. Эти дополнительные свойства можно запросить напрямую, просто обращаясь к полям объекта через точку:
wa = WorkspaceArray("my_wa")
wa.time # доступ к временны́м меткам
wa.value # доступ к значениям
wa.type # узнаем, какой тип у массива — :pair, :time или :value
Доступны следующие поля:
-
time— дочернийWorkspaceArray, содержащий только временные метки. Имеет тип:time; -
value— дочернийWorkspaceArray, содержащий значения сигнала. Имеет тип:value; -
type— тип текущего массива::time,:valueили:pair(временные метки + значения); -
parent— ссылка на родительскийWorkspaceArray, если текущий является результатом среза; -
range— диапазон индексов, на основе которого был создан срез. Используется при ленивом срезе; -
dimension— размерность данных в полеvalue(например, скаляр, вектор, матрица); -
signal_id— уникальный идентификатор источника данных в Engee.
Чаще всего при работе с WorkspaceArray напрямую используются поля time и value, особенно при необходимости получить данные по отдельности или преобразовать их в таблицу.
|
Повторное использование
После создания переменной, содержащей WorkspaceArray (например с именем wa), автоматически связывается с signal_id (уникальным идентификатором) в Engee. Это позволяет ссылаться на нее по имени и повторно использовать в других частях проекта — например, в веб-приложениях на базе фреймворка Genie (подробнее см. Работа с Genie в Engee), в других моделях или в блоках с вложенностью, например Подсистема:
wa = WorkspaceArray("my_wa")
Такая запись создает новый WorkspaceArray, ссылающийся на уже зарегистрированные данные под именем "my_wa".
Использование с моделями
Блоки В рабочую область и Из рабочей области предназначены для взаимодействия с WorkspaceArray в модели:
Блок В рабочую область записывает данные из модели в переменную типа WorkspaceArray в рабочей области Engee. Имя переменной задается параметром Variable name. Поддерживаются только числовые данные (скалярные и массивы).
Блок Из рабочей области считывает данные из рабочей области и подает их на вход модели. Используются только переменные типа WorkspaceArray.
Блоки To Workspace и From Workspace работают только с типом WorkspaceArray.
|
Пример использования: From/To Workspace демо.
Работа с CSV
Выгрузка данных
Полная выгрузка в DataFrame
Для полной выгрузки данных из WorkspaceArray в DataFrame используйте collect:
df = collect(wa) # получаем DataFrame с колонками time и value
Вы также можете получить отдельные колонки из WorkspaceArray:
collect(wa.time) # только время
collect(wa.value) # только значения
Не рекомендуется использовать collect для очень больших данных — возможна перегрузка памяти.
|
Ленивые срезы
Одно из ключевых преимуществ WorkspaceArray — поддержка ленивых срезов (Lazy Slices).
В отличие от обычных массивов Julia, где срез (wa[1:10]) создает новый массив с копией данных, WorkspaceArray работает иначе. При срезе создается представление (view), которое хранит только диапазон индексов (range) и ссылку на исходный объект (parent) — без фактической загрузки значений в память. Данные подгружаются из хранилища только при явном запросе, например, через collect, при итерации или доступе по индексу.
Это особенно полезно для:
-
Экономии памяти — срезы не копируют данные, а лишь указывают на нужные элементы;
-
Быстродействия — можно работать только с нужными фрагментами данных;
-
Гибкости — ленивые срезы можно использовать в качестве входных данных моделей, в визуализациях или при экспорте.
Пример:
wa_slice = wa[1:2:end] # ленивое представление: каждый второй элемент
collect(wa_slice) # загружаем данные в память (в виде DataFrame)
Результат:
Row │ time value
│ Float64 Int64
────┼───────────────
1 │ 0.1 1
2 │ 0.3 3
3 │ 0.5 5
Кроме срезов, можно получить доступ к отдельному элементу по индексу:
wa[1] # доступ к первой записи, будет получено (0.1, 1)
Срезы по полям time и value
В WorkspaceArray доступны отдельные поля .time и .value, к которым также можно применять ленивые срезы:
wa_values = wa.value[2:end] # срез только по значениям
wa_times = wa.time[2:end] # срез только по временной шкале
|
Срез При необходимости данные можно загрузить в память:
|
Методы и интерфейс WorkspaceArray
WorkspaceArray реализует стандартные интерфейсы Julia и дополняет их собственными методами. Ниже — краткий обзор наиболее полезных функций, которые можно использовать при работе с временными рядами:
-
wa[i]— доступ к элементу по индексу, возвращает кортеж(time, value):wa[1] # будет получено (0.1, 42.0) -
wa[start:stop]— срез по диапазону, возвращает ленивое представление. Данные не копируются, а подгружаются по мере необходимости:wa_slice = wa[1:10] collect(wa_slice) # загружает только выбранный диапазон -
wa[1:2:end]— ленивый срез с шагом. -
wa.time,wa.value— доступ к дочернимWorkspaceArray, содержащим отдельно время и значения. К ним тоже можно применять срезы:wa_times = wa.time[5:end] wa_values = wa.value[5:end] -
collect(wa)— преобразуетWorkspaceArrayвDataFrame. Это основной способ получить данные в явном виде:df = collect(wa)
-
copy(wa)/similar(wa)— создают поверхностную копию объекта. В текущей реализации работают одинаково. -
wa1 == wa2— сравнение двухWorkspaceArrayпоsignal_idи диапазону (range).
Если вы работаете с временными рядами в Engee, то, скорее всего, вам хватит collect, срезов (wa[1:10]) и iterrows для повседневных задач. Остальные методы пригодятся при оптимизации и тонкой настройке поведения.
|
Пример использования
Рассмотрим базовый пример работы с WorkspaceArray — от создания до получения среза и выгрузки данных. Этот сценарий охватывает самые типовые сценарии использования WorkspaceArray.
-
Для начала создайте таблицу (
DataFrame), содержащую два столбца:timeиvalue. Это обязательный формат для импорта данных вWorkspaceArray:using DataFrames df = DataFrame(time = [0.1, 0.2, 0.3, 0.4, 0.5], value = [1, 2, 3, 4, 5])-
time— момент времени (в секундах); -
value— значение сигнала в этот момент.
-
-
Преобразуйте таблицу в
WorkspaceArray, указав имя, под которым массив будет доступен в Engee:wa = WorkspaceArray("myarr", df)Здесь
"myarr"— имя переменной, с которой можно будет работать в моделях и скриптах. -
WorkspaceArrayподдерживает доступ по индексу. Например, получите первую запись:println(wa[1])Результат:
(0.1, 1)Это кортеж: первый элемент — время, второй — значение сигнала.
Данные подгружаются только при обращении к ним. То есть даже при wa[1]загружается только один элемент. -
Сделайте срез массива, получите каждый второй элемент
(1, 3, 5). Это создаст ленивое представление, а не копию:wa_slice = wa[1:2:end]Чтобы получить данные в виде таблицы, используйте
collect:println(collect(wa_slice))Результат:
3×2 DataFrame Row │ time value │ Float64 Int64 ─────┼──────────────── 1 │ 0.1 1 2 │ 0.3 3 3 │ 0.5 5Срез
wa[1:2:end]не загружает данные сам по себе. Только приcollect, итерации или обращении по индексу данные реально подгружаются из хранилища.