C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

txtファイルから読み出したデータを分類して統計に使う処理

[トピック内 6 記事 (1 - 6 表示)]  << 0 >>

■92779 / inTopicNo.1)  txtファイルから読み出したデータを分類して統計に使う処理
  
□投稿者/ sai (1回)-(2019/10/30(Wed) 01:58:04)

分類:[C#] 

どのような処理を書けばいいのか思いつかないので質問させて頂きます。

「年/月/日/労働時間(分)/利益」のデータを、セミコロンを挟んで記載してあるdata.txt
があります。
テキストファイルの中身は、

2019,9,15,125,120.5
2019,9,21,99,87.0
2020,2,11,145,55.2
2020,6,24,324,22.4
2020,8,7,320,19.3

という感じです。
例えば、一番上は「2019年9月15日に125分労働して$120.5の利益」という意味です。

このデータを「一年の合計利益」、「一ヶ月(例えば2019年9月)の平均利益」、「一ヶ月の平均時給」
の3つに分けたいのですが、どういう処理を書けばいいのか、思いつきません。

正規表現を使って年/月/日…と要素ごとに抜き出してyearData, monthData, dayData…とか別々のフィールドに分けて入れたり、
ループを回してなんとか同データ同士をまとめたりできないかとやってみたりしましたが、上手い処理を考えつきませんでした。

あるいは、txtファイル内のデータの持ち方を変えた方がいいのか…。
何でも構いませんので、解決案、アドバイスなど頂きたいです。

よろしくお願い致します。


引用返信 編集キー/
■92780 / inTopicNo.2)  Re[1]: txtファイルから読み出したデータを分類して統計に使う処理
□投稿者/ WebSurfer (1958回)-(2019/10/30(Wed) 05:16:42)
No92779 (sai さん) に返信

思い付きですが・・・

List<T> 型のオブジェクトを作って、Linq to Objects で集計する
方向で考えてみてはいかがでしょう。
引用返信 編集キー/
■92783 / inTopicNo.3)  Re[2]: txtファイルから読み出したデータを分類して統計に使う処理
□投稿者/ とっちゃん (641回)-(2019/10/30(Wed) 11:19:36)
No92779 (sai さん) に返信
> 「年/月/日/労働時間(分)/利益」のデータを、セミコロンを挟んで記載してあるdata.txt
> があります。

セミコロンは「;」です。「,」はカンマですね。

> テキストファイルの中身は、
>
> 2019,9,15,125,120.5
> 2019,9,21,99,87.0
<<省略>>
>
一般的に「CSV 形式」と呼ばれるテキストファイルですね。

> 正規表現を使って年/月/日…と要素ごとに抜き出してyearData, monthData, dayData…とか別々のフィールドに分けて入れたり、
> ループを回してなんとか同データ同士をまとめたりできないかとやってみたりしましたが、上手い処理を考えつきませんでした。
>
いろいろなやり方があると思いますが、データ数(行数)があまり多くないのであれば、オンメモリで処理する形でいいと思います。

もし、データ数が多く、メモリ的に厳しいという場合は、テキストファイルを一度自分にとって使いやすいデータベースエンジンなどに
格納して利用するのがいいと思います。
もしくは、64bitOSで64bit版を作って、出来るだけ多くのメモリを使えるようなところでやるか。。。ですかね。


ということで以下はオンメモリでの操作を前提とした場合で書いておきます。

データの内容は、「年月日」「労働時間」「利益」 の3つに分けられると思います。
それぞれをクラスのプロパティとして用意してやれば、そのあとの処理がだいぶ楽になると思います。
まずは、この行データを扱いやすく集合体としてのクラスを作成するのがいいと思います。

その上で、このクラスを一連のデータ集合体として扱えるように List<1行分データ> という形で用意してやれば操作しやすいかな?と思います。


> このデータを「一年の合計利益」、「一ヶ月(例えば2019年9月)の平均利益」、「一ヶ月の平均時給」
> の3つに分けたいのですが、どういう処理を書けばいいのか、思いつきません。
>
これらについては、先のデータを使ってその場で計算してしまうのがいいと思います。

例えば、「一年の合計利益」という処理をしたいのであれば、

利益をあらわすデータ型(既定の型を使えばいい) 一年の合計利益( int 計算対象年 );

というメソッドを作り、その中で計算する処理を行えば、良いでしょう。
他も同様です。

具体的にどんなコードにすればいいかは、まずは自分で考えてみてください。

その上で、具体的に質問すれば、具体的な回答が得られると思いますよ。

引用返信 編集キー/
■92824 / inTopicNo.4)  Re[2]: txtファイルから読み出したデータを分類して統計に使う処理
□投稿者/ sai (2回)-(2019/11/01(Fri) 00:06:29)
No92780 (WebSurfer さん) に返信
> ■No92779 (sai さん) に返信
>
> 思い付きですが・・・
>
> List<T> 型のオブジェクトを作って、Linq to Objects で集計する
> 方向で考えてみてはいかがでしょう。

