473,398 Members | 2,380 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,398 software developers and data experts.

rounding csv values

58
Hey all,
still a newbie to perl and programming and still needing some advice.. I have a ".CSV" table that I need to do some (rounding) manipulation on. the table looks something like this.. (the real table is actually comma delimited)

DD | H1 | H2 | H3 | H4
---------------------------------------------------
01 | 69.6 | -1 | 55.215 | 25.1231
02 | -1 | 1.23 | 1.45 | -1

I need it to look like this

DD | H1 | H2 | H3 | H4
---------------------------------------------------
01 | 69.9 | -1 | 55.2 | 25.1
02 | -1 | 1.2 | 1.5 | -1

basically I need to round to the tenth ONLY if the value contains more then 1 value after the decimal and i need the values that are "-1" to stay as "-1"

I've read a bunch of tutorials and still just don't get it.. i can get as far as opening the table but not parsing through it...

Expand|Select|Wrap|Line Numbers
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4.  
  5. my $fileInput="d:/temp/test.csv";
  6. my $fieldnames = 1;
  7.  
  8. open (READ, ">>$fileInput") or die "Can't open $fileInput: $!";
  9.  
  10. my $header;
  11. $header = <READ> if $fieldnames;
  12.  
  13. my @data = <READ>;
  14.  
  15. print READ $header;
i've also read that this will work for rounding

my($number) = shift;
return int($number + .5)

just not sure how to get to $number

thanks immensely ahead of time!
Cheers,
Eric

running locally on windows XP
Jun 19 '07 #1
8 1824
miller
1,089 Expert 1GB
Greetings Eric,

Now there are a lot of way to do this. Some rather perlish ways would actually take only 1 line of code. However, the following script is an example of how to program this responsibly. It uses two modules that will require installation, but this is how I would do what you proposed:

Expand|Select|Wrap|Line Numbers
  1. use Math::Round::Var;
  2. use Text::CSV;
  3. use Tie::File;
  4.  
  5. use strict;
  6.  
  7. my $file = 'test.csv';
  8.  
  9. tie my @array, 'Tie::File', $file or die "Can't open $file: $!";
  10.  
  11. my $csv = Text::CSV->new();
  12. my $rnd = Math::Round::Var->new(0.1);
  13.  
  14. for my $i (1..$#array) { # Note, skip 0 index with Header
  15.     # Parse CSV
  16.     $csv->parse($array[$i]) or die "parse() failed: ", $csv->error_input;
  17.  
  18.     # Round number fields.
  19.     my @fields = $csv->fields;
  20.     for my $j (0..$#fields) {
  21.         # Decimal with 2 digit precision
  22.         if ($fields[$j] =~ m{^-?\d*\.\d{2,}$}) {
  23.             $fields[$j] = $rnd->round($fields[$j]);
  24.         }
  25.     }
  26.  
  27.     # Resave CSV data
  28.     $csv->combine(@fields) or die "combine() failed: ", $csv->error_input;
  29.     $array[$i] = $csv->string;
  30. }
  31.  
  32. 1;
  33.  
  34. __END__
  35.  
This takes in the following input file:
Expand|Select|Wrap|Line Numbers
  1. "DD","H1","H2","H3","H4"
  2. "01","69.6","-1","55.215","25.1231"
  3. "02","-1","1.23","1.45","-1"
  4.  
And changes that file to the following:
Expand|Select|Wrap|Line Numbers
  1. "DD","H1","H2","H3","H4"
  2. "01","69.6","-1","55.2","25.1"
  3. "02","-1","1.2","1.5","-1"
  4.  
- Miller
Attached Files
File Type: txt scratch.txt (743 Bytes, 412 views)
Jun 19 '07 #2
KevinADC
4,059 Expert 2GB
Miller,

why not use "sprintf" and "%.1f" ? I realize this will add a .0 (dotzero) to whole numbers but it seems like that would easy to fix if necessary.
Jun 19 '07 #3
miller
1,089 Expert 1GB
Kevin,

You mean actually search perldoc before answering a question. Why would I do that? :)

perldoc search "round"
returns:
perldoc perlfaq4 Does perl have a round() function?

I simply didn't remember that sprintf had that functionality, because from my viewpoint it should simply truncate. However, actually testing it on data proves that it does in fact round, and amusingly enough that is the implementation method that the Math::Round::Var module uses for decimal rounding. Which probably proves why it's only in version .03 and is likely little used.

That changes my code only slightly, but does clean it up a little.

Expand|Select|Wrap|Line Numbers
  1. use Text::CSV;
  2. use Tie::File;
  3.  
  4. use strict;
  5.  
  6. my $file = 'test.csv';
  7.  
  8. tie my @array, 'Tie::File', $file or die "Can't open $file: $!";
  9.  
  10. my $csv = Text::CSV->new();
  11.  
  12. for my $i (1..$#array) { # Note, skip 0 index with Header
  13.     # Parse CSV
  14.     $csv->parse($array[$i]) or die "parse() failed: ", $csv->error_input;
  15.  
  16.     # Round number fields.
  17.     my @fields = $csv->fields;
  18.     for my $j (0..$#fields) {
  19.         # Decimal with 2 digit precision
  20.         if ($fields[$j] =~ m{^-?\d*\.\d{2,}$}) {
  21.             $fields[$j] = sprintf "%.1f", $fields[$j];
  22.         }
  23.     }
  24.  
  25.     # Resave CSV data
  26.     $csv->combine(@fields) or die "combine() failed: ", $csv->error_input;
  27.     $array[$i] = $csv->string;
  28. }
  29.  
  30. 1;
  31.  
  32. __END__
  33.  
