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}
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



-a
-- 
we can deny everything, except that we have the possibility of being better.
simply reflect on that.
- the dalai lama