アドバイスありがとうございます。
それを聞いて、あ、なるほど、となるほどC#に詳しくないので、
まずはList<T> 型とLinq to Objectsについて情報を集めようと思います。

もしかしたら、また分からなくなった時に質問させて頂くかもしれませんが。
ありがとうございました。
引用返信 編集キー/
■92825 / inTopicNo.5)  Re[3]: txtファイルから読み出したデータを分類して統計に使う処理
□投稿者/ sai (3回)-(2019/11/01(Fri) 00:10:31)
アドバイスありがとうございます。

> セミコロンは「;」です。「,」はカンマですね。
>
すみません、その通りでした…。


> データの内容は、「年月日」「労働時間」「利益」 の3つに分けられると思います。
> それぞれをクラスのプロパティとして用意してやれば、そのあとの処理がだいぶ楽になると思います。
> まずは、この行データを扱いやすく集合体としてのクラスを作成するのがいいと思います。
>
> その上で、このクラスを一連のデータ集合体として扱えるように List<1行分データ> という形で用意してやれば操作しやすいかな?と思います。
>
>
>>このデータを「一年の合計利益」、「一ヶ月(例えば2019年9月)の平均利益」、「一ヶ月の平均時給」
>>の3つに分けたいのですが、どういう処理を書けばいいのか、思いつきません。
>>
> これらについては、先のデータを使ってその場で計算してしまうのがいいと思います。
>
> 例えば、「一年の合計利益」という処理をしたいのであれば、
>
> 利益をあらわすデータ型(既定の型を使えばいい) 一年の合計利益( int 計算対象年 );
>
> というメソッドを作り、その中で計算する処理を行えば、良いでしょう。
> 他も同様です。
>
> 具体的にどんなコードにすればいいかは、まずは自分で考えてみてください。
>
> その上で、具体的に質問すれば、具体的な回答が得られると思いますよ。
>

正直、現状では知識的に全く想像できていませんが、まずはこれらについて調べてみます。

分からなくなったら、また質問させて頂くかもしれませんが…。


ありがとうございました。
引用返信 編集キー/
■92830 / inTopicNo.6)  Re[1]: txtファイルから読み出したデータを分類して統計に使う処理
□投稿者/ 魔界の仮面弁士 (2450回)-(2019/11/01(Fri) 10:29:32)
No92779 (sai さん) に返信
> 「一年の合計利益」
暦年で見て1月1日から12月31日までを一年とするのか、
会計年度で4月1日から3月31日までを一年とするのかについては
とりあえず暦年で考えるとして…。


> 「一ヶ月(例えば2019年9月)の平均利益」
月の勤務日数(2019年9月なら2日間)で割った値なのか、
月の暦日日数(2019年9月なら30日間)で割った値なのについては
とりあえず勤務日数で考えるとして…。


>「一ヶ月の平均時給」
上記 3 パターンを LINQ で求めてみました。


string[] rawData = System.IO.File.ReadAllLines(@"C:\Temp\data.txt");

var entries = rawData.Select(line => line.Split(',')).Select(cols => new
{
    Date = new DateTime(int.Parse(cols[0]), int.Parse(cols[1]), int.Parse(cols[2])),
    WorkTime = TimeSpan.FromMinutes(double.Parse(cols[3])),
    Payment = decimal.Parse(cols[4]),
}).ToArray();

// 一年の合計利益
var q1 = entries.GroupBy(r => r.Date.Year, (Span, r) => new { Span, Money = r.Sum(x => x.Payment) });

// 一ヶ月の平均利益
var q2 = entries.GroupBy(r => r.Date.ToString("yyyy/MM"), (Span, r) => new { Span, Money = (double)r.Average(x => x.Payment) / r.Count() });

// 一ヶ月の平均時給
var q3 = entries.GroupBy(r => r.Date.ToString("yyyy/MM"), (Span, r) => new { Span, Money = (double)r.Sum(x => x.Payment) / r.Sum(x => x.WorkTime.TotalHours) });


listBox1.BeginUpdate();
listBox1.Items.Clear();
listBox1.Items.Add("=== 年間合計 ===");
foreach (var record in q1)
{
    listBox1.Items.Add(record.Span + "年は" + record.Money.ToString("$0.00"));
}
listBox1.Items.Add("=== 月別平均利益 ===");
foreach (var record in q2)
{
    listBox1.Items.Add(record.Span + "は" + record.Money.ToString("$0.00"));
}
listBox1.Items.Add("=== 月別平均時給 ===");
foreach (var record in q3)
{
    listBox1.Items.Add(record.Span + "は" + record.Money.ToString("$0.0000"));
}
listBox1.EndUpdate();

引用返信 編集キー/

このトピックをツリーで一括表示


トピック内ページ移動 / << 0 >>

このトピックに書きこむ