【问题标题】:How to convert CSV columns into Vowpal Wabbit txt input file如何将 CSV 列转换为 Vowpal Wabbit txt 输入文件
【发布时间】:2021-03-30 19:33:34
【问题描述】:

我正在尝试将 csv(有 10 列)转换为 vowpal wabbit 输入格式 txt 文件。一些 csv 列具有整数值,一些具有字符串(例如:com.12346.xyz)。例如,如果我的 csv 列如下所示:

loss       weight         SSD_id      weight    label      imp            feat_val
0.693147   0.693147            1         1.0  -1.0000   0.0000       com.12346.xyz
0.419189   0.145231            2         2.0   1.0000  -1.8559       com.12346.xyz
0.235457   0.051725            4         4.0  -1.0000  -2.7588       com.12356.xyz
6.371911   12.508365           8         8.0  -1.0000  -3.7784       com.12346.xyz
3.485084   0.598258           16        16.0   1.0000  -2.2767       com.12346.xyz
1.765249   0.045413           32        32.0  -1.0000  -2.8924       com.1236.xyz
1.017911   0.270573           64        64.0  -1.0000  -3.0438       com.12236.xyz
0.611419   0.204927          128       128.0   1.0000  -3.1539       com.16746.xyz
0.469127   0.326834          256       256.0  -1.0000  -1.6101       com.1946.xyz
0.403473   0.337820          512       512.0   1.0000  -2.8843       com.126.xyz
0.337348   0.271222         1024      1024.0  -1.0000  -2.5209       com.1346.xyz
0.328909   0.320471         2048      2048.0   1.0000  -2.0732       com.1234.xyz
0.309401   0.289892         4096      4096.0   1.0000  -2.7639       com.12396.xyz

vowpal wabbit 输入格式如下所示:

label weight |i imp SSD_id loss |c feat_val

并且在 vowpal wabbit txt 文件中的值应该是:

-1 0.051725 |i imp:-2.7588 SSD_id:4 loss:0.235457 |c feat_val=com.12356.xyz
 1 0.598258 |i imp:-2.7588 SSD_id:4 loss:3.485034 |c feat_val=com.12346.xyz

... 等等... 对于所有行值。我在 csv 文件中有大量行,我想将它们转换为上述格式并将它们全部保存在单个 txt 文件中。我从下面给出的这个小功能开始:

def to_new_format(document, label=None):
      return str(label or '') + ' |i ' + ' '.join(re.findall('\w{3,}', document.lower())) + '\n'