Note, for the "Round number fields" section, I personally would use the following code. But I figure the former is easier to understand for someone new to perl.

Expand|Select|Wrap|Line Numbers
  1.     my @fields = map {
  2.         s{^(-?\d*\.\d{2,})$}{sprintf "%.1f", $1}e; $_
  3.     } $csv->fields;
  4.  
Thanks for the little reminder Kevin,
- Miller
Attached Files
File Type: txt scratch.txt (682 Bytes, 451 views)
Jun 19 '07 #4
erbrose
58
Thanks again for taking the time to enlighten a newbie! I did just get "programming perl" so hopefully my questions will come less and less and perhaps my replies more and more..
One more thing though.. the input .csv file does not contain 'double quotes' around each data value, but the script output does. The only problem with this is the text files I am processing on are >~200mb as inputs then >~300mb as outputs and we were hoping to reduce the files sizes just a bit by rounding the numbers. Im going to keep searching and hopefully find a solution! but some more insight will always be appreciated!
Cheers,
Eric
Jun 19 '07 #5
miller
1,089 Expert 1GB
There's just no making you happy is there? No matter, your question made me learn something. A better module to use is Text::CSV_XS as it uses a C implementation of the previous module and is therefore much faster. It also has been extended with a lot of additional functionality, including only quoting values that truly require it. They are stylistically the same, so only a renaming of the used module is required.

Final version:

Expand|Select|Wrap|Line Numbers
  1. use Text::CSV_XS;
  2. use Tie::File;
  3.  
  4. use strict;
  5.  
  6. my $file = 'test.csv';
  7.  
  8. tie my @array, 'Tie::File', $file or die "Can't open $file: $!";
  9.  
  10. my $csv = Text::CSV_XS->new();
  11.  
  12. for my $i (1..$#array) { # Note, skip 0 index with Header
  13.     # Parse CSV
  14.     $csv->parse($array[$i]) or die "parse() failed: ", $csv->error_input;
  15.  
  16.     # Round number fields.
  17.     my @fields = $csv->fields;
  18.     for my $j (0..$#fields) {
  19.         # Decimal with 2 digit precision
  20.         if ($fields[$j] =~ m{^-?\d*\.\d{2,}$}) {
  21.             $fields[$j] = sprintf "%.1f", $fields[$j];
  22.         }
  23.     }
  24.  
  25.     # Resave CSV data
  26.     $csv->combine(@fields) or die "combine() failed: ", $csv->error_input;
  27.     $array[$i] = $csv->string;
  28. }
  29.  
  30. 1;
  31.  
  32. __END__
  33.  
Attached Files
File Type: txt scratch.txt (688 Bytes, 424 views)
Jun 19 '07 #6
KevinADC
4,059 Expert 2GB
You mean actually search perldoc before answering a question. Why would I do that? :)

LOL @ Miller
Jun 19 '07 #7
erbrose
58
There's just no making you happy is there?
Im happy now :)
i was reading about the text::csv_xs too but didn't see where it would remove the quotes.... got a long way to go!!
Thanks again Miller and Kevin!
Cheers,
Eric
Jun 20 '07 #8
KevinADC
4,059 Expert 2GB
You're welcome


.....
Jun 20 '07 #9

Sign in to post your reply or Sign up for a free account.

Similar topics

4
by: spebola | last post by:
I am using vb.net 2003 professional and I get the following results when using the round method: dim Amount as decimal = 180.255 Amount = Amount.Round(Amount, 2) Amount now contains 180.25. ...
8
by: Zorpiedoman | last post by:
Howcome: Dim D as decimal = .5D msgbox d.Round(D, 0) this returns "0" Now when I went to school .5 rounds UP to 1 not DOWN to zero?????!!! Documentation says this, but what the heck are...
6
by: Jeff Boes | last post by:
(asked last week on .questions, no response) Can anyone explain why this happens? (under 7.4.1) select '2004-05-27 09:00:00.500001-04' :: timestamp(0) ; timestamp ---------------------...
2
by: Jiri Nemec | last post by:
Hello all, I have got one table with rounding values, table contains prices and round types. id price_from price_to rounding 1 0 1500 0.1 2 1500 ...
29
by: Marco | last post by:
Hello, I have : float f = 36.09999999; When I do : char cf; sprintf(cf,"%0.03lf", f); I get : 36.100
18
by: jdrott1 | last post by:
i'm trying to round my currency string to end in 9. it's for a pricing application. this is the function i'm using to get the item in currency: FormatCurrency(BoxCost, , , , TriState.True) if...
5
by: Spoon | last post by:
Hello everyone, I don't understand how the lrint() function works. long lrint(double x); The function returns the nearest long integer to x, consistent with the current rounding mode. It...
248
by: md | last post by:
Hi Does any body know, how to round a double value with a specific number of digits after the decimal points? A function like this: RoundMyDouble (double &value, short numberOfPrecisions) ...
30
by: bdsatish | last post by:
The built-in function round( ) will always "round up", that is 1.5 is rounded to 2.0 and 2.5 is rounded to 3.0. If I want to round to the nearest even, that is my_round(1.5) = 2 # As...
0
by: =?ISO-8859-1?Q?Marcel_M=FCller?= | last post by:
clintonb wrote: There is nothing like an original double amount. If you care about rounding errors you must not store any currency value in an approximate number. You must not do this even once....
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.