質問

基本的に答えが必要です これは、パワーローディストリビューションを提供する質問です, 、私のためにt-sqlに翻訳されています。

姓を一度に1つずつ引きたいと思っています 国勢調査は名前の表を提供しました. 。母集団で発生するのとほぼ同じ分布を取得したいと思います。テーブルには、周波数でランク付けされた88,799の名前があります。 「スミス」は1.006%の周波数でランク1、「Alderink」はランク88,799で、周波数は1.7 x 10^-6です。 「サンダース」はランク75で、頻度は0.100%です。

曲線はまったく正確に適合する必要はありません。約1%の「スミス」と100万人に1人の「Alderink」をください

これが私がこれまでに持っているものです。

SELECT [LastName]
FROM [LastNames] as LN
WHERE LN.[Rank] = ROUND(88799 * RAND(), 0)

しかし、これはもちろん均一な分布をもたらします。

賢い人が応答するまでに、これを自分で理解しようとしていると約束します。

役に立ちましたか?

解決

実際の分布から引き出すことができるのに、なぜパワーローディストリビューションに落ち着くのですか?

LastNamesテーブルを変更して、より一般的な名前を持つ実際の数字の個別の数を表す数値を含む数値列を含めることをお勧めします。おそらく、たとえば、より小さいが比例的なスケールで数字が必要です。

リストは次のようになります。
(質問に記載されている3つの名前を除いて、私はホワイトについて推測しています、ジョンソン等)

Smith          0   
White     10,060
Johnson   19,123
Williams  28,456
...
Sanders  200,987
..
Alderink 999,997

そして、名前の選択はそうでしょう

SELECT TOP 1 [LastName]
FROM [LastNames] as LN
WHERE LN.[number_described_above] < ROUND(100000 * RAND(), 0)
ORDER BY [number_described_above] DESC

これは、[均一な分布]乱数を超えない最初の名前を選択しています。クエリ、使用方法に注意してください 未満 注文 desc-Ending Order;これにより、最初のエントリ(スミス)が選ばれることが保証されます。別の方法は、スミスでシリーズをゼロではなく10,060で開始し、ランダムを破棄することです。この値よりも小さくなります。

上記の境界管理の問題(10,060ではなくゼロから始まる)は別として、この解決策は、これまでに他の2つの応答とともに、で示唆されているものと同じです。 dmckeeこの質問で言及されている質問に対する答え。本質的にアイデアはCDFを使用することです(累積分布関数).


編集:
使用することを主張する場合 実際の分布ではなく数学的関数, 、以下は、実際の分布の「ロングテール」形状を何らかの形で伝える電力法機能を提供する必要があります。 @pwrcoef値(整数である必要はありません)を微調整することができます。本質的には共同体が大きくなればなるほど、リストの先頭に歪んでいます。

DECLARE @PwrCoef INT
SET @PwrCoef = 2
SELECT 88799 - ROUND(POWER(POWER(88799.0, @PwrCoef) * RAND(), 1.0/@PwrCoef), 0)

ノート:
- 上記の関数の余分な「.0」は、SQLに整数操作ではなくフロート操作を実行させるために重要です。
- 88799から電力計算を差し引く理由は、計算の分布がスケールの終わりに近いほど、描画される可能性が高いためです。姓のリストは逆の順序でソートされています(おそらく最初の名前)、このサブラクションが必要です。

たとえば、3の力を仮定すると、クエリは次のようになります

SELECT [LastName]
FROM [LastNames] as LN
WHERE LN.[Rank]
     = 88799 - ROUND(POWER(POWER(88799.0, 3) * RAND(), 1.0/3), 0)

これは、最後の行を除く質問からのクエリです。

再編集:
国勢調査のデータで明らかなように、実際の分布を見ると、曲線は非常に急勾配であり、 非常に大きな電力係数。 上記の素朴な式で。
より賢明なアプローチは、いくつかの層で動作することであり、累積分布の3分の3(または4四半期または...)のそれぞれで同数の引き分けを実行することです。これらの各パーツリスト内で、おそらく同じ共同体で、範囲が異なる場合は、パワー法則関数を使用して描画します。
例えば
3分の1を仮定すると、リストは次のように分割されます。

  • スミスからアルバラドまで、最初の3番目の名前= 425名
  • 2番目の3番目の= 6,277名、ゲイナーまで
  • 最後の3番目= 82,097の名前、フリスビーから最後まで

たとえば、1,000の名前を必要とする場合、リストの上位3分の1から334、2番目から333、最後の3分の3から333を描画します。
3分の1のそれぞれについて、同様の式を使用します。おそらく、最初の3分の1のためにより大きなパワーを共有しています(リストの以前の名前を支持することに本当に興味がありました。 また、相対周波数がより統計的に関連している場合)。 3つの選択クエリは、次のようになります。

-- Random Drawing of a single Name in top third
--   Power Coef = 12
SELECT [LastName]
FROM [LastNames] as LN
WHERE LN.[Rank]
     =  425 - ROUND(POWER(POWER(425.0, 12) * RAND(), 1.0/12), 0)

-- Second third; Power Coef = 7
...
WHERE LN.[Rank]
     =  (425 + 6277) - ROUND(POWER(POWER(6277.0, 7) * RAND(), 1.0/7), 0)

-- Bottom third; Power Coef = 4
...
WHERE LN.[Rank]
     =  (425 + 6277 + 82097) - ROUND(POWER(POWER(82097.0, 4) * RAND(), 1.0/4), 0)

他のヒント

PDFをランクとして保存する代わりに、CDF(Aldekirkから始まるすべての周波数の合計)を保存します。

次に、選択を変更して、式の結果よりもランクが大きい最初のLNを取得します。

私は「1990年の米国国勢調査からの姓の頻度を反映する名前のストリームを取得する必要がある」とこの質問を読みました。

私は質問を他の提案とは少し違った方法で読んだかもしれませんし、答えが受け入れられていますが、それは非常に答えを通して、私は国勢調査の姓との私の経験を貢献します。

1990年の国勢調査から同じデータをダウンロードしました。私の目標は、医療記録アプリのパフォーマンステスト中に検索テストのために提出される多数の名前を作成することでした。姓と周波数の割合をテーブルに挿入しました。列を追加して、「必要な *周波数」の積である整数で埋めました。国勢調査からの頻度データは正確に100%になるわけではなかったため、名前の総数も要件に少し劣っていました。リストからランダムな名前を選択し、必要な数が正確に数になるまでカウントを増やすことで数値を修正することができました。ランダムに追加されたカウントは、合計1,000万の0.05%以上に拡大することはありませんでした。

1〜88799の範囲で1,000万回の乱数を生成しました。各乱数で、リストからその名前を選択し、その名前のカウンターを減らします。私のアプローチは、私のデッキにはさらに多くの異なるカードと各カードの数字があることを除いて、カードのデッキを扱うことをシミュレートすることでした。

実際の周波数をランクで保存していますか?

MySQLへの受け入れられた答えから代数を変換することは気にしません。 n. y あなたが現在持っているものになります ROUND(88799 * RAND(), 0)x0,x1 = 1,88799 私はそれを誤解するかもしれないが、私は思う。 T-SQLの観点から関与する唯一の非標準の数学オペレーターは ^ それはまさにです POWER(x,y) == x^y.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top