🏹

Red Arrowでカラム名の変更

に公開

できません。

けど、Red Arrowを使ったデータフレームライブラリーであるRedAmberではできるんですよね:

df.rename(:old_name => :new_name)

どうやっているんだろうと見てみました[1]
https://github.com/red-data-tools/red_amber/blob/449479bb02c08e083289209a9077c52de0b200f3/lib/red_amber/data_frame_variable_operation.rb#L370-L393

色々やった後にrename_by_hashに投げています。
rename_by_hashの実装は:
https://github.com/red-data-tools/red_amber/blob/449479bb02c08e083289209a9077c52de0b200f3/lib/red_amber/data_frame_variable_operation.rb#L648-L665

Arrow::Tableを作り直していました。
と言ってもデータその物をコピーしたりはせずに、データの名前や型定義であるスキーマだけ作り直してArrow::Tableを作っています(newの第一引数):

Arrow::Table.new(Arrow::Schema.new(fields), @table.columns)

これはまあ、できるのはできるけどめんどくさいので、やっぱデータフレームライブラリーあると便利ですね。

仮実装

RedAmberを入れるほどじゃないんだけどカラム名の変更だけしたい、みたいな場合はこんなパッチでいけます:

module ArrowRefinement
  refine Arrow::Table do
    def rename_column(from, to=nil)
      case
      when from.kind_of?(String) && to.nil?
        raise ArgumentError, "to is missing"
      when from.kind_of?(Hash) && to
        raise ArgumentError, "to is not needed"
      end
      renames = (from.kind_of?(String) ? {from => to} : from)
                  .transform_keys(&:to_s)
      fields = column_names.collect {|name|
        if to = renames[name]
          from = self[name]
          raise ArgumentError, "column #{name} not found in from" unless from
          Arrow::Field.new(to, from.data_type)
        else
          schema[name]
        end
      }
      Arrow::Table.new(Arrow::Schema.new(fields), columns)
    end
  end
end

using ArrowRefinement

Arrow::Table.load("path/to/data")
  .rename_column("変更前", "変更後")
  .rename_column(
    "変更前1" => "変更後1",
    "変更前2" => "変更前2",
    "変更前3" => "変更前3"
  )

selfじゃなくて新しいArrow::Tableを返すのが気持ち悪い人はいるかも知れない。そういうAPIはRed Arrowでも見掛けるからいいとは思うけど。

脚注
  1. RedAmber v0.5.2 ↩︎

Discussion