[リストへもどる]
一括表示

投稿時間:2002/11/05(Tue) 11:29
投稿者名:アンパンマン
Eメール:
URL :
タイトル:
平均値を求める
お世話になります。

5000日分のデータがあり、過去5日分の平均値を
取りたいのですが、一つのコードだと何も問題はありませんが、
コードが5000個あります。

かなり時間がかかってしまいます。これは何とか出来ないでしょうか?

今、やっているのは、データ(CSV)を
一行づつ読み込んで、最後の5日間の平均を取得する
といった感じです。

投稿時間:2002/11/05(Tue) 11:46
投稿者名:A221
Eメール:
URL :
タイトル:
Re: 平均値を求める
> お世話になります。
>
> 5000日分のデータがあり、過去5日分の平均値を
> 取りたいのですが、一つのコードだと何も問題はありませんが、
> コードが5000個あります。

5000日分のデータは未ソートですか?
5000日分×5000個のデータということですか?

> かなり時間がかかってしまいます。これは何とか出来ないでしょうか?
>
> 今、やっているのは、データ(CSV)を
> 一行づつ読み込んで、最後の5日間の平均を取得する
> といった感じです。

月並みですが、InputBで全部まとめて読み込んで配列に格納して
ソートをかけて必要なものだけ足し算して平均を出す・・とか。

投稿時間:2002/11/05(Tue) 14:29
投稿者名:Say
Eメール:
URL :
タイトル:
Re^2: 平均値を求める
データ量から考えてDBで処理したほうがいいのでは?

投稿時間:2002/11/06(Wed) 13:23
投稿者名:アンパンマン
Eメール:
URL :
タイトル:
Re^2: 平均値を求める

> 5000日分のデータは未ソートですか?
> 5000日分×5000個のデータということですか?

> 月並みですが、InputBで全部まとめて読み込んで配列に格納して
> ソートをかけて必要なものだけ足し算して平均を出す・・とか。

皆さんお返事ありがとうございます。
配列に読み込んでソートをかけるというのは、どの様にすればいいでしょうか?

投稿時間:2002/11/06(Wed) 14:48
投稿者名:A221
Eメール:
URL :
タイトル:
Re^3: 平均値を求める
> 皆さんお返事ありがとうございます。
> 配列に読み込んでソートをかけるというのは、どの様にすればいいでしょうか?

手元にあったCSV読み込み用のソースを適当に追加したものですが
動作するようです。サンプルにどうぞ。
(但しSplit使用のためVB6.0)
-----------------------------------------------------
Option Explicit
Private Const fname = "c:\test.csv"
Private Type RowMatrix
    rowDate As Date
    'ここを任意に変える
    data(1 To 8) As String
End Type
Private Alldata() As RowMatrix

Private Sub Form_Load()
Dim fnum As Long
Dim flen As Long
Dim tmpstr As String
Dim Linedata As Variant
Dim Coldata As Variant
Dim i As Long
Dim j As Long

