質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
CSV

CSV(Comma-Separated Values)はコンマで区切られた明白なテキスト値のリストです。もしくは、そのフォーマットでひとつ以上のリストを含むファイルを指します。

Perl

Perlは多目的に使用される実用性が高い動的プログラミング言語のひとつです。

Q&A

解決済

3回答

875閲覧

CSVファイルから分割属性と対応する属性値, ゴルフプレイ(○,☓)の頻度を求めるプログラムを作成したい

wagashi_157

総合スコア51

CSV

CSV(Comma-Separated Values)はコンマで区切られた明白なテキスト値のリストです。もしくは、そのフォーマットでひとつ以上のリストを含むファイルを指します。

Perl

Perlは多目的に使用される実用性が高い動的プログラミング言語のひとつです。

0グッド

0クリップ

投稿2022/05/07 05:58

編集2022/05/07 15:21

前提・実現したいこと

以下のtest.csvを読み込み, 分割属性(天気など), と対応する属性値(晴など), ゴルフプレイ(○, ×)の頻度を求めるプログラムを作成したいです。

test.csv

1天気 温度 湿度 風 ゴルフプレイ 2晴 暑 高 無 × 3晴 暑 高 有 × 4曇 暑 高 無 ○ 5雨 暖 高 無 ○ 6雨 涼 普通 無 ○ 7雨 涼 普通 有 × 8曇 涼 普通 有 ○ 9晴 暖 高 無 × 10晴 涼 普通 無 ○ 11雨 暖 普通 無 ○ 12晴 暖 普通 有 ○ 13曇 暖 高 有 ○ 14曇 暑 普通 無 ○ 15雨 暖 高 有 ×

ちなみに, 最終的には以下のように出力されるのが目標です。

天気 -> 雨 -> ○ = 3 天気 -> 雨 -> × = 2 天気 -> 晴 -> × = 3 天気 -> 晴 -> ○ = 2 天気 -> 曇 -> ○ = 4 風 -> 無 -> × = 2 風 -> 無 -> ○ = 6 風 -> 有 -> × = 3 風 -> 有 -> ○ = 3 湿度 -> 高 -> ○ = 3 湿度 -> 高 -> × = 4 湿度 -> 普通 -> ○ = 6 湿度 -> 普通 -> × = 1 ...

発生している問題・エラーメッセージ

csvファイルの読み込みと頻度表示はできたのですが, 出力結果がアドレス表示になってしまっています。その原因がよく分からないので教えてほしいです。

該当のソースコード

Perl

1#!/usr/bin/perl 2use strict; 3use Encode; 4use utf8; 5 6main(); 7 8sub main { 9 my %TrainData=mkDataHash("test.csv"); 10 11 foreach my $tag (keys %TrainData) 12 { 13 foreach my $data (keys %{$TrainData{$tag}}) 14 { 15 foreach my $det (keys %{$TrainData{$tag}{$data}}) 16 { 17 my $f = $TrainData{$tag}->{$data}->{$det}; 18 print("$TrainData{$tag}->$TrainData{$data}->$TrainData{$det}-->$f\n"); 19 } 20 } 21 } 22} 23 24sub mkDataHash { 25 my($csv_name)=shift(@_); 26 open(my $IN,$csv_name); 27 my $data_utf8=<IN>; 28 my @Tag=split(/\t/,decode_utf8($data_utf8)); 29 my %TrainData; 30 chomp($data_utf8); 31 while(my $data_utf8=<$IN>) { 32 chomp($data_utf8); 33 my @Data=split(/\t/,decode_utf8($data_utf8)); 34 my $det=pop(@Data); 35 my $i; 36 for($i=0; $i<=$#Data; $i++) 37 { 38 my $tag = $Tag[$i]; 39 my $data = $Data[$i]; 40 $TrainData{$tag}->{$data}->{$det}++; 41 } 42 } 43 close($IN); 44 return %TrainData; 45}

試したこと

配列でなければpop関数が使えないことに気づいたので新たに@list関数を追加しました。また, それに伴ってタブで区切られているところをsplit関数で表現してみました。ファイルの読み込みが以前実行したときにはできていなかったので, やり方を調べて修正しました。ファイルの読み込みと同じ要領でfor文を利用してtagとdataを処理してみました。

補足情報

Ubuntu-20.04を利用しています。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tatsu99

2022/05/07 08:11

