在工程中使用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"'是数组将存储在其下的名称 变量的窗口
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
上传数据
完全上传到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`字段。 这让您知道您正在查看一个懒惰的表示,而不是数据的副本。 如果需要,可以将数据加载到存储器中。:
|
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’最典型的使用方案。
-
首先,创建一个包含两列的表(
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'-此时信号的值。
-
-
通过指定数组在*Engee中可用的名称,将表转换为"WorkspaceArray"*:
wa = WorkspaceArray("myarr", df)
这里’myarr’是可以在模型和脚本中使用的变量的名称。
-
'WorkspaceArray’支持索引访问。 例如,获取第一条记录:
println(wa[1])
结果:
(0.1, 1)
这是一个元组:第一个元素是时间,第二个是信号值。
数据只有在被访问时才被加载。 也就是说,即使使用’wa[1]`,也只加载一个元素。 -
制作数组的切片,获取每个第二个元素`(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]`的切片本身不会下载数据。 只有当"收集
,迭代或访问索引时,数据才会从存储中实际加载。