【问题标题】:Julia DataFrames - How to do one-hot encoding?Julia DataFrames - 如何进行一次热编码?
【发布时间】:2021-02-10 08:55:15
【问题描述】:

我正在使用 Julia 的 DataFrames.jl 包。在其中,我有一个数据框,其中包含一个字符串列表(例如 ["Type A"、"Type B"、"Type D"])。然后如何执行 one-hot 编码?我无法在 DataFrames.jl 包中找到预构建的函数。

这是我想做的一个例子:

Original Dataframe

col1 | col2 |
102  |[a]   |
103  |[a,b] | 
102  |[c,b] |
After One-hot encoding

col1 | a | b | c |
102  | 1 | 0 | 0 |
103  | 1 | 1 | 0 | 
102  | 0 | 1 | 1 |

【问题讨论】:

    标签: dataframe julia one-hot-encoding


    【解决方案1】:

    DataFrames.jl 中确实没有 one-hot 编码功能 - 我认为这是明智的,因为这是一种特殊的机器学习转换,应该存在于 ML 包中,而不是基本的 DataFrames 包中。

    我认为你有两个选择:

    1. 使用为您执行此操作的 ML 包,例如MLJ.jl。在 MLJ 中,OneHotEncoder 是一个模型,它可以将任何包含Finite 特征的表转换为自身的单热编码版本,请参阅文档here

    2. 使用回归包,该包使用 StatsModels @formula API 自动生成分类变量的虚拟列 - 如果您适合回归,例如GLM.jl 而你的公式是@formula(y ~ x) 其中x 是一个分类变量,模型矩阵将通过对比编码x 自动构建,即除了一级x 之外,所有的都有二进制虚拟列

    对于第二个选项,您最好希望您的数据是分类的(尽管字符串也可以),为此 DataFrames.jl 包含 categorical! 函数。

    编辑 17/11/2021:此后在 Julia Discourse 上有一个明确的主题,其中包含大量建议进行单热编码:https://discourse.julialang.org/t/all-the-ways-to-do-one-hot-encoding/

    从那里分享我最喜欢的:

    julia> x = [1, 2, 1, 3, 2];
    
    julia> unique(x) .== permutedims(x)
    3×5 BitMatrix:
     1  0  1  0  0
     0  1  0  0  1
     0  0  0  1  0
    

    【讨论】:

      【解决方案2】:

      我已经包含了一个基于@Bogumil 代码的热门函数

      https://github.com/xiaodaigh/DataConvenience.jl#one-hot-encoding

      做吧

      onehot(df, :col2)
      

      完整的 MWE

      a = DataFrame(
        player1 = ["a", "b", "c"],
        player2 = ["d", "c", "a"]
      )
      
      # does not modify a
      onehot(a, :player1)
      
      # modfies a
      onehot!(a, :player1)
      

      【讨论】:

        【解决方案3】:

        使用我们提供的基本功能很容易做到这一点:

        julia> df = DataFrame(x=rand([1:3;missing], 20))
        20×1 DataFrame
        │ Row │ x       │
        │     │ Int64?  │
        ├─────┼─────────┤
        │ 1   │ 1       │
        │ 2   │ 2       │
        │ 3   │ missing │
        │ 4   │ 1       │
        │ 5   │ 3       │
        │ 6   │ missing │
        │ 7   │ 3       │
        │ 8   │ 3       │
        │ 9   │ 3       │
        │ 10  │ 3       │
        │ 11  │ missing │
        │ 12  │ 1       │
        │ 13  │ 3       │
        │ 14  │ 3       │
        │ 15  │ 3       │
        │ 16  │ 1       │
        │ 17  │ missing │
        │ 18  │ 1       │
        │ 19  │ 1       │
        │ 20  │ missing │
        
        julia> ux = unique(df.x); transform(df, @. :x => ByRow(isequal(ux)) .=> Symbol(:x_, ux))
        20×5 DataFrame
        │ Row │ x       │ x_1  │ x_2  │ x_missing │ x_3  │
        │     │ Int64?  │ Bool │ Bool │ Bool      │ Bool │
        ├─────┼─────────┼──────┼──────┼───────────┼──────┤
        │ 1   │ 1       │ 1    │ 0    │ 0         │ 0    │
        │ 2   │ 2       │ 0    │ 1    │ 0         │ 0    │
        │ 3   │ missing │ 0    │ 0    │ 1         │ 0    │
        │ 4   │ 1       │ 1    │ 0    │ 0         │ 0    │
        │ 5   │ 3       │ 0    │ 0    │ 0         │ 1    │
        │ 6   │ missing │ 0    │ 0    │ 1         │ 0    │
        │ 7   │ 3       │ 0    │ 0    │ 0         │ 1    │
        │ 8   │ 3       │ 0    │ 0    │ 0         │ 1    │
        │ 9   │ 3       │ 0    │ 0    │ 0         │ 1    │
        │ 10  │ 3       │ 0    │ 0    │ 0         │ 1    │
        │ 11  │ missing │ 0    │ 0    │ 1         │ 0    │
        │ 12  │ 1       │ 1    │ 0    │ 0         │ 0    │
        │ 13  │ 3       │ 0    │ 0    │ 0         │ 1    │
        │ 14  │ 3       │ 0    │ 0    │ 0         │ 1    │
        │ 15  │ 3       │ 0    │ 0    │ 0         │ 1    │
        │ 16  │ 1       │ 1    │ 0    │ 0         │ 0    │
        │ 17  │ missing │ 0    │ 0    │ 1         │ 0    │
        │ 18  │ 1       │ 1    │ 0    │ 0         │ 0    │
        │ 19  │ 1       │ 1    │ 0    │ 0         │ 0    │
        │ 20  │ missing │ 0    │ 0    │ 1         │ 0    │
        

        编辑:

        另一个例子:

        julia> df = DataFrame(col1=102:104, col2=[["a"], ["a","b"], ["c","b"]])
        3×2 DataFrame
        │ Row │ col1  │ col2       │
        │     │ Int64 │ Array…     │
        ├─────┼───────┼────────────┤
        │ 1   │ 102   │ ["a"]      │
        │ 2   │ 103   │ ["a", "b"] │
        │ 3   │ 104   │ ["c", "b"] │
        
        julia> ux = unique(reduce(vcat, df.col2))
        3-element Array{String,1}:
         "a"
         "b"
         "c"
        
        julia> transform(df, :col2 .=> [ByRow(v -> x in v) for x in ux] .=> Symbol.(:col2_, ux))
        3×5 DataFrame
        │ Row │ col1  │ col2       │ col2_a │ col2_b │ col2_c │
        │     │ Int64 │ Array…     │ Bool   │ Bool   │ Bool   │
        ├─────┼───────┼────────────┼────────┼────────┼────────┤
        │ 1   │ 102   │ ["a"]      │ 1      │ 0      │ 0      │
        │ 2   │ 103   │ ["a", "b"] │ 1      │ 1      │ 0      │
        │ 3   │ 104   │ ["c", "b"] │ 0      │ 1      │ 1      │
        

        【讨论】:

        • 这几乎是完美的。但就我而言,每一列都有一个类型列表,而不是单一类型,例如:["a","b"]
        • 请分享您拥有的可重现示例,我可以推荐解决方案(很可能几乎相同)。
        • 谢谢,如果有更清晰的例子,我已经更新了问题。
        • 添加示例
        • df2 = select(df, :col1, :col2 .=> [ByRow(v -> x in v) for x in ux] .=> Symbol.(ux))
        猜你喜欢
        • 2022-09-27
        • 1970-01-01
        • 2020-11-14
        • 2018-04-28
        • 2017-05-02
        • 2017-01-10
        • 2020-12-20
        • 2022-10-06
        相关资源
        最近更新 更多