• 締切済み

Ruby ヒストグラムの作成

画像の輝度値が保存されたtxtファイルを開いて、輝度値のヒストグラムを表示したいのですがrubyの配列の操作に戸惑っています。histgram[value] += 1のvalueが不確定なのでnilになってしまいます。何か良い解決方法はありますか? image.txtは 輝度値 その他の情報となっているためsplit[0]で輝度値部分のみを抽出しています。 f = open('image.txt') color = Array.new histogram = Array.new correlation = Array.new n = 0 while c = f.gets color[n] = c.split[0].to_i value = c.split[0].to_i histogram[value] += 1 if(n>1) correlation[value + 50 * color[n-1] ] += 1 end n+=1 end f.close

みんなの回答

  • ki073
  • ベストアンサー率77% (491/634)
回答No.2

要素の上限が分かっていることがほとんどなので、No.1の回答で良いのですが、ちょっと違った方法を紹介します。 histogram[value]=histogram[value] ? histogram[value] +1 : 1 histogram[value]を条件判断し、nilの時には1にするものです。まあ当たり前と言えば当たり前の方法です。 もうひとつ、 histogram[value] ||= 0 histogram[value] += 1 最初の行を追加します。これはnilの場合(falseも)に0を代入するというもので初期化ができます。 これらの場合いずれにしても代入していない要素はnilになりますので、後で0にしてやらないと不都合があるかも知れません。 グラフを書くところまで考えるなら、rsrubyでRの機能を使うのが便利なように思います。 gnuplotよりも高度なグラフが書きやすいのと、統計計算が簡単にできるので私はもっぱらrsrubyを使っています。 (Rをダウンロードして、gemでrsrubyをインストールします)

全文を見る
すると、全ての回答が全文表示されます。
  • siffon9
  • ベストアンサー率64% (136/211)
回答No.1

こんにちは > histgram[value] += 1のvalueが不確定なのでnilになってしまいます。 多分 histgram[]の各要素の初期値がnilなので+1ができないという意味だと思うのですが、初期値を決めてあげれば良いです。(詳しくは参照URLをご確認くださいね) size = 10 histogram = Array.new(size, 0) p histogram[0] # => 0 p histogram[9] # => 0 p histogram[10] # => nil それとも、もしかして value = c.split[0].to_iが上手く数値に変換されないという意味でしょうか? その場合は、image.txtの問題のある行を提示していただいた方が良いと思います。

