ãããNArrayã§ã§ããããããã£ã¨ä¾¿å©ã«ãã - æå¹å¸ä¸å¤®åºRubyä¼è°01
ããå é±ã®è©±ã«ãªã£ã¦ãã¾ãã¾ããããTricknotesãã主å¬ã®æå¹å¸ä¸å¤®åºRubyä¼è°01ã«åå ãã¦ãã¾ããã ã³ã³ãã¯ããªè¦æ¨¡ãªããããé常ã«è¯ãRubyistã®æ´»åã観測ãï¼byãã¾ã ããï¼ããããææ義ãã¤æ¥½ããä¼è°ã§ããã
ã©ã®çºè¡¨ãè´ãå¿ãã®ãããã°ããããã®ã§ããããä¸ã§ãtmaedaããã®ãããNArrayã§ã§ããããã¯æ°å¤è¨ç®ã©ã¤ãã©ãªã®NArrayãbetter Excelã¨ãã¦ä½¿ã£ã¦ãã¾ãã³ãã«ãã¯ã¹ççºæ³ã§è¡æçã§ããã
ãã®çºè¡¨ã®ãªãã§ãNArrayã®è»¸ãHuman-Readableãªå½¢å¼ã§æ±ããã©ããã¼ã¯ã©ã¹ãä½ãã¨ä¾¿å©ã ããã¨ããã話ãããã¾ãããã
ããããã£ã¨ä¾¿å©ã«ããNArrayCube
ã¯ã©ã¹ã試é¨çã«å®è£
ãã¦ã¿ãã®ã§ç´¹ä»ãã¾ãã
使ãæ¹
# åºãä¸ä»£ãæ§å¥ã®3軸ãããªã売ä¸è¡¨ãä½æ cube = NArrayCube.new(:int, { title: :shop, labels: ['A', 'B', 'C'] }, { title: :generation, labels: ['teens', 'twenties', 'thirties', 'fourties'] }, { title: :gender, labels: ['men', 'women'] } ) # åºAã20代ãç·æ§ã®å£²ä¸ãå ¥å cube.set({ shop: 'A', generation: 'teens', gender: 'men' }, 100) # åºAã10代ã®å£²ä¸ãå ¥å cube.set({ shop: 'A', generation: 'teens' }, [90, 110]) # åºBã®å£²ä¸ãä¸æ°ã«å ¥åï¼4ä¸ä»£ à 2æ§å¥ã®Arrayï¼ cube.set({ shop: 'B'}, [ [50, 80, 60, 75], [70, 40, 35, 50] ]) # åºCã®å£²ä¸ãä¸æ°ã«å ¥åï¼ç¬¬2å¼æ°ãä¸æ¬¡å ã®Arrayã§ä¸ããã¨åæã«4x2ã«å¤æãã¦ããã cube.set({ shop: 'C'}, [70, 80, 55, 60, 30, 45, 70, 60]) # 10代ã®å£²ä¸ãåå¾ cube.get({ generation: 'teens' }) #=> # #<NArrayCube: ... # [ [ 90, 50, 70 ], # [ 110, 70, 30 ] ]> # 10代ã®å£²ä¸ã®åè¨ cube.get({ generation: 'teens' }).sum #=> 420 # 10代ã®å£²ä¸ãåºãã¨ã«éè¨ => ç·æ§ï¼å¥³æ§ã®å¤ãè¨ç®ããã°ãã cube.get({ generation: 'teens' }).sum(:gender) #=> # NArray.int(3): # [ 200, 120, 100 ]
ãã
NArrayCube#set
ã§è¤æ°ã®ã»ã«ã«ä¸æ°ã«å¤ãæµãè¾¼ããNArray#sum
ãNArrayCube#sum
ã§ã©ãããããã¨ã«ããã軸ã®æå®ãHuman-Readableã«è¡ãã
TODO
- specæ¸ã
- documentæ¸ã
NArray#sum
ã ããããªãprod
/max
/min
ã¨ããã®ä»ã®ã¡ã½ããã«ã対å¿ããã =>method_missing
ã¨ã使ããããªï¼- ã10代ã®å£²ä¸ãåºãã¨ã«éè¨ãã¯
cube.get({ generation: 'teens' }).sum_by(:shop)
ã¿ããã«æ¸ããã»ããç´æç - getã§è»¸ã©ãã«ãè¤æ°æå®ã§ããã»ãããã
cube.get({ shop: ['A', 'B'] })
- tmaedaããããããã£ã¦è¨ã£ã¦ããããGemåãã¦å ¬é
ã³ã¼ã
require 'narray' class NArrayCube NARRAY_TYPES = %i(byte sint int sfloat float scomplex complex object) class NArrayAxis def initialize(id, title, labels) @id = id @title = title.to_s @labels = labels.map(&:to_s) end def value_index(value) @labels.index(value.to_s) end attr_reader :id, :title, :labels end def initialize(type, *axes) if NARRAY_TYPES.include?(type) @type = type else raise ArgumentError end @axes = axes.map.with_index do |a, i| NArrayAxis.new(i, a[:title], a[:labels]) end @narray = NArray.method(type).call(*@axes.map { |a| a.labels.length }) end def get(conditions) conditions = build_condition(conditions) values = @narray[*conditions] axes = conditions.map.with_index do |c, id| if c.class == Array a = @axes[id] { title: a.title, labels: a.labels.select.with_index { |v, i| c.include? i } } else nil end end NArrayCube.new(@type, *axes.compact).set({}, values) end def set(conditions, values) conditions = build_condition(conditions) unless [Array, NArray].include?(values.class) @narray[*conditions] = values else partial = @narray[*conditions] values = NArray.to_na(values) if partial.shape == values.shape @narray[*conditions] = values elsif partial.total == values.total && values.shape.length == 1 @narray[*conditions] = values.reshape(*partial.shape) else raise ArgumentError end end self end def sum(*titles) if titles.length > 0 @narray.sum(*titles.map { |t| axis(t).id }) else @narray.sum end end private def build_condition(conditions) cond = @axes.map { |a| (0..(a.labels.length - 1)).to_a } conditions.each do |title, label| a = axis(title) cond[a.id] = a.value_index(label) end cond end def axis(title) @axes.select { |a| a.title == title.to_s }.first end end