DataFrames.transform 在 Julia 中使用匿名函数指定目标变量

DataFrames.transform specifying target variable with anonymous function in Julia

我正在尝试将 transform 与匿名函数 (x -> uppercase.(x)) 结合使用,并通过指定目标列名称 (:A) 将新列存储为 "A" .

如果我没有指定目标列变量(下面的第一个转换),新变量生成很好(即一个包含 5 个元素的向量)。但是,一旦我指定了目标列(下面的第二个转换),函数 return 就是 "a_function" 名称下的对向量。

如何使用包含具有 5 个元素(“A”到“E”)的 Vector 的新列 "A" 生成所需的 DataFrame?为什么下面的第二个转换 return 是一个名称与指定名称不同的对向量?

using DataFrames

df_1 = DataFrame(a = ["a", "b", "c", "d", "e"])

df_2 = transform(df_1, :a => x -> uppercase.(x))  # first transformation

df_2
 Row │ a       a_function 
     │ String  String
─────┼────────────────────
   1 │ a       A
   2 │ b       B
   3 │ c       C
   4 │ d       D
   5 │ e       E


df_3 = transform(df_1, :a => x -> uppercase.(x) => :A) # second transformation

df_3
5×2 DataFrame
 Row │ a       a_function
     │ String  Pair…
─────┼───────────────────────────────────────
   1 │ a       ["A", "B", "C", "D", "E"]=>:A
   2 │ b       ["A", "B", "C", "D", "E"]=>:A
   3 │ c       ["A", "B", "C", "D", "E"]=>:A
   4 │ d       ["A", "B", "C", "D", "E"]=>:A
   5 │ e       ["A", "B", "C", "D", "E"]=>:A

期望的结果数据帧:

 DataFrame(a = ["a", "b", "c", "d", "e"],
    A = ["A", "B", "C", "D", "E"])

原因是运算符优先级,如果你写:

julia> :a => x -> uppercase.(x) => :A
:a => var"#7#8"()

你看到你只定义了一对。整个部分 uppercase.(x) => :A 成为你的匿名函数的主体。

改为写(注意我在匿名函数周围添加了 ()):

julia> :a => (x -> uppercase.(x)) => :A
:a => (var"#9#10"() => :A)

得到你想要的:

julia> df_3 = transform(df_1, :a => (x -> uppercase.(x)) => :A)
5×2 DataFrame
 Row │ a       A
     │ String  String
─────┼────────────────
   1 │ a       A
   2 │ b       B
   3 │ c       C
   4 │ d       D
   5 │ e       E

在这种情况下,更标准的写法是:

julia> transform(df_1, :a => ByRow(uppercase) => :A)
5×2 DataFrame
 Row │ a       A
     │ String  String
─────┼────────────────
   1 │ a       A
   2 │ b       B
   3 │ c       C
   4 │ d       D
   5 │ e       E

甚至:

julia> transform(df_1, :a => ByRow(uppercase) => uppercase)
5×2 DataFrame
 Row │ a       A
     │ String  String
─────┼────────────────
   1 │ a       A
   2 │ b       B
   3 │ c       C
   4 │ d       D
   5 │ e       E

最后一种形式是 DataFrames.jl 1.3 中的新形式,它允许您将函数作为目标列名称说明符传递(在本例中,转换是将源列名称大写)。当然在这种情况下它更长,但如果您以编程方式定义转换,它有时会很有用。