それぞれに同様の数値を持つデータのバンド/グループを動的に生成する方法は?
-
12-10-2019 - |
質問
バンドを動的に生成したいので、レポートにグループ化されます。
私の最初の考えは、最小値と最大値を取得し、差を分割することにより、バンドを生成することでした。
たとえば、大勢の人々の給与があったとします。
- 最も低い賃金は年間12,000ポンドを稼ぎ、最高は3,000,000ポンドを稼ぐ
- だから私はそれを同様のサイズの10バンドに分割しました:(£3mill-£12k) / 10 =£298800
- だから私の最初のバンドは£12kから310,800ポンドになり、何千人もの人々を獲得します
- 私の2番目のバンドは£310kから£610kになり、数百を持っています
- 他のすべてのバンドにはそれぞれに数人の人がいます
したがって、これは実際にはあまり役に立ちません。私が手動でバンドを作成する場合、それぞれにほぼ同様の数字が必要です。 1.5〜300万ポンド
これはほんの一例です - 異なる分布がたくさんある可能性があります。
バンドを生成するアルゴリズムを探しているので、ユーザーは必要なバンドの数を入力し、データがそれぞれに似た数字を持つ多くのバンドにグループ化されます。
バンディングは迅速である必要があります - データセット全体をループすることはできません。
アプリケーションはSQLの上にあるC#ですが、他の言語からの解決策を歓迎します。
解決
既存のデータセットを「バンド」に照会する方法について尋ねていると思います...
これが当てはまる場合、Oracleはこの目的でntile集計関数をサポートします。他のSQL実装には同等のものが必要です。
他のヒント
見たことがありますか ntile? SQL ServerとほとんどのDBMはそれをサポートしています。
例えば:
select b.band, count(*), min(b.valuefield), max(b.valuefield)
from (
select ntile(10) over (order by valuefield) as 'band', valuefield
from table ) b
group by b.band
あなたは間違った観点から問題を見ています。給与を見るのではなく、ソートされた給与の範囲で人の順序付けられた位置を見てください。アルゴリズムを少し脇に置いて、数学的に考えます。
すべての人を連れて、給料で並べ替えてください。現在、1からnまでの1つまで連続して番号を付けます。最後の給与は最高です。 Mグループが必要な場合、各グループにはN/M人が含まれます。したがって、最初の給与バンドは0から人[n/m]まで行きます。サラリー、2番目はそこから人[2*n/m]に行きます。
C#では、LINQでこれをかなり効率的に行うことができます。このようなもの。これはテストされていないコードであり、これは最終的な解決策ではなく概念です。おそらく、私が正しく考えていないエッジ状態の問題があるでしょう。
List<int> GetBands(int numBands)
{
using(var db = new MyContext())
{
var list SalaryBands = new List<int>();
var count = db.People.Count();
var salaries = db.People.OrderBy(item => item.Salary)
.Select(item => item.Salary);
int skipCount = count / numBands;
for(int segmentNum = 0; segmentNum < numBands; segmentCount++)
{
salaries = salaries.Skip(skipCount);
salaryBands.Add(salaries.First());
}
return salaryBands;
}
}
まず、まっすぐ線形とは対照的に、ログのようなグラフが必要です。
2番目の観察:私は通常、大きなサンプルデータセットを構築し(指定した例に似ています)、共通の要因を探し、実際のデータから定型システムを導き出します。もう少しシナリオを仮定できますか?