问题描述
我在 julia 中有以下函数,读取一个 Arrow 文件(使用 Arrow.jl)从磁盘读取数据并处理它:
function getmembershipsdays(fromId,toId)
memberships = Arrow.Table("HouseholdMemberships.arrow") |> DataFrame
filter!([:IndividualId] => id -> id >= fromId && id <= toId,memberships)
...
end
> Error: ERROR: LoadError: MethodError: no method matching
> deleteat!(::Arrow.Primitive{Int64,Array{Int64,1}},::Array{Int64,1})
The DataFrame has the following structure:
123226x10 DataFrame
Row | MembershipId | IndividualId | HouseholdId | ...
| Int64 | Int64 | Int64 |
函数中用于单步执行 Dataframe 的其余代码有效,但如果我添加过滤条件,则会出现此错误。就好像 Dataframe 列未转换为基础 julia 类型一样。
如果我这样做
m = filter([:IndividualId] => id -> id >= fromId && id <= toId,memberships)
然后就可以了。如何就地过滤?
解决方法
您正在使用内存映射,这意味着您无法就地调整从 Arrow.jl 源创建的 DataFrame
的大小。这是您必须为从 Arrow 源超快速零拷贝创建数据帧而支付的成本。
为什么要这样设计?
- 通常您只读取数据帧(而不对其进行变异)——在这种情况下,您可能希望节省复制数据的成本(尤其是对于非常大的数据集)。
- 在 DataFrames.jl 中使用复制函数来执行复制很容易(例如在您的示例中将
filter!
替换为filter
)。
有关更多示例,请参见 https://bkamins.github.io/julialang/2020/11/06/arrow.html(特别是 - 如何避免使用 IO
源而不是文件名作为源进行内存映射)。
附注。请注意,id >= fromId && id <= toId
可以只写为 fromId <= id <= toId
。