Engee 文档

在工程中使用WorkspaceArray

'WorkspaceArray`是*Engee*建模环境中的一种特殊数据类型,专为存储和处理时间序列而设计。 它基于语言的’AbstractArray’接口 Julia,但与标准数组不同,实现了数据的延迟加载,这使得它成为一个懒惰的数组。

懒惰数组(或懒惰加载的数组)是一种结构,它不会将数据完全存储在RAM中,而是根据需要加载它:例如,在迭代,访问索引或转换为表时。 这使您能够有效地处理不适合内存或来自外部源(例如,来自数据库或文件)的非常大的数据集。 *Engee*中的’WorkspaceArray`用于以下场景:

  • 作为模拟的结果,它用于存储记录的信号。 例如,在’simout’变量中(有关更多信息,请参阅 Engee中仿真结果的软件处理);

  • 通过块在模型之间传输数据 至工作区来自工作区;

  • 从CSV文件或表格(DataFrame)导入自定义时间序列,然后可以在*Engee*模型中使用。

因此,WorkspaceArray提供了一个单一且用户友好的界面,用于在整个模拟过程中访问临时数据,从准备输入数据到分析结果。

创建WorkspaceArray

通常,在仿真过程中会自动形成"WorkspaceArray",例如,当通过块记录信号时 至工作区 或者将结果保存到变量时 simout

但是,它也可以手动创建,例如,加载外部数据或在预先准备的输入上测试模型。 在这种情况下,使用以下方法之一创建`WorkspaceArray:

  • 来自CSV文件。 要从CSV文件下载数据,只需指定文件的路径即可。:

    my_wa = WorkspaceArray("my_wa", "/user/path_to_csv.csv")

    这里`"my_wa"'是数组将存储在其下的名称 变量的窗口 variables article 2 1 Engee。 它用于模型、脚本和其他应用程序中的后续数组引用。

    CSV文件必须包含两列:一列*必需*名称为"time",第二列包含信号的值。 CSV文件结构示例:

    time,value
    0.1,1
    0.2,2
    0.3,3
  • 从’DataFrame`表。 如果您已经在Julia中使用表格数据,则可以直接从"DataFrame"对象创建"WorkspaceArray"。 这在以编程方式生成输入信号时,在数据分析或转换期间尤其有用。

    'DataFrame’是来自包’DataFrames的表格结构。jl`,类似于Excel中的表格或Python中的DataFrame(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—indexed,iterated,sliced等中的常规数组一样访问`但是,除了数组的基本行为外,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`)的变量后,它会自动与*Engee*中的`signal_id`(唯一标识符)相关联。 这允许您按名称引用它,并在项目的其他部分中重用它,例如,在基于Genie框架的web应用程序中(有关更多信息,请参阅 在Engee与Genie合作),在其他模型中或在具有嵌套的块中,例如 子系统:

wa = WorkspaceArray("my_wa")

这样的记录创建一个新的’WorkspaceArray`,引用名称为`"my_wa"`的已经注册的数据。

与模型一起使用

街区 至工作区来自工作区 设计用于与模型中的"WorkspaceArray"交互:

至工作区 将模型中的数据写入工作区*Engee*中的"WorkspaceArray"类型的变量。 变量名由*变量名*参数设置。 仅支持数值数据(标量和数组)。

来自工作区 从工作区读取数据并将其馈送到模型输入。 只使用’WorkspaceArray’类型的变量。

'To Workspace’和`From Workspace’块仅使用’WorkspaceArray`类型工作*。

使用示例: 从/到工作区演示

使用CSV

将WorkspaceArray导出为CSV

要将`WorkspaceArray’导出为CSV,请使用’CSV。写`用所需的参数’delim="\t"`:

using CSV
CSV.write("/user/workspacearray_csv.csv", delim="\t", data_frame)
没有参数’delim="\t"`将导致导入期间错误`BoundsError',并将创建一个空文件。

从CSV导入WorkspaceArray

wa = WorkspaceArray("my_wa", "/user/my_data.csv")

该文件应包含两列:

  • 'time’是必需的列名。;

  • 'value'-值。

上传数据

完全上传到DataFrame

要将数据从`WorkspaceArray’完全上传到DataFrame’使用`collect':

df = collect(wa) # 获取包含 time 和 value 列的 DataFrame

您还可以从"WorkspaceArray"中获取单个列:

collect(wa.time)   # 仅收集时间
collect(wa.value)  # 仅收集值
对于非常大的数据,不建议使用"收集",因为内存过载是可能的。

懒人片

WorkspaceArray的一个关键优势是它对惰性切片的支持。

与常规Julia数组不同,其中一个slice(wa[1:10])创建一个带有数据副本的新数组,WorkspaceArray’的工作方式不同。 切片时,会创建一个仅存储索引范围(`range)和对源对象(parent)的引用的视图—而不会将值实际加载到内存中。 数据仅在显式请求时从存储*加载,例如,在迭代或索引访问期间通过"收集"。

这对于…​…​特别有用:

  • 保存内存-切片不会复制数据,而只指向必要的元素。;

  • 高性能—您只能使用正确的数据。;

  • 灵活性-懒惰切片可以用作模型输入,在可视化中或导出时。

例子::

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)

按"时间"和"值"字段划分的横截面

分开的字段`。时间’和`。值’在’WorkspaceArray`中可用,也可以应用惰性切片。:

wa_values = wa.value[2:end] # 仅截取数值部分
wa_times  = wa.time[2:end]  # 仅截取时间轴部分

`Wa[1:2:end]`的Slice返回具有相同`signal_id`的`WorkspaceArray`类型对象,但具有指示slice的新`range`字段。 这让您知道您正在查看一个懒惰的表示,而不是数据的副本。

如果需要,可以将数据加载到存储器中。:

wa = WorkspaceArray("my_wa")

wa_slice = wa[1:2:end]     # 创建懒惰切片
df = collect(wa_slice)     # 加载数据
println(df)                # 获取包含切片值的表格

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。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—-通过`signal_id`和range(range)比较两个`workspacearrays`。

如果你在*Engee*中使用时间序列,那么很可能你会有足够的`collect`,slices(wa[1:10])和`iterrows`用于日常任务。 其余方法对于优化和微调行为很有用。

使用示例

让我们来看一个使用"WorkspaceArray"的基本示例—从创建到接收切片并上传数据。 此方案涵盖’WorkspaceArray’最典型的使用方案。

  1. 首先,创建一个包含两列的表(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])
    • '时间—-时间的时刻(以秒为单位);

    • 'value'-此时信号的值。

  2. 通过指定数组在*Engee中可用的名称,将表转换为"WorkspaceArray"*:

    wa = WorkspaceArray("myarr", df)

    这里’myarr’是可以在模型和脚本中使用的变量的名称。

  3. 'WorkspaceArray’支持索引访问。 例如,获取第一条记录:

    println(wa[1])

    结果:

    (0.1, 1)

    这是一个元组:第一个元素是时间,第二个是信号值。

    数据只有在被访问时才被加载。 也就是说,即使使用’wa[1]`,也只加载一个元素。
  4. 制作数组的切片,获取每个第二个元素`(1, 3, 5)`. 这将创建一个*惰性视图*,而不是副本。:

    wa_slice = wa[1:2:end]

    要将数据作为表获取,请使用"收集":

    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]`的切片本身不会下载数据。 只有当"收集,迭代或访问索引时,数据才会从存储中实际加载。