
下記のようなcsv形式のファイルがあります。
--元データ--
,,,,,,,07月01日,,,,07月02日
ID,発拠点名,ID,着拠点名,試験ファイル,測定項目,基礎化値,0-5時,6-11時,12-17時,18-23時,0-5時,6-11時,12-17時,18-23時
001,大阪,002,兵庫,test01,遅延,最大,11,11,13,13,13,12,12,12
001,大阪,002,兵庫,test01,遅延,最小,8,9,9,9,9,10,10,10
001,大阪,002,兵庫,test01,遅延,平均,10,10,10,10,10,11,11,11
------------
これを
--変換後イメージ--
発拠点名,着拠点名,日,時,遅延最大,遅延最小,遅延平均
大阪,兵庫,07月01日,0-5時,11,8,10
大阪,兵庫,07月01日,6-11時,11,9,10
大阪,兵庫,07月01日,6-11時,13,9,10
大阪,兵庫,07月01日,6-11時,13,9,10
-----
といった形式にperlで変換するスクリプトを作りたいのですが初心者でどのように書けばよいのかわからず困っています。どなたかご教授願えないでしょうか?
よろしくお願い致します。
No.1ベストアンサー
- 回答日時:
質問で提示されているデータだけでは規則がどういうものが判断できない部分があります。
もう少し明確に規則を書いてもらえれば二度手間を避けることもできると思います。
たとえば変換前のデータでは、
001,大阪,002,兵庫,test01,遅延,最大,11,11,13,13,13,12,12,12
001,大阪,002,兵庫,test01,遅延,最小,8,9,9,9,9,10,10,10
001,大阪,002,兵庫,test01,遅延,平均,10,10,10,10,10,11,11,11
の三行しかデータがないのに、変換後になると
大阪,兵庫,07月01日,0-5時,11,8,10
大阪,兵庫,07月01日,6-11時,11,9,10
大阪,兵庫,07月01日,6-11時,13,9,10
大阪,兵庫,07月01日,6-11時,13,9,10
四行に増えているのでしょう?
,,,,,,,07月01日,,,,07月02日
どのような理由で、7/1と7/2がそれぞれこの位置に置かれているのか不明です。
サンプルデータには7/2で出力するものがありませんし。
多分二行目(ヘッダ?)の
0-5時,6-11時,12-17時,18-23時,0-5時,6-11時,12-17時,18-23時
の部分に入っている数字が何かの基準になるのでしょうが
まったくもって不明です。
変換後のヘッダにある
> 遅延最大,遅延最小,遅延平均
もどのように求める数値なのか規則がわかりません。
適当に判断して書いたところで「実は…」というパターンは避けたいので、
出せるものは出してください。
とはいうものの出されたら必ず書きますとはお約束できません。
努力はしますが。
> 教授
こういうときに使うのは「教示」ですよん。
この回答への補足
すみません。補足(タイプミスもありましたので修正)いたします。
>,,,,,,,07月01日,,,,07月02日
>どのような理由で、7/1と7/2がそれぞれこの位置に置かれているのか不明です。
>サンプルデータには7/2で出力するものがありませんし。
元データの1行目に月日があって、2行目にその他のデータ項目があるのはこれを出力するツールの仕様で2行目は大阪ー兵庫の遅延の最大の(07月01日)の0-5時の値、,6-11時の値、,12-17時の値,18-23時の値,(07月02日)の0-5時の値、,6-11時の値,12-17時の値,18-23時の値という表現となっています。次の行では、遅延の最小値として期間での値、その次の行では、遅延の平均値として期間の値が入ってきています。
これを変換後は
大阪,兵庫,07月01日,0-5時,11,8,10
大阪,兵庫,07月01日,6-11時,11,9,10
大阪,兵庫,07月01日,12-17時,13,9,10
大阪,兵庫,07月01日,18-23時,13,9,10
大阪,兵庫,07月02日,0-5時,13,9,10
大阪,兵庫,07月02日,6-11時,13,10,10
大阪,兵庫,07月02日,12-17時,12,10,11
大阪,兵庫,07月02日,12-17時,12,10,11
というように、発/着拠点名と月日時間ごとの各種測定値(遅延最大、遅延最小、遅延平均)という表現に並び替えてたいと考えています。
>> 教授
>こういうときに使うのは「教示」ですよん。
失礼いたしました。ご教示おねがいできないでしょうか。
よろしくお願いいたします。
No.3
- 回答日時:
あ、先越されてるしw
せっかく書いたのでぺたり。
一行目に入る日付は二日分しか想定してないとかありますんで、
#2の方の回答のほうがいいでしょう。
少しでもわかりやすくしようと思って効率的に悪いところがあります。
そんなにでかいデータでもなければ無視できるほどでしょうけど。
use strict;
my %data;
my $date1;
my $date2;
my $line;
$line = <DATA>;
chomp $line;
(undef, $date1, $date2) = split /,+/, $line;
$line = <DATA>;
while ($line = <DATA>) {
#my @fields = split /,/, $line;
chomp $line;
my ($id1, $from, $id2, $to, $file, $mesure, $base, @rest) =
split /,/, $line;
$data{$date1}{from} = $from;
$data{$date1}{to} = $to;
$data{$date2}{from} = $from;
$data{$date2}{to} = $to;
$data{$date1}{$base} = [@rest[0..3]];
$data{$date2}{$base} = [@rest[4..7]];
}
print join(q{,},
qw(発拠点名 着拠点名 日 時 遅延最大 遅延最小 遅延平均)), "\n";
foreach my $day ($date1, $date2) {
my @time_table = ('0-5', '6-11', '12-17', '18-23');
for (my $idx; $idx < scalar @time_table; $idx++) {
my $tzone = $time_table[$idx];
my @out;
push @out,
$data{$day}{from},
$data{$day}{to},
$day,
($tzone . '時'),
$data{$day}{'最大'}[$idx],
$data{$day}{'最小'}[$idx],
$data{$day}{'平均'}[$idx];
print join(q{,}, @out), "\n";
}
}
__END__
,,,,,,,07月01日,,,,07月02日
ID,発拠点名,ID,着拠点名,試験ファイル,測定項目,基礎化値,0-5時,6-11時,12-17時,18-23時,0-5時,6-11時,12-17時,18-23時
001,大阪,002,兵庫,test01,遅延,最大,11,11,13,13,13,12,12,12
001,大阪,002,兵庫,test01,遅延,最小,8,9,9,9,9,10,10,10
001,大阪,002,兵庫,test01,遅延,平均,10,10,10,10,10,11,11,11
sakusaker7さん
ありがとうございます!
最初の質問内容がわかりにくくてすみませんでした。
うまく質問できなかったということは、ゴールまでの手順がちゃんとイメージできてなかったんだと思います。
わかりやすいコードなので、参考にしながら勉強します。
No.2
- 回答日時:
こんにちは、
#1氏への補足でなんとなく分かったような気がしたので、
試しにやってみました。
で、こんな感じですか?
1行目と2行目は必ず所定のデータが入っているつもりです。
全部ハッシュに貯めているので、ファイルが大きくなるとまずい事になるかも知れませんが…。
とりあえず、実行してみてうまくいったなら、
DATAを読んでるトコを標準入力からにして(つまり<>)
windows ならコマンドプロンプトから、
type 元のファイル名 | perl スクリプト名 > 新しいファイル名
でやってみて下さい。
うまく行かなかったらごめんなさい。
#!perl
use strict;
use warnings;
my %LINES_OF = ();
my @TIME_RANGE = qw( 0-5時 6-11時 12-17時 18-23時 );
#1行目は必ず日付の行?
chomp ( my $line = <DATA>);
my @DATE = grep {$_} split /,/ , $line;
#2行目無視
$line = <DATA>;
while (<DATA>) {
chomp;
my( @headers , @datas);
#見出しとデータに分割
(@headers[ 0..6 ],@datas) = split /,/;
my $header = join ',' , @headers[ 1 , 3 ];
#ハッシュに展開
for my $date (@DATE) {
for my $range (@TIME_RANGE) {
$LINES_OF{ $date }->{ $header }->{ $range }->{ $headers[6] } = shift @datas;
}
}
}
#ハッシュぐるぐるで表示
print "発拠点名,着拠点名,日,時,遅延最大,遅延最小,遅延平均\n";
for my $date ( @DATE ) {
for my $header ( sort keys %{ $LINES_OF{$date} } ) {
for my $range ( @TIME_RANGE ) {
my $line = join ',' , $header , $date , $range;
for ( '最大' , '最小' , '平均' ) {
$line .= ',' . $LINES_OF{ $date }->{ $header }->{ $range }->{ $_ };
}
print $line , "\n";
}
}
}
__DATA__
,,,,,,,07月01日,,,,07月02日
ID,発拠点名,ID,着拠点名,試験ファイル,測定項目,基礎化値,0-5時,6-11時,12-17時,18-23時,0-5時,6-11時,12-17時,18-23時
001,大阪,002,兵庫,test01,遅延,最大,11,11,13,13,13,12,12,12
001,大阪,002,兵庫,test01,遅延,最小,8,9,9,9,9,10,10,10
001,大阪,002,兵庫,test01,遅延,平均,10,10,10,10,10,11,11,11
ありがとうございます!
やりたかったことはこういうことでした。
元のファイル名を読み込みようにして実行してもうまくいきました。
perlのスクリプトはほぼ初めてなので、参考に勉強させていただきます。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
MATLAB std::exceptionエラー
-
Perlで特定行から特定行までを...
-
perlでcsvファイルを読む(ダブ...
-
ExcelをCSV書き出す場合のシー...
-
VBAでCSVファイルを途中行まで...
-
エクセルVBA コードが同じでも...
-
MATLAB グローバル変数の宣言
-
vba dir の相対パス
-
MATLABのm-fileについて
-
readdir()で得られるファイル・...
-
フォルダが開かなくなりました。
-
batファイルでrenameができませ...
-
window.open でのファイル指定方法
-
CSVが可変長の場合の検索方法
-
全角と半角文字が混在している...
-
read() on unopened filehandle...
-
重複するデータを抽出できる秀...
-
dos変数の%~dp0は powershellで...
-
バッチファイルで、記号を含む...
-
ファイル名と更新日付の取得に...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
Perlで特定行から特定行までを...
-
perlでcsvファイルを読む(ダブ...
-
FTP接続時失敗時、接続先名をcs...
-
Perlの初心者です。2重ループ...
-
MATLAB std::exceptionエラー
-
BBCode削除&改行をサニタイジ...
-
CSVファイルのデータの行数を取...
-
パイソンでCSVファイル場所を指...
-
perl:パターンマッチを使ったif...
-
perlでファイルの比較
-
書き込み時に勝手にクリアさせ...
-
Argument "\\\\n" isn't numeri...
-
先頭の単語が一致した時のデー...
-
郵便番号辞書のアップデート手...
-
Perlでの重複要素カウントにつ...
-
pealを用いたcsvファイルの抽出
-
ExcelをCSV書き出す場合のシー...
-
エクセルVBA コードが同じでも...
-
awkスクリプトでダブルクォーテ...
-
batファイルでrenameができませ...
おすすめ情報