Create CSV file from 2d array perl - arrays

I am trying to load a csv file, transpose it and write a new one. I have everything working correctly except writing a new file. I have looked around online without success.
use strict;
use warnings;
use Text::CSV;
use Data::Dump qw(dump);
use Array::Transpose;
my #data; # 2D array for CSV data
my $file = 'sample_array.csv';
my $csv = Text::CSV->new;
open my $fh, '<', $file or die "Could not open $file: $!";
while( my $row = $csv->getline( $fh ) ) {
shift #$row; # throw away first value
push #data, $row;
}
#data=transpose(\#data);
dump(#data);
The output here is the transposed array #data (["blah", 23, 22, 43], ["tk1", 1, 11, 15],["huh", 5, 55, 55]). I need that output to be written to a new CSV file.
CSV file:
text,blah,tkl,huh
14,23,1,5
12,22,11,55
23,42,15,55

Refer to the code after dump. This was derived from the Text::CSV SYNOPSIS:
use strict;
use warnings;
use Text::CSV;
use Data::Dump qw(dump);
use Array::Transpose;
my #data; # 2D array for CSV data
my $file = 'sample_array.csv';
my $csv = Text::CSV->new;
open my $fh, '<', $file or die "Could not open $file: $!";
while( my $row = $csv->getline( $fh ) ) {
shift #$row; # throw away first value
push #data, $row;
}
#data=transpose(\#data);
dump(#data);
open $fh, ">:encoding(utf8)", "new.csv" or die "new.csv: $!";
for (#data) {
$csv->print($fh, $_);
print $fh "\n";
}
close $fh or die "new.csv: $!";

Along with Toolic's addition I had to make some edits due to the specific type of data I was dealing with. This was an extremely large set with engineering symbols & units and negative numbers with long decimals. For reference, my final code is below.
use strict;
use warnings;
use Text::CSV;
use Data::Dump qw(dump);
use Array::Transpose;
my #data; # 2D array for CSV data
my $file = 'rawdata.csv';
my $csv = Text::CSV->new({ binary => 1, quote_null => 0 });
open my $fh, '<', $file or die "Could not open $file: $!";
while( my $row = $csv->getline( $fh ) ) {
#shift #$row; # throw away first value, I needed the first values.
push #data, $row;
}
#data=transpose(\#data);
open $fh, ">:encoding(utf8)", "rawdata_trans.csv" or die "rawdata_trans.csv: $!";
for (#data) {
$csv->print($fh, $_);
print $fh "\n";
}
close $fh or die "rawdata_trans.csv: $!";

Related

Convert string into array perl

I have a script which takes headers of a multi-fasta file and pushes them into an array. Then I want to loop through this array to find a specific pattern and perform some commands.
open(FH, '<', $ref_seq) or die $!;
while(<FH>){
$line = $_;
chomp $line;
if(m/^>([^\s]+)/){
$ref_header = $1;
print "$ref_header\n";
chomp $header;
if($1 eq $header){
$ref_header = $header;
#print "header is $ref_header\n";
}
}
}
This code prints headers like
chr1
chr2
chr3
How can I push these headers into an array?
I tried following code, but it splits individual letters, instead of $header_array[0] being chr1
#header_array = split(/\n*/, $ref_header);
print ("Here's the first element $header_array[0]");
Any help will be appreciated.
Shorten the code as shown below, removing some extra statements, and use push. You can combine push and the pattern match:
#!/usr/bin/env perl
use strict;
use warnings;
use Carp;
my $in_file = shift;
my #headers;
open my $in_fh, '<', $in_file or croak "cannot open $in_file: $!";
while ( <$in_fh> ) {
push #headers, />(\S+)/;
}
close $in_fh or croak "cannot close $in_file: $!";
print "#headers";
# Now, loop through headers and select the ones you need, for example:
for my $header ( #headers ) {
if ( $header =~ /foo/ ) {
# do something
}
}
A few suggestion on fixing your original code are below:
# Always use strict and use warnings.
# Remove extra parens and make the error message more informative:
open(FH, '<', $ref_seq) or die $!;
while(<FH>){
$line = $_;
chomp $line;
# [^\s] is simply \S:
if(m/^>([^\s]+)/){
$ref_header = $1;
print "$ref_header\n";
# where is $header coming from?
chomp $header;
# if the condition is satisfied, this assignment does not make sense:
# $ref_header is already the same as $header:
if($1 eq $header){
$ref_header = $header;
#print "header is $ref_header\n";
}
}
}
You can use push:
push #header_array, $ref_header;

Perl array overriding

I am trying to do sum of the array in my perl code but I was not able to get the right output.
Here is my sample code
use File::Find::Rule;
use Date::Parse;
my ($dir, $type, $fh, $line, $str_1,
$str_2,$str_3, $str_4);
my #array;
$dir = '/dir/test/';
$type = '*';
$str_1 = 'somestr1';
$str_2 = 'somestr2';
$str_3 = 'somestr3';
$str_4 = 'somestr4';
my #files = File::Find::Rule->file()->name($type)->in($dir);
open $out, '>>', "output_log" or die "Unable to open 'output_log' : $!";
print $out "\Logs \n";
print $out "--------------------------\n";
close $out or die "Unable to finish writing output_log : $!";
for my $file (#files) {
open $fh, '<', $file or die "can't open $file: $!";
open $out, '>>', "output_log" or die "Unable to open 'output_log' : $!";
while ( $line = <$fh> ) {
if ( $line !~ /$str_1/ && $line =~ /$str_2/ )
{
#array = $somevar # result of this loop 2,3
}
if ( $line !~ /$str_3/ && $line =~ /$str_4/ )
{
#array = $somevar #result of this loop 2,3,4,5,6
}
}
close $out or die "Unable to finish writing output_log : $!";
}
So Here is what I want
#array = (2,3,2,3,4,5,6)
and sum of #array
but unfornately,if i print this array that is running each and every line but instead i want to write a loop which stores the result in array from both if blocks..
now the code is overriding the #array in the second if block. Hope I made this clear!! Please help
#array = ... overwrites the contents of the array. Use push to add elements to an existing array.
For sum, see sum (or sum0) in List::Util.

Perl Hashes of Arrays and Some issues

I currently have a csv file that looks like this:
a,b
a,d
a,f
c,h
c,d
So I saved these into a hash such that the key "a" is an array with "b,d,f" and the key "c" is an array with "h,d"... this is what I used for that:
while(<$fh>)
{
chomp;
my #row = split /,/;
my $cat = shift #row;
$category = $cat if (!($cat eq $category)) ;
push #{$hash{$category}}, #row;
}
close($fh);
Not sure about the efficiency but it seems to work when I do a Data Dump...
Now, the issue I'm having is this; I want to create a new file for each key, and in each of those files I want to print every element in the key, as such:
file "a" would look like this:
b
d
f
<end of file>
Any ideas? Everything I've tried isn't working, I'm not too familiar / experienced with hashes...
Thanks in advance :)
The output process is very simple using the each iterator, which provides the key and value pair for the next hash element in a single call
use strict;
use warnings;
use autodie;
open my $fh, '<', 'myfile.csv';
my %data;
while (<$fh>) {
chomp;
my ($cat, $val) = split /,/;
push #{ $data{$cat} }, $val;
}
while (my ($cat, $values) = each %data) {
open my $out_fh, '>', $cat;
print $out_fh "$_\n" for #$values;
}
#!/usr/bin/perl
use strict;
use warnings;
my %foos_by_cat;
{
open(my $fh_in, '<', ...) or die $!;
while (<$fh_in>) {
chomp;
my ($cat, $foo) = split /,/;
push #{ $foos_by_cat{$cat} }, $foo;
}
}
for my $cat (keys %foos_by_cat) {
open(my $fh_out, '>', $cat) or die $!;
for my $foo (#{ $foos_by_cat{$cat} }) {
print($fh_out "$foo\n");
}
}
I wrote the inner loop as I did to show the symmetry between reading and writing, but it can also be written as follows:
print($fh_out "$_\n") for #{ $foos_by_cat{$cat} };

print specific word staring with in text and count

I like to find word start with sid=word and sid=text and print and count it the same word.
sid=word 2
sid=text 5
I have try make some script
use warnings;
use strict;
my $input = 'input.txt';
my $output = 'output.txt';
open (FILE, "<", $input) or die "Can not open $input $!";
open my $out, '>', $output or die "Can not open $output $!";
while (<FILE>){
foreach my #arr = /(?: ^|\s )(sid=\S*) {
$count{$arr}++;
}
}
foreach my #arr (sort keys %count){
printf "%-31s %s\n", $str, $count{$arr};
}
but show error missing $ on loop variable
anyone can help me out what i miss.
thanks.
This should produce desired output to output.txt, with words in order of appearance
use warnings;
use strict;
my $input = 'input.txt';
my $output = 'output.txt';
open (my $FILE, "<", $input) or die "Can not open $input $!";
open (my $out, ">", $output) or die "Can not open $output $!";
my (%count, #arr);
while (<$FILE>){
if ( /(?: ^|\s )(sid=\S*)/x ) {
push #arr, $1 if !$count{$1};
$count{$1}++;
}
}
foreach my $str (#arr) {
print $out sprintf("%-31s %s\n", $str, $count{$str});
}

Simple Perl: can't compare array elements to strings

I initially wrote a script to convert a wordlist(each line is just 1 word) into an array of words #keywords(each line an element) using:
-------------------
open (FH, "< $keyword_file") or die "Can't open $keyword_file for read: $!";
my #keywords;
while (<FH>) {
push (#keywords, $_);
}
close FH or die "Cannot close $keyword_file: $!";
--------------------
I am now trying to use regex to compare this with other strings, but i just keep getting false results for some reason?
-----------------------
FULL PROGRAM
-----------------------------------
#!/usr/bin/env perl
use strict;
use warnings;
use Data::Dumper;
print "\n[Keywords]";
my $keyword_file = "keywords.txt";
#read keywords
my #keywords;
open (FH, "$keyword_file") or die "Can't open $keyword_file for read: $!";
while (<FH>) {
chomp;
push (#keywords, $_);
}
close FH or die "Cannot close $keyword_file: $!";
#pattern match
foreach(#keywords)
{
if ("print" =~ m/$_/) {
print "match found\n";
}
}
----------------------------------
the above argument is supposed to be true but it just keeps returning false. What am i doing wrong? Is this because the array is storing nextlines(enter) as well (sorry if i sound ignorant for thinking this :p)?
Yes, you need to chomp your array to remove line endings:
chomp(#keywords);
You forget to remove the newline in your keywords, try this:
while (<FH>) {
chomp;
push (#keywords, $_);
}
Here is a test program:
#!/usr/bin/perl
use strict;
use warnings;
my #keyword;
while (<DATA>) {
chomp;
push #keyword, $_;
}
foreach (#keyword) {
if ("print exit write" =~ m/$_/) {
print "match found\n";
}
}
__DATA__
print
exit
write

Resources