You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Ruby的red-parquet gem修改Parquet文件列类型的问题

问题解决:Parquet文件列类型从String转Int32(Ruby red-parquet)

问题根源

你的代码没生效是因为Arrow::Table是不可变对象,调用cast方法只会返回转换后的新列,不会修改原table。原代码里调用table.heading.cast('int32')后没有将结果赋值回table,相当于白做了转换,保存的还是原始数据。

修正后的代码

require 'arrow'
require 'fileutils'

def cast_col(target_col = :heading)
  files_written = 0
  get_parquets.each do |file|
    table = Arrow::Table.load(file)
    # 检查目标列的类型是否为string
    col = table[target_col]
    next unless col.data_type.to_s == "string"

    new_file_loc = File.join(@save_dir, File.basename(file)) # 用File.join避免路径拼接问题
    puts "Processing: #{new_file_loc}"

    # 创建目标目录
    FileUtils.mkdir_p(File.dirname(new_file_loc))

    begin
      # 转换列类型,返回新的列对象
      casted_col = col.cast('int32')
      # 用转换后的列替换原table中的对应列,生成新的table
      new_table = table.select(table.schema.fields.reject { |f| f.name == target_col.to_s })
                       .add_column(casted_col)
      # 保存新table
      new_table.save(new_file_loc)
      files_written += 1
    rescue => e
      puts "Failed to process #{file}: #{e.message}"
      # 根据需求选择跳过或终止
      next
    end
  end
  puts "Number of Files Written: #{files_written}"
end

关键改进点

  • 不可变对象处理:明确生成新的列和新的table,而不是修改原对象
  • 路径安全:用File.join拼接路径,避免因操作系统差异导致的路径错误
  • 异常处理:捕获转换时的异常(比如字符串无法转为整数的情况),避免批量处理中断
  • 列选择逻辑:通过select+add_column确保只替换目标列,保留其他列的结构和数据

额外建议

  1. 转换验证:处理完部分文件后,加载新文件验证列类型:
    test_table = Arrow::Table.load(new_file_loc)
    puts test_table[target_col].data_type # 应该输出int32
    
  2. 性能优化:700个文件可以考虑用并行处理(比如Parallel gem),但要注意内存占用,避免同时加载过多大文件
  3. 数据校验:转换前可以先检查列中所有字符串是否都是合法整数,避免转换失败:
    invalid_rows = col.data.select { |val| val !~ /^\d+$/ }.compact
    unless invalid_rows.empty?
      puts "File #{file} has invalid integer strings: #{invalid_rows.take(5)}"
      next
    end
    

内容的提问来源于stack exchange,提问作者Smithy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 08:12:48