From: William James Date: 2007-02-08T05:00:06+09:00 Subject: Re: How do you get the rows out of FasterCSV? On Feb 5, 11:58 pm, ara.t.how...@noaa.gov wrote: > On Tue, 6 Feb 2007, Gary wrote: > > Hi. I want to add a normalized column to a csv file. That is, I want to > > read the file, sum all of a column X, then add another column in which > > each X is divided by the sum. So do I use the CSV rows twice without > > reading the file twice? > > > The examples in the FasterCSV documentation at > >http://fastercsv.rubyforge.org/show class methods that provide > > file-like operations. I want the file read once while the data is read, > > then closed. While reading the first time, the column sum is calculated. > > But then I want to go through the csv rows again, this time writing out > > the rows with their new column. > > > Here's a sketch of what I had in mind. It doesn't work as intended... > > > # read csv file, summing the values > > sum = 0 > > csv = > > FasterCSV.new(open(csv_filename),{:headers=>true}).each_with_index do | > > row, c | > > sum += row["VAL"].to_f > > end > > > # now write > > FasterCSV.open("test_csv_file.csv", "w", {:headers=>true}) do |csvout| > > csv.each_with_index do | row, c | > > row["NORMED"] = row["VAL"].to_f / sum > > csvout << row.headers if c==0 > > csvout << row > > end > > end > > > Also, is there a more graceful way to have the headers written out? > > harp:~ > cat a.rb > require 'rubygems' > require 'fastercsv' > > csv = <<-csv > f,x > a,0 > b,1 > c,2 > d,3 > csv > > fcsv = FasterCSV.new csv, :headers => true > table = fcsv.read > > xs = table['x'].map{|x| x.to_i} > sum = Float xs.inject{|sum,i| sum += i} Should be sum + i. > norm = xs.map{|x| x / sum} > > table['n'] = norm > puts table > > harp:~ > ruby a.rb > f,x,n > a,0,0.0 > b,1,0.166666666666667 > c,2,0.333333333333333 > d,3,0.5 array = "\ f,x a,0 b,1 c,2 d,3 ".split.map{|s| s.split ","} headers = array.shift << 'n' array = array.transpose sum = array[1].inject{|a,b| a.to_i + b.to_i}.to_f array << array[1].map{|x| x.to_i / sum} array = array.transpose ([headers] + array).each{|x| puts x.join(',')} --- output ----- f,x,n a,0,0.0 b,1,0.166666666666667 c,2,0.333333333333333 d,3,0.5