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

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

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

1回答

4171閲覧

【C#】LINQを使用したクロス集計について

inari_ken

総合スコア34

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

0クリップ

投稿2019/02/01 03:09

編集2019/02/01 03:10

こんにちは。今回もよろしくお願いいたします。

前提・実現したいこと

List<string[]>型のリスト"filetredMultiGroupF"から、クロス集計をとりたいと思っています。
変数"result1"でグループ化した選択肢番号をもとに
変数"result2"にChoise,Countの並びでリスト化したいです。

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

変数"tmp"にて各選択肢番号ごとに抽出することはできたのですが、これをresult2に入れる際に
型の違いから格納することができません。
正しく格納する方法を教えてください。

該当のソースコード

C#

1 List<string[]> result2 = new List<string[]>(); 2 3 var result1 = filetredMultiGroupF.GroupBy(x => x[0] ).Select(x => x.Key).OrderBy(x => x); 4 foreach(var item in result1) 5 { 6 var tmp = filetredMultiGroupF.Where(x => x[1] == item) 7 .GroupBy(x => x[1]) 8 .Select(x => new { Choise = x.Key, Count = x.Count() }) 9 .OrderBy(x => x.Choise); 10 11 // result2.AddRange(???) 12 13 }

補足情報(入力・出力)

filetredMultiGroupFの中身は下表です。
プログラムでは1列目の回答と2列目の回答をクロス集計します。

列1列2列3・・・
12...
11...
22...
21...
22...
13...
13...

クロス集計の結果としては、result2に下記のような形で格納します
1,1   ※列1で"1"を選択 且つ 列2で"1"を選択した人のカウント
2,1   ※列1で"1"を選択 且つ 列2で"2"を選択した人のカウント
3,2   ※列1で"1"を選択 且つ 列2で"3"を選択した人のカウント
1,1   ※列1で"2"を選択 且つ 列2で"1"を選択した人のカウント
2,2   ※列1で"2"を選択 且つ 列2で"2"を選択した人のカウント

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

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

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

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

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

papinianus

2019/02/01 03:13 編集

> クロス集計の結果としては、result2に下記のような形で格納します で、書いておられる「1,1」「2,1」の左側の数字って何ですか?Listのn番目かと思ったんですが、1,2,3,1,2になってるんですよね。
inari_ken

2019/02/01 03:17

ご回答ありがとうございます。 左側の数字は列"2"の選択肢です(tmp.Choise)
papinianus

2019/02/01 03:28 編集

result2てList<string[]>ですから2次元配列ですよね?[["1","1"],["2","1"]["3","2"],...]となりたいということでOKですか?
guest

回答1

0

ベストアンサー

とりあえず、result2には、1の選択、2の選択、集計、の作りにしてます。

csharp

1 public static void Main() 2 { 3 var filetredMultiGroupF = new List<string[]> { new []{"1","2"},new []{"1","1"},new []{"2","2"},new []{"2","1"},new []{"2","2"},new []{"1","3"},new []{"1","3"}, }; 4 var result1/*unique1*/ = filetredMultiGroupF.Select(x=>x[0]).Distinct().OrderBy(x=>x); 5 var unique2 = filetredMultiGroupF.Select(x=>x[0]).Distinct().OrderBy(x=>x); 6 var result2 = filetredMultiGroupF.GroupBy(x => new { one = x[0], two = x[1]}).Select(g => new []{$"{g.Key.one}", $"{g.Key.two}", g.Count().ToString()}).OrderBy(a => a[0]).ThenBy(a=>a[1]); 7 foreach(var res in result2) 8 { 9 Console.WriteLine(string.Join(" , ", res)); 10 } 11 }

投稿2019/02/01 03:39

編集2019/02/01 04:46
papinianus

総合スコア12705

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

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

inari_ken

2019/02/01 04:32

ありがとうございます。result2の要素の並びはこちらでも問題ありません。 たった1行でクロス集計できるものなんですね;;; ちなみに、集計結果をorderbyにてg.Key.one→g.Key.twoの順でソートかける場合、どのようにnewしたパラメータを参照するのでしょう? var result2 = filetredMultiGroupF.GroupBy(x => new { one = x[0], two = x[1] }).Select(g => new[] { $"{g.Key.one}", $"{g.Key.two}", g.Count().ToString() }).OrderBy(g => g.???? );
papinianus

2019/02/01 04:50

ソートしたいんだろうなーと思って、結果に0列目を入れててよかったです。 ordeby,thenbyを使うのが簡易だと思います。もちろんorderbyでラムダをかいてもいいですが、面倒ですし、汎用性がないので割愛します(Comparerを取れる気もしますが、いずれにしても面倒) (列の値が数値でないか、もしくは数値でも桁が揃っているなら、g=>$"{g[0]},{g[1]}"と連結した値でソートすれば辞書順でうまく並ぶと思います)
tamoto

2019/02/01 04:54

横からですが、 コメントの部分にソートを書きたいならSelectの前にOrderByを置けばいいですよ。
papinianus

2019/02/01 04:59

GroupBy().OrderBy(g=>g.Key.one).ThenBy(g=>g.Key.two).Select()ということでしょうか。
tamoto

2019/02/01 05:02

はい、コメントのresult2を見た限り、g.Keyを参照してソートしたいと言うことだったので。
inari_ken

2019/02/01 06:02

papinianus様の案にて動作することを確認しました。 ちなみにg=>$"{g[0]},{g[1]}"ですが、これはorderbyに文字列としての{g[0]},{g[1]}を突っ込んでる状態なんでしょうか それともorderbyの中で{}を使うために$を設けていて、動作時には1,1のように勝手に変化するものなのでしょうか。 tamoto様のご回答でも動作することを確認しました var result2 = filetredMultiGroupF.GroupBy(x => new { one = x[0], two = x[1] }).OrderBy(g => g.Key.one).ThenBy(g => g.Key.two).Select(g => new[] { $"{g.Key.one}", $"{g.Key.two}", g.Count().ToString() }); お二人ともご回答ありがとうございました。
papinianus

2019/02/01 06:08 編集

$の件、文字列を作ってます。もし知ってるならstring.Format()の安全版です。文字列補間といいます。 https://docs.microsoft.com/ja-jp/dotnet/csharp/tutorials/string-interpolation ちなみにこの集計って2列だけじゃないんですよね、ホントは。Key側でのソートは、**より**可変にしにくいだろうなと思っての回答案です(配列インデクサでもソートはしにくいでしょうが)。
inari_ken

2019/02/01 06:31

ご回答ありがとうございます。 なるほど、安全版というのは$にするとコンパイルの時点で記入ミスを見つけてくれるのですね。VisualStudio使ってるのでこっちのほうが便利ですね。 下2行がいまいちピンとこないのですが(勉強不足ですいません)、要は可変性を持たせたプログラムをご回答いただいた、ということですか?
papinianus

2019/02/01 06:36 編集

列3のときを考えてください、ThenByに使うg.Key.threeを例えば3や2といった文字列・数値から組立られますか? 決してやさしくないと思います(具体コードは思いついてないです)が、3番目という情報から、ThenBy(x=>x[2])を作るほうがまだ取り組みやすそうです。 ちょうどタイミングよく、$を使えば容易に防げたバグの質問が↓に出たので共有しておきます。 https://teratail.com/questions/172085#reply-256331
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問