use v5.14; use warnings; use autodie; use Text::CSV_XS; use Data::Peek; my $csv = Text::CSV_XS->new ({ binary => 1, auto_diag => 1 }); my $hdr = $csv->getline (*DATA); $csv->column_names ($hdr); my ($pn, $pc, @comp) = @$hdr; my %comp = map { $_ => {} } @comp; while (my $row = $csv->getline_hr (*DATA)) { my $p = $row->{$pc}; $comp{$_}{$p} = $row->{$_} for @comp; } DDumper \%comp; __END__ Product Name,Product Code,Company1,Company2,Company3 Test One,C001,Y,N,N Test Two,C002,N,N,Y Test Three,C003,Y,Y,N => { Company1 => { C001 => 'Y', C002 => 'N', C003 => 'Y' }, Company2 => { C001 => 'N', C002 => 'N', C003 => 'Y' }, Company3 => { C001 => 'N', C002 => 'Y', C003 => 'N' } }