to_new_format(str(text_train[1])

但是经过多次使用数据框、csv 格式和尝试功能的试验后,我现在完全迷失了。有人可以指导我如何用最少的代码行来实现这一点。

【问题讨论】:

    标签: python vowpalwabbit


    【解决方案1】:

    这比看起来更简单,因为 Pandas 提供了一些方便的方法,让您可以像在 Python 中处理单个值一样对待序列。

    首先,我们将导入您的 CSV 文件,将所有值视为字符串以使我们的格式更容易:

    import pandas as pd
    
    df = pd.read_csv('test_data.txt', dtype=pd.StringDtype())
    

    您的label 列在您的文件中记录为1.0000,但您不希望输出中出现小数点或零。我们可以使用 Pandas 的 str.replace 方法来解决这个问题。

    df.label = df.label.str.replace('.0000', '', regex=False)
    

    这是神奇的部分:我们可以将它们连接起来,就像它们是单独的字符串一样!

    formatted = (
        df.label + ' ' + df.weight +
        ' |i imp:' + df.imp +
        ' SSD_id: ' + df.SSD_id +
        ' loss:' + df.loss +
        ' |c feat_val=' + df.feat_val +
        '\n'
    )
    

    该代码看起来会创建一个字符串,但由于它包含数据帧的列(每个列都是 Pandas 序列),结果也是一个序列:

    print(formatted)
    
    0     -1 0.693147 |i imp:0.0000 SSD_id: 1 loss:0.693...
    1     1 0.145231 |i imp:-1.8559 SSD_id: 2 loss:0.419...
    2     -1 0.051725 |i imp:-2.7588 SSD_id: 4 loss:0.23...
    3     -1 12.508365 |i imp:-3.7784 SSD_id: 8 loss:6.3...
    4     1 0.598258 |i imp:-2.2767 SSD_id: 16 loss:3.48...
    5     -1 0.045413 |i imp:-2.8924 SSD_id: 32 loss:1.7...
    6     -1 0.270573 |i imp:-3.0438 SSD_id: 64 loss:1.0...
    7     1 0.204927 |i imp:-3.1539 SSD_id: 128 loss:0.6...
    8     -1 0.326834 |i imp:-1.6101 SSD_id: 256 loss:0....
    9     1 0.337820 |i imp:-2.8843 SSD_id: 512 loss:0.4...
    10    -1 0.271222 |i imp:-2.5209 SSD_id: 1024 loss:0...
    11    1 0.320471 |i imp:-2.0732 SSD_id: 2048 loss:0....
    12    1 0.289892 |i imp:-2.7639 SSD_id: 4096 loss:0....
    

    这样打印时,每一行都会被截断,但都在里面。例如:

    print(formatted[0])
    
    -1 0.693147 |i imp:0.0000 SSD_id: 1 loss:0.693147 |c feat_val=com.12346.xyz
    

    剩下的就是把它保存到一个文件中:

    with open('out.txt', 'w') as f:
        f.writelines(formatted)
    

    【讨论】:

    • 您的解决方案非常干净、出色且易于理解。我学到了一些新东西。一个星期以来我一直在尝试这个。是的,你是对的,如果以正确的方式完成,它看起来很复杂但实现起来很简单。如果数据是 json 格式,这仍然有效吗?
    • 很高兴它有帮助!老实说,我现在也在学习 Pandas,回答这个问题对我来说很有教育意义。碰巧 Pandas 也有一个 read_json 方法!您可能需要根据文件的格式进行调整,但是是的,这种方法应该仍然有效。
    • 我会尝试使用 read_json,如果它有效,我会在这里发布。发送请求时,数据基本上以 json 格式出现,但是对于我来说太复杂了,无法解决这个问题,所以我想先尝试使用 csv。是的,您的解决方案方法非常适合我尝试使用 csv 进行的操作,现在将尝试使用 json。
    【解决方案2】:

    在最近的版本中,Vowpal Wabbit 有一个 Python 模块,可以轻松将 pandas DataFrame 转换为 Vowpal Wabbit 输入格式。

    例如使用 8.11.0 版 并假设您的列类型如下:

    loss        float64
    weight      float64
    SSD_id        int64
    weight.1    float64
    label         int64
    imp         float64
    feat_val     object
    dtype: object
    

    你可以使用下面的代码

    from vowpalwabbit.DFtoVW import DFtoVW, SimpleLabel, Namespace, Feature
    
    label = SimpleLabel(label="label", weight="weight")
    namespaces = [
        Namespace(features=[Feature(col) for col in ["imp", "SSD_id", "loss"]], name="i"),
        Namespace(features=Feature("feat_val"), name="c")
    ]
    
    converter = DFtoVW(df=dat, label=label, namespaces=namespaces)
    
    

    然后调用convert_df方法获取输出

    examples = converter.convert_df()
    
    print(examples)
    
    ['-1 0.693147 |i imp:0.0 SSD_id:1 loss:0.693147 |c feat_val=com.12346.xyz',
     '1 0.145231 |i imp:-1.8559 SSD_id:2 loss:0.419189 |c feat_val=com.12346.xyz',
     '-1 0.051725 |i imp:-2.7588 SSD_id:4 loss:0.235457 |c feat_val=com.12356.xyz',
     '-1 12.508365 |i imp:-3.7784 SSD_id:8 loss:6.371911 |c feat_val=com.12346.xyz',
     '1 0.598258 |i imp:-2.2767 SSD_id:16 loss:3.485084 |c feat_val=com.12346.xyz',
     '-1 0.045413 |i imp:-2.8924 SSD_id:32 loss:1.765249 |c feat_val=com.1236.xyz',
     '-1 0.270573 |i imp:-3.0438 SSD_id:64 loss:1.017911 |c feat_val=com.12236.xyz',
     '1 0.204927 |i imp:-3.1539 SSD_id:128 loss:0.611419 |c feat_val=com.16746.xyz',
     '-1 0.326834 |i imp:-1.6101 SSD_id:256 loss:0.469127 |c feat_val=com.1946.xyz',
     '1 0.33782 |i imp:-2.8843 SSD_id:512 loss:0.403473 |c feat_val=com.126.xyz',
     '-1 0.271222 |i imp:-2.5209 SSD_id:1024 loss:0.337348 |c feat_val=com.1346.xyz',
     '1 0.320471 |i imp:-2.0732 SSD_id:2048 loss:0.328909 |c feat_val=com.1234.xyz',
     '1 0.289892 |i imp:-2.7639 SSD_id:4096 loss:0.309401 |c feat_val=com.12396.xyz']
    

    并将其写入文件

    with open("test.dat", "w") as f:
        for example in examples:
            f.writelines(example+"\n")
    

    【讨论】:

      猜你喜欢
      • 2015-09-29
      • 1970-01-01
      • 2012-05-19
      • 2015-12-11
      • 2016-01-31
      • 1970-01-01
      • 1970-01-01
      • 2015-02-19
      • 1970-01-01
      相关资源
      最近更新 更多