PubMedのシンプソン数
おとなり日記からのぞいてみた記事*1に触発されて作ってみました。
(PubMedもシンプソン数も何に使うのかよくわかってないです。><)
追記
map_countの定義のところで無駄がありました><
- lambda/procを関数内関数のように使うと遅くなる
- それ以前に、map_countのしている処理はひとつだけ
- mapperが要らない。
#!/usr/bin/env ruby require 'rexml/document' require 'open-uri' def count(gene) url = "http://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi?db=pubmed&term="+gene source = open(url).read doc = REXML::Document.new source return doc.elements['/eSearchResult/Count'].text.to_i end #p map_count([[1,2],3]) => [[count(1), count(2)],count(3)] #たくさん調べるときに def map_count arr arr.map { |e| (e.respond_to? :flatten)? map_count(e) : count(e)} end ##=============前に作った時の========= ##def map_count arr ## #Arrayオブジェクトならflattenを持ってるかな〜ってことで ## mapper = proc do |a| ## a.map { |e| (e.respond_to? :flatten)? mapper.call(e) : count(e)} ## end ## ## mapper[arr] ##end ##==================================== #シンプソン数を調べる前に負の数をチェック def ok? arr arr.flatten.each {|e| return false if e < 0} true end #シンプソン数の計算 def simpson args #[[count(x), count(y)], count(xny)]という感じの配列が引数になります。 exit(-1) unless ok? args args[1] / args[0].min.to_f end #配列の要素からそれぞれのシンプソン数を求める def calc_simpson_from_array arr combinations = (all_comb(arr)) num_array = map_count(combinations) labels = combinations.map{|e| e[1].to_s} labels.zip(num_array.map{|e| simpson(e)}) end def all_comb elems dp = proc {|a,b| a.map {|ae| b.map {|be| ae+"+"+be}}} result = [] until elems.empty? tmp = elems.shift result << elems.map {|e| dp.call(tmp,e)} end result.flatten!.map {|e| [e.split("+"),e]} end def main *args exit(-1) if args.size < 2 calc_simpson_from_array(args) end main ARGV if $0 == __FILE__ seed = ["CDK2", "CDK6", "CDK3", "CDK5"] (calc_simpson_from_array(seed)).each {|e| p e} #==結果== #["CDK2+CDK6", 0.432032301480485] #["CDK2+CDK3", 0.680851063829787] #["CDK2+CDK5", 0.127956989247312] #["CDK6+CDK3", 0.191489361702128] #["CDK6+CDK5", 0.0390309555854643] #["CDK3+CDK5", 0.297872340425532] end