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

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

ただいまの
回答率

88.92%

[VB] DataTableによる平均値の算出

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 4,024

inukujira

score 106

以下のテキストファイルがあります。

[test.txt]
2015/07/13 00:00:00, 1
2015/07/13 00:00:01, 2
2015/07/13 00:00:02, 3
2015/07/13 00:01:00, 1
2015/07/13 00:01:01, 2
2015/07/13 00:01:02, 3
…(省略:実際には24時間分の1秒毎データがあります。)
これを次のように、DataTableへセットしました。
no,date,value
0,2015/07/13 00:00:00,1
1,2015/07/13 00:00:01,2
2,2015/07/13 00:00:02,3
3,2015/07/13 00:01:00,1
4,2015/07/13 00:01:01,2
5,2015/07/13 00:01:02,3
…(省略)
行いたい事はdata"2015/07/13 00:00"の"value"平均値を算出したいです。
(要は1秒間隔で出力された値を1分間隔毎に平均値を取得したい)

DataTableに入れる事までは出来ました。

Dim MyDB As New DataTable
Dim no As Integer = 0

With MyDB
    .PrimaryKey = New DataColumn() {.Columns.Add("no", Type.GetType("System.Int32"))}
    .Columns.Add("date", Type.GetType("System.DateTime"))
    .Columns.Add("value", Type.GetType("System.Int32"))
End With

With New StreamReader("test.txt", System.Text.Encoding.Default)
    While .Peek() > -1
        Dim value() As String = .ReadLine.Split(","c)
        dtRow = mydb.NewRow()
        dtRow("no") = no
        dtRow("date") = value.ToArray(0)
        dtRow("value") = value.ToArray(1)
        mydb.Rows.Add(dtRow)
        no = no + 1
    End While
End With

ちなみに、以下の処理だとめっちゃくちゃ時間がかかって話になりませんでした、、、
Dim TitleDate As String
TitleDate = MyDB.Select("no=0").ToArray(0).Item("date")

For i = 0 To 1440
    dtRow = ds.Tables(0).NewRow
    dtRow(0) = DateTime.Parse(TitleDate & " 00:00").AddMinutes(i).ToString("yyyy/MM/dd HH:mm")
    dtRow(1) = MyDB.Compute("Avg(value)", "Convert(date, 'System.String') LIKE '" & dtRow(0).ToString & "%'")
    ds.Tables(0).Rows.Add(dtRow)
Next
すばやく1分毎の平均値を取得するにはどのように行えば良いでしょうか?
DataTableよりも高速な方法があれば、そちらも教えて頂きたいです。
よろしくご教示下さい。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

0

クエリ式を使われてはいかがでしょう。
クエリ式の構文例 : 集計演算子(MSDN)

当方VBの知識があまりないのでC#で申し訳ありませんがご参考になれば。

ちなみに、当方環境で集計処理は100ミリ秒程度でした。

static void Main(string[] args)
{

    DataTable table = new DataTable();
    table.Columns.Add("id", typeof(int));
    table.Columns.Add("date", typeof(DateTime));
    table.Columns.Add("dateMin", typeof(string)); // グルーピングのため年月日時分までのフィールドを追加
    table.Columns.Add("value", typeof(int));

    DataColumn[] keyColumns = new DataColumn[1];
    keyColumns[0] = table.Columns["id"];
    table.PrimaryKey = keyColumns;


    // ダミーデータ作成
    Random rand = new Random();
    DateTime dt = DateTime.ParseExact("2015/01/01", "yyyy/MM/dd", null);
    DateTime endDt = DateTime.ParseExact("2015/01/02", "yyyy/MM/dd", null);

    Console.WriteLine("Start: Create Source Table");

    int id = 0;
    while (dt < endDt)
    {
        DataRow row = table.NewRow();
        row[0] = id++;
        row[1] = dt;
        row[2] = dt.ToString("yyyy/MM/dd HH:mm");
        row[3] = rand.Next(0, 9999);

        table.Rows.Add(row);

        dt = dt.AddSeconds(1);
    }

    Console.WriteLine("End  : Create Source Table");


    // 集計結果保存のテーブル
    DataTable avgTable = new DataTable();
    avgTable.Columns.Add("date", typeof(DateTime));
    avgTable.Columns.Add("avg", typeof(double));

    Console.WriteLine("Stert: Calc Average");

    Stopwatch sw = new Stopwatch();
    sw.Start();

    // クエリ式の作成
    var query =
        from row in table.AsEnumerable()
        group row by row.Field<string>(2) into r // 分までのデータでグルーピング
        select new
            {
                key = r.Key,
                avg = r.Average(row => (int)row[3])
            };

    // とりあえず結果をテーブルに保存
    foreach (var avgRow in query)
    {
        DataRow row = avgTable.NewRow();
        row[0] = avgRow.key;
        row[1] = avgRow.avg;

        avgTable.Rows.Add(row);
    }
    sw.Stop();

    Console.WriteLine("End  : Calc Average");
    Console.WriteLine(string.Format("Spend Time : {0} [ms]", sw.ElapsedMilliseconds));


    Console.ReadKey();

}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/07/15 10:34

    この方法でできました!^^
    どうもありがとうございました!

    キャンセル

0

たぶん期待されている答えでは無いと思いますが、思い至ったので、、、

目的が、時系列データからの集計演算なので、読み込みと同時に計算してしまうのはダメでしょうか?

集計用テーブルを用意するか読み込み先テーブルに1列余分を作っておくかして、データファイルから1行ずつ読み込む時、分替わりまでデータ値を積算して積算個数をカウントし、分が替わったタイミングにその分の平均を求めてテーブルに格納するような処理です
毎秒データが86400行確実に入っているなら、カウントの必要もなく割る60すればよいですが

データファイルの読み込み後に、そのデータに対して変更等が発生しないなら、合計や平均のような集計演算は入力と同時に計算してしまうのが効率よいように思います

「データの読み込み時に読み込み以外の処理はできません」というお話ならまったくダメですが・・・


あと、これはご質問と異なる部分のお話なのですが

時系列データの1分平均の考え方について

2015/07/13 00:01 の平均値
といったら
2015/07/13  00:00:01 から 00:01:00 までの平均(積算値を60で割った値)
というのが私の感覚です
(ですので、2015/07/13 00:00 の平均値を求めたい場合には前日データが必要になります)

記述されたコードでは
2015/07/13 00:00:00 から 00:00:59 までのAve平均

2015/07/13 00:00 の平均値
として記録されるような気がします

未来の値で平均を作るのはどうもしっくりきませんが・・・そこは問題ないでしょうか?

(データファイルの先頭が0秒なので、それを前日データとするのか、当日データとするのか・・・)
(最後は23:59で終わるのか、00:00で終わるのか・・・)
(余計なことですが気になったので)

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 88.92%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る