From 4d9e6d7e32463c8aa7e3ef7ce8aa10527376bed6 Mon Sep 17 00:00:00 2001 From: Kitaiti Makoto Date: Sun, 7 Jan 2024 06:39:14 +0900 Subject: [PATCH 1/2] :white_check_mark: Add test for DataFrame#to_wide with missing values --- test/test_data_frame_reshaping.rb | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/test_data_frame_reshaping.rb b/test/test_data_frame_reshaping.rb index 98cf7814..88012236 100644 --- a/test/test_data_frame_reshaping.rb +++ b/test/test_data_frame_reshaping.rb @@ -128,5 +128,20 @@ class DataFrameReshapingTest < Test::Unit::TestCase df = @df.rename(NAME: :key1, VALUE: :key2) assert_equal @str, df.to_wide(name: :key1, value: :key2).to_s end + + test '#to_wide with missing values' do + df = DataFrame.new( + names: %w[name1 name1 name1 name2 name2 name3 name3 name3], + NAME: %w[One Two Three One Three One Two Three], + VALUE: [1.1, 2.1, 3.1, 1.2, 3.2, 1.3, 2.3, 3.3] + ) + wide = DataFrame.new( + names: %w[name1 name2 name3], + One: [1.1, 1.2, 1.3], + Two: [2.1, nil, 2.3], + Three: [3.1, 3.2, 3.3] + ) + assert_equal wide, df.to_wide(fill_missing: true) + end end end From f498163ed849e1184cc73080d87d410a48609320 Mon Sep 17 00:00:00 2001 From: Kitaiti Makoto Date: Sun, 7 Jan 2024 06:43:09 +0900 Subject: [PATCH 2/2] :zap: Add fill_missing option to DataFrame#to_wide --- lib/red_amber/data_frame_reshaping.rb | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/lib/red_amber/data_frame_reshaping.rb b/lib/red_amber/data_frame_reshaping.rb index 567d04f4..c0027ec5 100644 --- a/lib/red_amber/data_frame_reshaping.rb +++ b/lib/red_amber/data_frame_reshaping.rb @@ -250,7 +250,7 @@ def to_long(*keep_keys, name: :NAME, value: :VALUE) # # @since 0.2.0 # - def to_wide(name: :NAME, value: :VALUE) + def to_wide(name: :NAME, value: :VALUE, fill_missing: false, fill_with: nil) name = name.to_sym unless keys.include?(name) raise DataFrameArgumentError, @@ -274,6 +274,22 @@ def to_wide(name: :NAME, value: :VALUE) h = converts.to_h hash[keeps.to_h][h[name].to_s.to_sym] = h[value] end + if fill_missing + names = [].union(*hash.values.collect(&:keys)) + hash.each_pair do |ns, vs| + next if vs.length == names.length + + keys = vs.keys + values = vs.values + names.each_with_index do |n, i| + next if vs.key?(n) + + keys.insert(i, n) + values.insert(i, fill_with) + end + hash[ns] = keys.zip(values).to_h + end + end ks = hash.first[0].keys + hash.first[1].keys vs = hash.map { |k, v| k.values + v.values }.transpose DataFrame.new(ks.zip(vs))