提示されたtest.csvを読み込んだ場合、 期待する出力結果は、どのようになりますか?
wagashi_157

2022/05/07 13:54

天気 -> 雨 -> ○ = 3 天気 -> 雨 -> × = 2 天気 -> 晴 -> × = 3 天気 -> 晴 -> ○ = 2 ・・・ というように分割属性→対応する属性値→○×→出現頻度の順で出力されるプログラムを作成したいです。
guest

回答3

0

ベストアンサー

分割属性(天気など), と対応する属性値(晴など), ゴルフプレイ(○, ×)をキーにしたハッシュを作成しています。
ハッシュの値をハッシュにするようにはしていません。

perl

1#!/usr/bin/perl 2use strict; 3use Encode; 4use utf8; 5 6main(); 7 8sub main { 9 my %TrainData = mkDataHash("test.csv"); 10 foreach my $key (sort(keys %TrainData)) 11 { 12 my ($tag,$data,$det) = split(/\|/,$key); 13 print $tag,' -> ',$data,' -> ',$det,' = ',$TrainData{$key},"\n"; 14 } 15} 16 17sub mkDataHash { 18 my $csv_name = shift(@_); 19 open(IN,$csv_name); 20 my $data_utf8 = <IN>; 21 chomp($data_utf8); 22 my @Tag = split(/\t/,$data_utf8); 23 my %TrainData = (); 24 while(my $data_utf8 = <IN>) { 25 chomp($data_utf8); 26 my @Data = split(/\t/,$data_utf8); 27 my $i; 28 for($i=0; $i < $#Data; $i++) 29 { 30 my $tag = $Tag[$i]; 31 my $data = $Data[$i]; 32 my $det = $Data[$#Tag]; 33 my $key = $tag . '|' . $data . '|' . $det; 34 $TrainData{$key}++; 35 } 36 } 37 close(IN); 38 return %TrainData; 39} 40

実行結果
天気 -> 晴 -> × = 3
天気 -> 晴 -> ○ = 2
天気 -> 曇 -> ○ = 4
天気 -> 雨 -> × = 2
天気 -> 雨 -> ○ = 3
温度 -> 暑 -> × = 2
温度 -> 暑 -> ○ = 2
温度 -> 暖 -> × = 2
温度 -> 暖 -> ○ = 4
温度 -> 涼 -> × = 1
温度 -> 涼 -> ○ = 3
湿度 -> 普通 -> × = 1
湿度 -> 普通 -> ○ = 6
湿度 -> 高 -> × = 4
湿度 -> 高 -> ○ = 3
風 -> 有 -> × = 3
風 -> 有 -> ○ = 3
風 -> 無 -> × = 2
風 -> 無 -> ○ = 6

投稿2022/05/08 13:20

編集2022/05/08 13:22
tatsu99

総合スコア5493

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

Perl ではなく、GNU awk を利用する場合。

bash

1$ gawk --version 2GNU Awk 5.1.0, API: 3.0 (GNU MPFR 4.1.0, GNU MP 6.2.1) 3 4$ gawk ' 5 NR==1{split($0, cols); next} 6 {for(i=1;i<length(cols);i++) tbl[cols[i] " -> " $i " -> " $5]++} 7 END{ 8 PROCINFO["sorted_in"] = "@ind_str_asc" 9 for(i in tbl) print i " = " tbl[i] 10 } 11' test.tsv 12 13天気 -> 晴 -> × = 3 14天気 -> 晴 ->= 2 15天気 -> 曇 ->= 4 16天気 -> 雨 -> × = 2 17天気 -> 雨 ->= 3 18温度 -> 暑 -> × = 2 19温度 -> 暑 ->= 2 20温度 -> 暖 -> × = 2 21温度 -> 暖 ->= 4 22温度 -> 涼 -> × = 1 23温度 -> 涼 ->= 3 24湿度 -> 普通 -> × = 1 25湿度 -> 普通 ->= 6 26湿度 -> 高 -> × = 4 27湿度 -> 高 ->= 3 28風 -> 有 -> × = 3 29風 -> 有 ->= 3 30風 -> 無 -> × = 2 31風 -> 無 ->= 6

投稿2022/05/07 09:41

編集2022/05/08 04:00
melian

総合スコア20655

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ファイルをオープンだけして読み込みをしてないですね。当然ながら読み込んでないデータは表示されません。

投稿2022/05/07 06:32

KojiDoi

総合スコア13692

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問