fnum = FreeFile
Open fname For Input As #fnum
flen = LOF(fnum) - 2
tmpstr = InputB$(flen, #fnum)
tmpstr = StrConv(tmpstr, vbUnicode)

Linedata = Split(tmpstr, vbCrLf)

ReDim Alldata(1 To UBound(Linedata))
For i = 0 To UBound(Linedata) - 1
    Coldata = Split(Linedata(i), ",")
    Alldata(i + 1).rowDate = Coldata(0)
    For j = 1 To UBound(Coldata) - 1
        Alldata(i + 1).data(j) = Coldata(j)
    Next j
Next i

Call QuickSort(Alldata, 1, UBound(Alldata))

End Sub

Private Sub QuickSort(tmpdata() As RowMatrix, ByVal leftP As Long, ByVal rightP As Long)
Dim i As Long
Dim j As Long
Dim x As Date
Dim SwapDim As RowMatrix

x = tmpdata((leftP + rightP) \ 2).rowDate
i = leftP
j = rightP

Do
    Do Until tmpdata(i).rowDate < x
        i = i + 1
    Loop
    Do Until tmpdata(j).rowDate > x
        j = j - 1
    Loop
    If i <= j Then Exit Do
    SwapDim = tmpdata(i)
    tmpdata(i) = tmpdata(j)
    tmpdata(j) = SwapDim
    i = i + 1
    j = j - 1
Loop
If (leftP < i - 1) Then Call QuickSort(tmpdata, leftP, i - 1)
If (rightP > j + 1) Then Call QuickSort(tmpdata, j + 1, rightP)
End Sub

投稿時間:2002/11/07(Thu) 10:03
投稿者名:A221
Eメール:
URL :
タイトル:
Re^4: 無理でした(mOm)
すこし興味があったので実験してみたのですが、さんざんでした。

魔界の仮面弁士さんが作られたテストデータ生成を少しいじって
5000日×5000個で作ってみたところ、ファイルサイズが95MB
になりました。(動作が不安定でとまったり・・)

テキストからの読込であれば、花ちゃんさんのおっしゃるように

>ファイルの指定行(範囲・飛び飛びでも可)を読込む事ができ高速に
>CSVファイルを読み込めます。
>最後の5日間のデータがファイルの最後の方ならある範囲までのデータを
>読み飛ばせば早くなります。

これらの処理を入れないと実行すら難しいですね。

投稿時間:2002/11/06(Wed) 23:02
投稿者名:魔界の仮面弁士
Eメール:
URL :
タイトル:
ADOを使うなら
ADOを使って、そのCSVファイルをデータベースのように扱うこともできます。


=================================
Option Explicit

Private Sub Command1_Click()
    'これは、実験用のcsvファイルを作成するだけです。

    Dim FNo As Integer
    Dim Dt As String
    Dim I As Long
    
    Randomize
    FNo = FreeFile()
    Open "C:\USER\TEST.CSV" For Output As #FNo
    
    Write #FNo, "日付", "値"
    For I = 1 To 5000
        Dt = Format(DateSerial(2002, 1, I), "yyyy-mm-dd")
        Write #FNo, Dt, Int(Rnd() * 1000)
    Next
    
    Close #FNo
End Sub

Private Sub Command2_Click()
    'こちらが実際の処理。データシェイプを利用して算出する例です。
    Dim Cn      As ADODB.Connection
    Dim rsCSV   As ADODB.Recordset
    Dim rsCalc  As ADODB.Recordset
    Dim SQL     As String

    Set Cn = New ADODB.Connection
    Cn.Provider = "MSDataShape"
    Cn.Properties("Data Provider").Value = "Microsoft.Jet.OLEDB.4.0"
    Cn.Open "Data Source=C:\USER\;" _
          & "Extended Properties=""text;HDR=YES;FMT=Delimited"""

    '日付の降順に並べて、そのうちの上位5件を取得します。
    SQL = "SELECT TOP 5" _
        & "   日付, 値" _
        & " FROM `TEST.CSV`" _
        & " ORDER BY 日付 DESC"
    Set rsCSV = New ADODB.Recordset
    rsCSV.Open "SHAPE {" & SQL & "} AS rsCSV", Cn

    '別途作成した、rsCSVというRecordsetをリシェイプします。
    SQL = "SHAPE rsCSV COMPUTE" _
        & "  rsCSV," _
        & "  AVG(rsCSV.値) AS 平均," _
        & "  MAX(rsCSV.値) AS 最大"
    Set rsCalc = Cn.Execute(SQL)

    '結果を表示します。
    Debug.Print "直近5日間の平均は、"; rsCalc.Fields("平均").Value; "です。"
    Debug.Print "直近5日間の最大は、"; rsCalc.Fields("最大").Value; "です。"

    rsCalc.Close
    rsCSV.Close
    Cn.Close
    
    Set rsCalc = Nothing
    Set rsCSV = Nothing
    Set Cn = Nothing
End Sub

投稿時間:2002/11/05(Tue) 16:04
投稿者名:花ちゃん
Eメール:
URL :
タイトル:
Re: 平均値を求める
> お世話になります。
>
> 5000日分のデータがあり、過去5日分の平均値を
> 取りたいのですが、一つのコードだと何も問題はありませんが、
> コードが5000個あります。
>
> かなり時間がかかってしまいます。これは何とか出来ないでしょうか?
>
> 今、やっているのは、データ(CSV)を
> 一行づつ読み込んで、最後の5日間の平均を取得する
> といった感じです。

FileSystemObject オブジェクトを使ってファイルの読み書きすれば
ファイルの指定行(範囲・飛び飛びでも可)を読込む事ができ高速に
CSVファイルを読み込めます。
最後の5日間のデータがファイルの最後の方ならある範囲までのデータを
読み飛ばせば早くなります。

投稿時間:2002/11/08(Fri) 15:20
投稿者名:アンパンマン
Eメール:
URL :
タイトル:
Re: 平均値を求める
皆さん、お返事ありがとうございます。

結局うまく出来なかったので、今回は飛ばしたいと思います。

色々とありがとうございました。