如何将函数按列应用于 julia 数据框

ElB*_*cas 4 dataframe julia

您将如何按列将函数应用于 julia 数据框中的某些/所有列?我试图解决的用例是简单的类型解析和处理。例如,我想将此示例数据帧的列从字符串解析为整数

df = DataFrame(a = ["1","2", "3"], b = ["4","5","6"])

# something like this works but destroys the structure of the dataframe
[parse.(Int64, col) for col in eachcol(df)]
Run Code Online (Sandbox Code Playgroud)

将来,我希望能够拥有一个包含许多不同类型列的数据框,并且只修改此数据框的选择。但是,我仍然坚持将函数应用于所有列的简单情况。

Bog*_*ski 6

目前尚不清楚您想要达到的目标。根据您的评论,我假设您想将数据框作为源并获得数据框作为结果。如果是这种情况,这里是选项。

基本的一种是使用mapcols(创建一个新的数据框)或mapcols!(就地操作)。以下是mapcols您查询的示例:

julia> mapcols(col -> parse.(Int, col), df)
3×2 DataFrame
? Row ? a     ? b     ?
?     ? Int64 ? Int64 ?
???????????????????????
? 1   ? 1     ? 4     ?
? 2   ? 2     ? 5     ?
? 3   ? 3     ? 6     ?
Run Code Online (Sandbox Code Playgroud)

一组更通用的函数是transform(创建一个新的数据框)和 `transform! (就地操作)。他们将新列添加到您的数据框中:

julia> transform(df, :a => ByRow(x -> parse(Int, x)) => :a)
3×2 DataFrame
? Row ? a     ? b      ?
?     ? Int64 ? String ?
????????????????????????
? 1   ? 1     ? 4      ?
? 2   ? 2     ? 5      ?
? 3   ? 3     ? 6      ?

julia> transform(df, [:a, :b] .=> ByRow(x -> parse(Int, x)) .=> [:a, :b])
3×2 DataFrame
? Row ? a     ? b     ?
?     ? Int64 ? Int64 ?
???????????????????????
? 1   ? 1     ? 4     ?
? 2   ? 2     ? 5     ?
? 3   ? 3     ? 6     ?
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请参阅 DataFrames.jl 的文档(因为它们很长 - 该函数有很多选项,但您可以从这里这里开始)。

这里有几点需要注意:

  • 因为transformmapcols指定输出列的名称更通用(如果省略输出列名称,它将通过合并源列名称和函数名称自动生成)
  • 如您所见,您可以应用transform到列的子集,但是请注意,为了将相同的转换应用于多个列,我们使用了带.=>符号的广播。

(请注意,有selectselect!功能几乎相同,但默认情况下不保留旧数据框的列)

最后,在实践中,写这样的东西也是完全可以的:

julia> foreach(n -> df[!, n] = parse.(Int, df[!, n]), names(df))

julia> df
3×2 DataFrame
? Row ? a     ? b     ?
?     ? Int64 ? Int64 ?
???????????????????????
? 1   ? 1     ? 4     ?
? 2   ? 2     ? 5     ?
? 3   ? 3     ? 6     ?
Run Code Online (Sandbox Code Playgroud)

(如您所见,这会就地修改您的数据框)