自力での解決をと思っていましたが、身も心も消耗して
きましたのでヘルプを求めてやってきました。
(VisualBasic2010 Express)
DataTableの2列目のすべての値の平均をAggregate句を
使って求めたいのですが、どなたかご教授願えれば幸いです。
Private Sub hoge()
Dim TB As New DataTable
TB.Columns.Add("名前", GetType(String))
TB.Columns.Add("体重", GetType(Double))
TB.Rows.Add("鈴木", 65.2)
TB.Rows.Add("佐藤", 75.5)
TB.Rows.Add("小林", 49.5)
TB.Rows.Add("高橋", 63.2)
Dim Sum_Wt as Double
Sum_Wt= Aggregate wt As XXXX In YYYY Into Average()
'↑のXXXX と YYYY のところの記述がわからないです。
End sub
まずは,MSDNの記述から。
http://msdn.microsoft.com/ja-jp/library/vstudio/bb531251.aspx
XXXXは列挙される型になります。
今回の場合は,DataRowになります。
次に,YYYYの部分は元になるコレクション,つまりはTB.Rowsになります。
最後に,Averageの中に,どの項目を使うのかを示す式を入れる必要があります。
wt("体重")をDoubleにキャストすることになるかと思います。
>最後に,Averageの中に,どの項目を使うのかを示す式を入れる必要があります。
>wt("体重")をDoubleにキャストすることになるかと思います。
お手上げです。こんなのしか思いつきません。↓
Average("SELECT 体重 FROM Ctype(TB.Rows,Double)")
その「SELECT云々」はどこから出てきたのですか。
LINQはコンパイル時に全てを式にします。
なので,文字列で式を指定するようなことはありません。
今はAggregateではなく、とりあえずTB.Compute("sum(体重)","")で済ませ
ました。For〜Eachでもいいんですが・・。
恥ずかしながら「LINQ」という言葉を最近知りました。
時間を見つけてLINQについて勉強するつもりです。
ご教授ありがとうございました。
> すべての値の平均をAggregate句を使って求めたいのですが
> Dim Sum_Wt as Double
平均なのに、変数名が Sum なのは何故でしょうか?
> Sum_Wt= Aggregate wt As XXXX In YYYY Into Average()
> '↑のXXXX と YYYY のところの記述がわからないです。
Into 句を見直した方が良いでしょう。
提示された構文だと、XXXX は「Double」で済みますが、
YYYY の部分が、「TB.AsEnumerable().Select(Function(r) CDbl(r!体重))」
などのような複雑な構文になってしまいます。
Into 句を見直した書き方としては、こんな感じ。
Dim Ave1 As Double = Aggregate row In TB Into Average(row.Field(Of Double)("体重"))
あるいは、こんな書き方もあります。
Dim Ave2 As Double = (From row In TB Select row.Field(Of Double)("体重")).Average()
Linq を使わず、DataTable の Compute メソッドを使う手もあります。
この方法だと、より古いバージョンの VB.NET でも算出できます。
Dim Ave3 As Double = CDbl(TB.Compute("Avg(体重)", ""))
いずれの方法を使うにしろ、件数が 0 だった場合の扱いに注意してください。
たとえば TB.Compute を使った方法では、0件の場合の戻り値が
DBNull になるため、その結果を CDbl すると変換エラーとなります。
また、上記 Ave1, Ave2 の構文も、0 件の時は要素なしエラーとなります。
データ件数が 0 の場合も考慮するためには、このような書き方ができます。
Dim Ave0 As Double = (From row In TB Select row.Field(Of Double)("体重")).DefaultIfEmpty().Average()
あるいは、事前に「If TB.Count > 0 Then」などの判定を入れるのも手です。
>>Dim Sum_Wt as Double
>平均なのに、変数名が Sum なのは何故でしょうか?
悪戦苦闘中の名残です。
Aggregateの件ですが、具体例を示していただきありがとうございました。
昔VB6でSQL文でExcelの巨大ファイルを処理した
ことがあるのでLinqはSQL文っぽいなぁという感じがしています。
その後も暇を見つけては調べていましたが自力での解決には
至っておらず、半ば諦めかけておりました。
MSDNで調べても「わけわかめ」でついついググって
「そのものズバリ!」のサンプルのコピペに頼ってしまいます。
みなさんとグーグルが私の先生です。
私はネット環境無しでは何も出来ないと思っています。
上級者とそうでない人とで、「見えているもの」がこれほど
違う世界はないのではないかと思い始めています。
> あるいは、事前に「If TB.Count > 0 Then」などの判定を入れるのも手です。
訂正:
型付 DataSet/DataTable なら、If TB.Count > 0 Then でも良いですが、
素の DataTable の場合は、If TB.Rows.Count > 0 Then もしくは
If TB.AsEnumerable().Any() Then などを使ってみてください。
> 「そのものズバリ!」のサンプルのコピペに頼ってしまいます。
VB.NET 向け LINQ サンプル集
http://msdn.microsoft.com/en-us/vstudio/bb688088.aspx
ご親切にありがとうございます。
サンプル集、そこそこ目を通しました。
Linqの素晴らしさを実感しました。
こんなこともできるんですね。驚きです。↓
Public Sub Linq78()
Dim numbers() As Integer = {5, 4, 1, 3, 9, 8, 6, 7, 2, 0}
Dim numSum = numbers.Sum()
Console.WriteLine("The sum of the numbers is " & numSum)
End Sub
ツイート | ![]() |