在Perl中转置CSV数据
我是一名Perl初学者,目前正在编写一个Perl脚本来自动化我们的一些任务。我正在编写的一个脚本涉及从系统中提取性能数据,将其存储在CSV文件中,并生成Excel图表。在这个脚本上工作了几天之后,我成功地将提取的数据转换成CSV,但是现在,我在尝试转换数据时遇到了困难!我看过这个帖子(多亏了道尔顿的脚本):,但我似乎无法将它应用到我的案例中 基本上,我的CSV文件每行包含一个每日数据,列为一天中的小时数(24小时): 现在,我想转置它,这样我将写入新CSV文件的结果数据将如下所示:在Perl中转置CSV数据,perl,csv,transpose,Perl,Csv,Transpose,我是一名Perl初学者,目前正在编写一个Perl脚本来自动化我们的一些任务。我正在编写的一个脚本涉及从系统中提取性能数据,将其存储在CSV文件中,并生成Excel图表。在这个脚本上工作了几天之后,我成功地将提取的数据转换成CSV,但是现在,我在尝试转换数据时遇到了困难!我看过这个帖子(多亏了道尔顿的脚本):,但我似乎无法将它应用到我的案例中 基本上,我的CSV文件每行包含一个每日数据,列为一天中的小时数(24小时): 现在,我想转置它,这样我将写入新CSV文件的结果数据将如下所示: Time,2
Time,29-Aug-2013,30-Aug-2013,1-Sep-2013,2-Sep-2013,3-Sep-2013,4-Sep-2013
01:00,3.68,3.46,3.19,2.88,3.28,3.31,3.64
02:00,3.63,2.97,3.50,3.16,2.92,2.54,3.48
03:00,3.75,3.83,4.01,2.79,3.89,3.59,2.86
...
my @rows = ();
my @transposed = ();
open F1,"D:\\Temp\\perf_data.csv";
while(<F1>) {
chomp;
push @rows, split [ /,/ ];
}
#print @rows;
for my $row (@rows) {
for my $column (0 .. $#{$row}) {
push(@{$transposed[$column]}, $row->[$column]);
}
}
for my $new_row (@transposed) {
for my $new_col (@{$new_row}) {
print $new_col, ",";
}
print "\n";
}
现在,我的脚本如下所示:
Time,29-Aug-2013,30-Aug-2013,1-Sep-2013,2-Sep-2013,3-Sep-2013,4-Sep-2013
01:00,3.68,3.46,3.19,2.88,3.28,3.31,3.64
02:00,3.63,2.97,3.50,3.16,2.92,2.54,3.48
03:00,3.75,3.83,4.01,2.79,3.89,3.59,2.86
...
my @rows = ();
my @transposed = ();
open F1,"D:\\Temp\\perf_data.csv";
while(<F1>) {
chomp;
push @rows, split [ /,/ ];
}
#print @rows;
for my $row (@rows) {
for my $column (0 .. $#{$row}) {
push(@{$transposed[$column]}, $row->[$column]);
}
}
for my $new_row (@transposed) {
for my $new_col (@{$new_row}) {
print $new_col, ",";
}
print "\n";
}
my@rows=();
我的@transposed=();
打开F1,“D:\\Temp\\perf_data.csv”;
while(){
咀嚼;
按@行,拆分[/,/];
}
#打印@行;
对于我的$row(@rows){
对于我的$列(0..$#{$row}){
push(@{$transposed[$column]},$row->[$column]);
}
}
对于我的$new_行(@transposed){
对于我的$new_col(@{$new_row}){
打印$new_col,“,”;
}
打印“\n”;
}
我甚至不能从中得到一个结果!有人能给我一些提示我怎么做吗?提前谢谢 你犯了一个简单但严重的错误
split [ /,/ ]
应该是
[ split /,/ ]
split
的语法为
split /PATTERN/, EXPR, LIMIT
其中后两个是可选的。您正在做的是将一个匿名数组ref作为模式
传递,它很可能被字符串化为类似数组(0x54d658)
的内容。结果是该行不会被分割,而整个行会被推到阵列上。稍后,这将导致取消对$row
的引用失败并出现错误
Can't use string ("29-Aug-2013,3.68,3.63,3.75,3.65,"...) as an ARRAY ref while "
strict refs" in use at foo.pl line 18, <F1> line 7.
不能将字符串(“29-Aug-2013,3.68,3.63,3.75,3.65,”…)用作数组引用,而
foo.pl第18行第7行中使用的“严格参考”。
这是我的Perl程序,用于将行数据转换为列。
行以标题名称开头,后跟一个或多个值。
在我的例子中,我需要从标题中删除日期(mm/dd/yyyy),以便标题字段的其余部分在多行中是唯一的
sub usage { << "EOF";
Convert rows to columns.
Remove dates from column headings.
Usage:
perl $0
Example:
$0 data-to-transpose.txt
Source data:
header1, row1Value1, row2Value2
header2, row2Value1
header3 11/31/2011, row3Value1, row3Value2
Output:
header1, header2, header3
row1Value1, row2Value1, row3Value1
row1Value2, , row3Value2
EOF
}
#
#-------------------------------------------------------------------------------
use 5.010;
use strict;
use warnings;
# use Data::Dumper;
sub printColumns;
my $inFile = shift or die usage();
# @ARGV = ('.') unless @ARGV;
my @headers; # Order list of column headers
my %data; # map{colHeader, arrayColSourceData }
my $colCnt = 0; # maximum number of columns in source data, header, value1, value2, ....
my $printColHeaders = 1;
my %hasharray; open (my $fh, "<", $inFile) or die "can't open the $inFile";
while (<$fh>) {
chomp;
my @parts = split /,/;
if (@parts > 1) {
# Remove date from heading field
(my $header = $parts[0]) =~ s/[0-9]+\/[0-9]+\/[0-9]+//;
if (!exists $data{$header}) {
push @headers, $header;
}
my $have = $data{$header};
if (defined $data{$header}) {
if ($printColHeaders == 1) {
$printColHeaders = 0;
foreach my $col (@headers) {
print "$col,";
}
print "\n";
}
printColumns();
foreach my $col (@headers) {
$data{$col} = undef;
}
}
$data{$header} = \@parts;
$colCnt = (@parts > $colCnt) ? @parts : $colCnt;
}
}
printColumns();
print "\n";
foreach my $col (@headers) {
print "$col,";
}
print "\n";
#### Subs
sub printColumns() {
for my $row (1 .. $colCnt-1) {
foreach my $colHeader (@headers) {
my $colData = $data{$colHeader};
if (defined $colData) {
my $len=@$colData;
if (defined $colData && $row < @$colData) {
print "$colData->[$row], ";
} else {
print ", ";
}
} else {
print ", ";
}
}
print "\n";
}
}
子用法{1){
#从标题字段中删除日期
(我的$header=$parts[0])=~s/[0-9]+\/[0-9]+\/[0-9]+/;
如果(!exists$data{$header}){
推送@headers,$header;
}
my$have=$data{$header};
if(定义的$data{$header}){
如果($printColHeaders==1){
$printColHeaders=0;
foreach my$col(@headers){
打印“$col”;
}
打印“\n”;
}
printColumns();
foreach my$col(@headers){
$data{$col}=undef;
}
}
$data{$header}=\@部分;
$colCnt=(@parts>$colCnt)?@parts:$colCnt;
}
}
printColumns();
打印“\n”;
foreach my$col(@headers){
打印“$col”;
}
打印“\n”;
####潜艇
子列(){
对于我的$row(1..$colCnt-1){
foreach my$colheaders(@headers){
my$colData=$data{$colHeader};
if(定义为$colData){
my$len=@$colData;
if(定义为$colData&&$row<@$colData){
打印“$colData->[$row],”;
}否则{
打印“,”;
}
}否则{
打印“,”;
}
}
打印“\n”;
}
}
看起来您主要是从中复制代码的。但是你犯了一个严重的错误split[/,/]
应该是[split/,/]
.TLP-是的,这就是我在帖子中感谢海报的原因。我相信我在这里要做的是逐行提取我的CSV文件,并将其用作数组的数组。但是,我似乎无法将其放入新数组@rows中。我会试试你的建议,然后告诉你。谢谢TLP-就是这样!它正在工作!非常感谢你的帮助!不客气。我会添加一个答案,这样你就不会在你的历史中遇到一个没有答案的问题。顺便说一句:一些基本规则1)始终使用use strict;使用警告代码>启动您的脚本2)一旦字段中出现任何不寻常的内容,使用或系列来读取和写入CSV;3) 将输入文件作为脚本的参数,而不是将其硬编码到文件中,这使脚本更易于使用和测试