سؤال

أنا في الأساس بحاجة إلى الإجابة على هذا السؤال الذي يوفر توزيع قانون السلطة, ، ترجم إلى T-SQL بالنسبة لي.

أريد سحب اسم العائلة ، واحد في وقت واحد ، من أ قدم التعداد جدول الأسماء. أريد الحصول على نفس التوزيع تقريبًا كما يحدث في السكان. يحتوي الجدول على 88،799 أسماء في المرتبة حسب التردد. "Smith" هي المرتبة الأولى بنسبة 1.006 ٪ ، "Alderink" هي المرتبة 88،799 بتردد 1.7 × 10^-6. "Sanders" هي المرتبة 75 بتردد 0.100 ٪.

المنحنى لا يجب أن يتناسب بدقة على الإطلاق. فقط أعطني حوالي 1 ٪ "سميث" وحوالي 1 في مليون "Alderink"

هذا ما لدي حتى الآن.

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

ولكن هذا بالطبع ينتج عنه توزيع موحد.

أعدك أنني ما زلت أحاول معرفة ذلك بنفسي بحلول الوقت الذي يستجيب فيه شخص أكثر ذكاءً.

هل كانت مفيدة؟

المحلول

لماذا تسوية توزيع قانون الطاقة عندما يمكنك الاستخلاص من التوزيع الفعلي؟

أقترح عليك تغيير جدول الأسماء الأخيرة لتشمل عمودًا رقميًا يحتوي على قيمة رقمية تمثل العدد الفعلي للرسائل غير المتوفرة مع اسم أكثر شيوعًا. ربما تريد رقمًا على نطاق أصغر ولكنه متناسق ، على سبيل المثال ، ربما 10000 لكل في المئة من التمثيل.

ستظهر القائمة بعد ذلك شيئًا مثل:
(بخلاف الأسماء الثلاثة المذكورة في السؤال ، أنا أظن عن وايت ، جونسون وآخرون)

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ترتيب الانتصار ؛ هذا سيضمن اختيار الإدخال الأول (سميث). سيكون البديل هو بدء السلسلة مع Smith عند 10،060 بدلاً من الصفر وتجاهل السحب العشوائي أصغر من هذه القيمة.

بصرف النظر عن مسألة إدارة الحدود (بدءًا من الصفر بدلاً من 10،060) المذكورة أعلاه ، فإن هذا الحل ، إلى جانب الإجابات الأخرى حتى الآن ، هو نفسه الذي اقترح في 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)

وهو الاستعلام من السؤال باستثناء السطر الأخير.

أعد تحريره:
عند النظر إلى التوزيع الفعلي ، كما هو واضح في بيانات الإحصاء ، فإن المنحنى شديد الانحدار وسيتطلب معامل قوة كبير للغاية ، والذي بدوره قد يتسبب في تدفقات و/أو أخطاء تقريب شديد في الصيغة الساذجة الموضحة أعلاه.
قد يكون النهج الأكثر عقلانية هو العمل في عدة مستويات أي لإجراء عدد متساوٍ من السحب في كل من ، على سبيل المثال ، ثلاثة ثلثين (أو أربعة أرباع أو ...) من التوزيع التراكمي ؛ ضمن كل قائمة من هذه الأجزاء ، سنرسم باستخدام وظيفة قانون الطاقة ، ربما مع نفس النطاقات ، ولكن مع نطاقات مختلفة.
فمثلا
على افتراض الثلثين ، تنقسم القائمة على النحو التالي:

  • الثالث الأول = 425 اسمًا ، من سميث إلى ألفارادو
  • الثاني الثاني = 6،277 أسماء ، من الرابح
  • آخر ثالث = 82،097 أسماء ، من فريسبي إلى النهاية

إذا كنا نحتاج ، على سبيل المثال ، 1000 اسم ، فسنرسم 334 من الثلث الأول من القائمة ، 333 من الثلث الثاني و 333 من الثلث الأخير.
بالنسبة لكل من الثلثين ، كنا نستخدم صيغة مماثلة ، ربما مع وجود قوة أكبر في الثلث الأول (كانت مهتمة حقًا بتفضيل الأسماء السابقة في القائمة ، و أيضا حيث تكون الترددات النسبية أكثر صلة إحصائيا). يمكن أن تبدو استعلامات الاختيار الثلاثة كما يلي:

-- 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).

ثم قم بتعديل SELECT لاسترداد أول LN برتبة أكبر من نتيجة الصيغة الخاصة بك.

قرأت السؤال على أنه "أحتاج إلى الحصول على دفق من الأسماء من شأنه أن يعكس تواتر الأسماء الأخيرة من تعداد الولايات المتحدة 1990"

ربما قرأت السؤال بشكل مختلف قليلاً عن الاقتراحات الأخرى ، وعلى الرغم من أن الإجابة قد تم قبولها ، ومن خلال الإجابة عليها ، سأساهم في تجربتي في أسماء الإحصاء الأخيرة.

كنت قد قمت بتنزيل نفس البيانات من تعداد 1990. كان هدفي هو إنتاج عدد كبير من الأسماء التي سيتم تقديمها لاختبار البحث أثناء اختبار الأداء لتطبيق السجل الطبي. لقد أدرجت الأسماء الأخيرة والنسبة المئوية للتردد في جدول. أضفت عمودًا وملأته بأحد الأعداد الصحيحة التي كانت نتاج "إجمالي الأسماء المطلوبة * التردد". لم تزيد بيانات التردد من التعداد إلى 100 ٪ تمامًا ، لذا فإن إجمالي عدد الأسماء كان أقل قليلاً من المتطلبات. تمكنت من تصحيح الرقم عن طريق اختيار أسماء عشوائية من القائمة وزيادة عددهم حتى حصلت على الرقم المطلوب بالضبط ، لا يتم إدراج العدد بشكل عشوائي أبدًا إلى أكثر من 0.05 ٪ من إجمالي 10 ملايين.

لقد أنشأت 10 ملايين رقم عشوائي في حدود 1 إلى 88799. مع كل رقم عشوائي ، أختار هذا الاسم من القائمة وأقلل من العداد لهذا الاسم. كان نهجي هو محاكاة التعامل مع سطح البطاقات باستثناء سطح السفينة الخاص بي كان لديه العديد من البطاقات المتميزة وعدد متشابه من كل بطاقة.

هل تقوم بتخزين الترددات الفعلية مع الرتب؟

إن تحويل الجبر من تلك الإجابة المقبولة إلى MySQL ليس عناء ، إذا كنت تعرف القيم التي يجب استخدامها n. y سيكون ما لديك حاليا ROUND(88799 * RAND(), 0) و x0,x1 = 1,88799 أعتقد ، على الرغم من أنني قد أسيء فهمه. مشغل الرياضيات الوحيد غير القياسي المشارك من منظور T-SQL هو ^ وهو عادل POWER(x,y) == x^y.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top