参考URL:
http://doc.ruby-lang.org/ja/1.9.3/class/Array.html
全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • Ruby

    class CDPlayer def playDisk(disk) puts "playing a "+disk+".\n"; end end class CDRadioCaset < CDPlayer def playRadio(channel) puts "playing a"+channel+"\n"; end def playCaset(tape) puts "playing a "+tape+"\n"; end end class DVDRPlayer < CDPlayer def playDisk(disk) puts "playing a"+disk+"\n" end def recoredDisk(disk) puts "recording to a "+ disk+". \n" end end cd=CDPlayer.new puts "CDPlayer. \n" cd.playDisk("CD") radio=CDRadioCaset.new puts "\n CDRadioCaset. \n" radio.playRadio("Radio") radio.playCaset("Caset") dvd=DVDRPlayer.new puts "\n DVDRPlayer.\n" dvd.playDisk(" CD or DVD") dvd.recoredDisk("disk") の意味わかる方、教えてください

  • Rubyでの比較 (Float)

    Ruby初心者です。 簡単な比較を行いたいんですが、エラーが出てしまいます。 ファイルに ex. ruby_test.rb 0 12.3243 32 112.233 0.33123 とあり、このファイルを読み込んで比較しようとしています。 以下のコードで比較しようとしました。 ----------------------------------------------------------- fp = open("c:/ruby_test.txt") aaa = Array.new while line2 = fp.gets line2.chomp! bbb = line2.split(/\t/) aaa << bbb[1] if ( bbb[2] < 1.301029996 ) then       ※11行目 print "aaa\n" elsif ( bbb[2] < 8.164943898 ) then print "bbb\n" elsif ( bbb[2] >= 8.164943898 ) then print "ccc\n" end end fp.close -------------------------------------------- 実行すると ( ※ **** はファイル名 ) C:/ruby/*******.rb:11:in'<': comparison of String with Float failed (Argument Error) というエラーが出ます。 比較する  bbb[2] < 1.301029996  を bbb[2] < "1.301029996" すれば 動きますが、これでは文字列としての比較になってしまいますよね?? Floatは数字として比較するにはどうしたらよいのでしょうか? どなたか宜しくお願いします。

  • Rubyのプログラムについて

    Rubyのプログラムについて、宜しければ教えてください。 def fct(n, f=1) if n<=1 then f else fct(n-1, n*f) end end def factorial(n) (1..n).inject{|x,y| x*y} end def factorial(n) eval( [*(1..n)].join("*") ) end このプログラムが、階乗を計算するメソッドになっているみたいなのですが、なぜコレだけで階乗が計算できるのでしょうか? 宜しければ教えてください><

    • ベストアンサー
    • Ruby
  • <html>

    <html> <head> <title>Quiz</title> <script language="javascript"> <!-- var n=0; var ten=0; var f_start=0 var f_ok=0 var n_max=0; function RTN_START(){ if(f_start==1){ if(confirm('クイズを中断して、やり直しますか?')==true){ f_start=1; n=0; ten=0; document.forms[0].txtKAZ.value=n; document.forms[0].txtTEN.value=ten; RTN_1(n); } else{} } else{ f_start=1; n=0; ten=0; document.forms[0].txtKAZ.value=n; document.forms[0].txtTEN.value=ten; RTN_1(n) }; }; function RTN_1(s){ if(s>=n_max){ RTN_END(); } else{ document.forms[0].txtMON.value=mon[n]; document.forms[0].txtKI1.value=ki1[n]; document.forms[0].txtKI2.value=ki2[n]; document.forms[0].txtKI3.value=ki3[n]; f_ok=1; }; }; function RTN_2(s){ if(f_ok==0){ } else{ f_ok=0; if(s==sei[n]){ document.forms[0].txtMON.value="ピンポン!正 解 です。"; document.forms[0].txtTEN.value=++ten*10; } else{ document.forms[0].txtMON.value="残念、はずれです。"; }; document.forms[0].txtKAZ.value=n+1; n++; window.setTimeout('RTN_1(n)',1000) }; }; function RTN_END(){ var str=""; var rit=0; document.forms[0].txtKAZ.value=n; document.forms[0].txtKI1.value=""; document.forms[0].txtKI2.value=""; document.forms[0].txtKI3.value=""; rit=Math.round(ten*100/n_max); . . }; mon=new Array(); ki1=new Array(); ki2=new Array(); ki3=new Array(); sei=new Array(); mon[n]="1+1?"; ki1[n]="1"; ki2[n]="2"; ki3[n]="3"; sei[n++]="2"; mon[n]="3+4?"; ki1[n]="4"; ki2[n]="6"; ki3[n]="7"; sei[n++]="3"; . . . n_max=n //--> </script> </head> <body> <FORM action="" method=post> <div align="center"> 3択クイズ <br><br> <input onclick=RTN_START(); type=button value=スタート> <HR> <br> 解答問題数 : <input size=3 name=txtKAZ> 獲得得点 : <input size=3 name=txtTEN> <br> <textarea name=txtMON rows=4 cols=45></textarea> <br><br> <input onclick=RTN_2(1) type=button value=" 1 "> <input size=25 name=txtKI1> <br> <input onclick=RTN_2(2) type=button value=" 2 "> <input size=25 name=txtKI2> <br> <input onclick=RTN_2(3) type=button value=" 3 "> <input size=25 name=txtKI3> </FORM> </div> </body> </html> ランダムで問題と選択肢を出題したいのですがわかりません。

  • ソート時同じ値がある場合、表示順をコントロールする事は可能ですか?

    ハッシュの配列を配列の数の多い順に表示する場合で配列の数が同じの場合の最初に表示される配列の数字につきまして この配列の数が同じである場合の表示順序を意図した順番にする事は可能でございますか? この意図した順番と申しますのは、小さい数字を先に表示するのではなく下記の@array2の配列値の並んでいる順や別途配列に0~9の数字を適当に入れておきにそれを参考に評価するという形を希望しており模索中なのですが、まずこの事につきまして可能か不可能かをご教授願いたいのと、もし可能でしたらどうか解決に至る先輩方のお知恵をお借り出来ませんでしょうか よろしくお願い致します。 #!/usr/bin/perl use Tie::IxHash; @array0_n=('a','b','c','d'); @array1_n=('e','f','g'); @array2_n=('h','i'); @array3_n=('j'); @array4_n=(); @array5_n=(); @array6_n=('k'); @array7_n=('l','n'); @array8_n=('m','o','p'); @array9_n=('q','r','s','t'); %array1 = ( '0' => [ (@array0_n) ], '1' => [ (@array1_n) ], '2' => [ (@array2_n) ], '3' => [ (@array3_n) ], '4' => [ (@array4_n) ], '5' => [ (@array5_n) ], '6' => [ (@array6_n) ], '7' => [ (@array7_n) ], '8' => [ (@array8_n) ], '9' => [ (@array9_n) ], ); #配列の数の多い順に並び替え my @array2 =reverse sort { scalar @{$array1{$b}} <=> scalar @{$array1{$a}} or $a <=> $b } keys %array1; @array9_n2=('a2','b2','c2','d2'); @array1_n2=('e2','f2','g2'); @array2_n2=('h2','i2'); @array3_n2=('j2'); @array4_n2=(); @array5_n2=(); @array6_n2=('k2'); @array7_n2=('l2','n2'); @array8_n2=('m2','o2','p2'); @array0_n2=('q2','r2','s2','t2'); tie %TmpList, 'Tie::IxHash'; #@array2を元に更に動的にハッシュ内に配列を作成 foreach(@array2){ my $x="array$_\_n2"; $TmpList{$_}=[(@$x)]; print "$_,$#{$x},@$x<br>\n"; } print "1-end\n"; while ( ( $key , $value ) = each %TmpList ){ print "key:$key value:@$value\n" ; } print "2-end\n"; my @array3 = sort { scalar @{$TmpList{$b}} <=> scalar @{$TmpList{$a}} or $a <=> $b } keys %TmpList; #Tie::IxHashモジュールで表示する際の順番を固定出来るかテスト foreach(@array3){ my $x="array$_\_n2"; $TmpList2{$_}=[(@$x)]; print "$_,$#{$x},@$x<br>\n"; } print "3-end\n"; __END__;

    • ベストアンサー
    • Perl
  • Rubyのルンゲクッタ法がうまくいきません

    Rubyでルンゲクッタ法でy=exp(x**2)と比較しようという問題で、下のようなプログラムを組むとyの値がかなり大きくなってしまいます。どこが間違っているのでしょうか。教えてください。 #! ruby -Ks #ルンゲックッタ def df(a,b) z=2*a*b return z end n=10 x=Array.new(n) y=Array.new(n) x[0]=0.0 y[0]=1.0 h=1.0/n #任意で変更 fw=File.open("output2.txt","w") for i in 0..n k1=df(x[i],y[i])*h k2=df(x[i]+h/2,y[i]+k1/2)*h k3=df(x[i]+h/2,y[i]+k2/2)*h k4=df(x[i]+h,y[i]+k3) k=(k1+2*k2+2*k3+k4)/6 x[i+1]=x[i]+h y[i+1]=y[i]+k fw.print x[i]," ",y[i]," ","\n" end fw.close()

    • ベストアンサー
    • Ruby
  • 動的なハッシュの配列を作成したい

    #お世話になります。最終的には、下記のように配列の順番にハッシュを作成したいのですが、ご教授願えませんでしょうか #!/usr/bin/perl #想定される配列 @array=(0,2,4,6,8,1,3,5,7,9); #下記が最終的に動的に作成したいハッシュの形です。 %List = ( '0' => [ (@array0_n) ], '2' => [ (@array2_n) ], '4' => [ (@array4_n) ], '6' => [ (@array6_n) ], '8' => [ (@array8_n) ], '1' => [ (@array1_n) ], '3' => [ (@array3_n) ], '5' => [ (@array5_n) ], '7' => [ (@array7_n) ], '9' => [ (@array9_n) ], ); $a='array'; $n='_n'; foreach (@array){ #試行錯誤中... print "\@{${a}[$_]{$n}}=@{${a}[$_]{$n}}"; } __END__; お忙しいかとは存じますが、よろしくお願いいたします。

    • ベストアンサー
    • Perl
  • エクセルで四者択一の問題を作りたい。・フォーム画面のボタンをクリック、解答、採点画面を出したい。

    一応、フォーム画面で、ボタンをクリックするとデータシートから 持ってきて、それを問題がなくなるまで繰り返したいのですが、うまく いきません。 Private Sub cmd次_click() Dim n As Integer For n = 3 To Cells(Rows.Count, 1).End(xlUp).Row txt設問.Value = Worksheets("データ").Cells(n, 1).Value   txt問1.Value = Worksheets("データ").Cells(n, 2).Value txt問2.Value = Worksheets("データ").Cells(n, 3).Value txt問3.Value = Worksheets("データ").Cells(n, 4).Value txt問4.Value = Worksheets("データ").Cells(n, 5).Value n = n + 1 Next n End Sub Private Sub cmd判定_click() If op3.Value = True Then txt正解.Value = "○" Else txt正解.Value = "×" End If End Sub Private Sub cmd消去_Click() txt設問.Value = "" txt問1.Value = "" txt問2.Value = "" txt問3.Value = "" txt問4.Value = "" txt正解.Value = "" op1.Value = "" op2.Value = "" op3.Value = "" op4.Value = "" End Sub よろしければ、教えていただけないでしょうか?

  • perlでファイルの拡張子を除いた文字列の取得

    perlでファイルの拡張子を除いた文字列を取得するにはどうすればいいんでしょうか? foo.txt --> foo aaa.pl --> aaa splitを使用して @array = split(/./,<filename>) $value = $array[0] としてもうまく取得できないんですが。。 よろしくお願いします。

    • ベストアンサー
    • Perl
  • Rubyの株価ダウンロードプログラム

    以下は、Yhooファイナンスからの株価ダウンロードプログラムらしいのですが、私にはどういったことをしているのか、いまいちわかりません。 どなたか解説していただけませんか。 require 'open-uri' require 'nkf' require 'jcode' require 'date' $KCODE='s' # 漢字コードをEUCに。Windowsでは 's' #****シフトJISに変換**** class String def to_sjis henkan = NKF.nkf('-s', self) henkan end end #*************** today = Date::today regEx = '(\d+)年(\d+)月(\d+)日<\/small><\/td><td><small>([\d,]+)<\/small><\/td><td><small>([\d,]+)<\/small><\/td><td><small>([\d,]+)<\/small><\/td><td><small><b>([\d,]+)<\/b><\/small><\/td><td><small>([\d,]+)<\/small><\/td><td><small>([\d,]+)' 1301.upto(9999) do |meigara| begin begin meigaradatafile = open("#{meigara}.csv" , "r" ) rescue puts "#{meigara}" + 'は存在しません' meigaradatafile = open("#{meigara}.csv" , "w" ) meigaradatafile.close meigaradatafile = open("#{meigara}.csv" , "r" ) end meigaradata = meigaradatafile.readlines if meigaradata == [] lastdate = Date::new(1983 , 1 , 4) else meigaradatalastline = meigaradata[meigaradata.length-1].split(/\s*,\s*/) lastyear = meigaradatalastline[0] lastmonth = meigaradatalastline[1] lastday = meigaradatalastline[2] meigaradatafile.close lastdate = Date::new(lastyear.to_i , lastmonth.to_i , lastday.to_i) if lastdate >= today next end lastdate = lastdate + 1 end starttime = Time.now temp2 = String.new max = today - lastdate 0.step(max , 50) do |i| begin f = open("http://table.yahoo.co.jp/t?s=#{meigara}.t&a=#{lastdate.month 5;&b=#{lastdate.day}&c=#{lastdate.year}&d=# 23;today.month 5;&e=#{today.day 25;&f=#{;today.year}&g=d&q=t&y=#{i}&z=#{meigara}.t&x=.csv") rescue TimeoutError puts 'タイムアウト リトライ' retry end str = Array.new temp = String.new temp = f.read.to_sjis temp3 = Array.new temp.each_line do |line| line = line.gsub("," , "") if line.scan(/#{regEx}/) != [] str.push line.scan(/#{regEx}/) end end p meigara.to_s + ':' + i.to_s if str == [] break end str.each do |j| temp3.push j end temp3.each do |k| temp2 = k.join(",").to_s + "\n" + temp2 end end if temp2 != "" foo = open("#{meigara}.csv",'a') foo.puts temp2 foo.close end elapsedtime = (Time.now - starttime)/60 yosou = elapsedtime * (9999 - meigara.to_i) puts meigara.to_s + ' ' + '経過時間' + ':' + (elapsedtime.to_s) + '予想時間' + ':' + (yosou/60/60).to_s rescue retry end end