Pregunta

Básicamente necesito la respuesta a esta pregunta de manera que proporciona una distribución de ley de potencia , traducido a T-SQL para mí.

Quiero tirar de un apellido, una a la vez, de un censo facilitó la tabla de nombres . Quiero llegar más o menos la misma distribución que ocurre en la población. La tabla tiene 88,799 nombres clasificados por frecuencia. "Smith" es rango 1 con frecuencia 1.006% "Alderink" es rango 88799 con frecuencia de 1,7 x 10 ^ -6. "Sanders" es rango 75 con una frecuencia de 0,100%.

La curva no tiene que ajustarse exactamente en absoluto. Sólo dame un 1% "Smith" y cerca de 1 en un millón "Alderink"

Esto es lo que tengo hasta ahora.

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

Pero esto, por supuesto, produce una distribución uniforme.

Te prometo Voy a seguir tratando de resolver esto a mí mismo por el tiempo que una persona inteligente responde.

¿Fue útil?

Solución

¿Por qué conformarse con la distribución de ley de potencia cuando se puede extraer de la distribución real?

Le sugiero que modificar la tabla apellidos que incluir una columna numérica que contendría un valor numérico que representa el número real de indivuduals con un nombre que es más común. Usted probablemente querrá un número en una escala más pequeña, pero proporcional, por ejemplo, tal vez 10.000 por cada porcentaje de la representación.

La lista a continuación, sería algo como:
(Aparte de los 3 nombres mencionados en la pregunta, supongo que sobre White, Johnson et al)

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

Y la selección del nombre sería

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

Eso de recoger el primer nombre que el número no supera el número aleatorio [uniforme distribución]. Nota cómo la consulta, usos menor que y ordenación en desc para -ending; esta voluntad garantía de que la primera entrada (Smith) es recogido. La alternativa sería empezar la serie con Smith en 10.060 en vez de cero y para descartar el azar empates menor que este valor.

Aparte de la cuestión de la gestión límite (a partir de cero en lugar de 10.060) mencionado anteriormente, esta solución, junto con los otros dos respuestas hasta el momento, son los mismos que el sugerido en dmckee ' s respuesta a la pregunta que se hace referencia en esta pregunta. Esencialmente, la idea es utilizar la CDF ( función de distribución acumulativa ).


Editar :
Si usted insiste en el uso de una función matemática en lugar de la distribución real , la siguiente debe proporcionar una función de ley de potencia que de alguna manera haría una "cola larga" forma de la distribución real. Es posible que wan para ajustar el valor @PwrCoef (que por cierto no tiene que ser un número entero), esencialmente, cuanto mayor sea el coeficiente, más sesgada al principio de la lista es la función.

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

Notas:
  - el extra" 0.0" en la función anterior son importantes para forzar SQL para realizar operaciones de flotación en lugar de operaciones con enteros
.   - la razón por la restamos el cálculo de la potencia de 88799 es que la distribución del cálculo es tal que cuanto más cerca está un número más cerca del final de nuestra escala, lo más probable es que se elaborará. La lista de apellidos que se ordena en orden inverso (muy probablemente el primer nombre), necesitamos esta sustracción.

Suponiendo una potencia de, por ejemplo, 3 la consulta sería entonces algo como

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

¿Cuál es la pregunta de la pregunta a excepción de la última línea.

Re-Edit :
Al analizar la distribución real, como es evidente en los datos del censo, la curva es muy empinada y requeriría un coeficiente de potencia muy grande, que a su vez podría causar desbordamientos y / o errores extremos redondeo en la ingenua fórmula que se muestra anteriormente.
Un enfoque más sensible puede ser para funcionar en varios niveles es decir, para llevar a cabo el mismo número de empates en cada uno de los, digamos, tres tercios (o cuatro cuartos o ...) de la distribución acumulada; dentro de cada una de estas listas de piezas, nos dibuja usando una función de ley de potencia, posiblemente con el mismo coeficiente, pero con diferentes rangos.
Por ejemplo
Suponiendo tercios, se divide la lista de la siguiente manera:

  • primer tercio = 425 nombres, de Smith a Alvarado
  • Segundo Tercero = 6.277 nombres, de a Gainer
  • último tercio = 82,097 nombres, de Frisby hasta el final

Si nos vamos a la necesidad, por ejemplo, 1.000 nombres, nos dibujan 334 desde el tercio superior de la lista, 333 del segundo, tercer y 333 desde el último tercio.
Para cada una de las terceras partes que usaríamos una fórmula similar, tal vez con un coeficiente de potencia más grande para el primer tercio (eran eran realmente está interesado en favorecer los nombres anteriores en la lista, y también donde la relación frecuencias son estadísticamente más relevante). Los tres consultas de selección podría ser similar a la siguiente:

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

Otros consejos

En lugar de almacenar el archivo PDF como rango, almacenar la CDF (la suma de todas las frecuencias hasta ese nombre, a partir de Aldekirk).

A continuación, modifique su selección para recuperar la primera LN con mayor rango que el resultado de la fórmula.

He leído la pregunta como "Necesito conseguir un flujo de nombres que será un reflejo de la frecuencia de apellidos desde el censo de 1990 de Estados Unidos"

Me podría haber leído la pregunta de forma diferente a las otras sugerencias y aunque la respuesta ha sido aceptada, y un muy través respuesta es, voy a aportar mi experiencia con los apellidos del censo.

Me había descargado los mismos datos del censo de 1990. Mi objetivo era producir un gran número de nombres que se somete a las pruebas de búsqueda durante las pruebas de rendimiento de una aplicación de registro médico. Inserté los apellidos y el porcentaje de la frecuencia en una tabla. Añadí una columna y lo llenó de un número entero que era el producto de los "nombres total requerido * frecuencia". Los datos de frecuencia del censo no den exactamente el 100% en lo que mi número total de nombres era también un poco por debajo de la exigencia. Yo era capaz de corregir el número seleccionando al azar los nombres de la lista y aumentar su recuento hasta que tuve exactamente el número requerido, el recuento añadido al azar Nunca ammounted a más de 0,05% del total de 10 millones de dólares.

me genera 10 millones de números aleatorios en el rango de 1 a 88799. Con cada número al azar elegiría ese nombre en la lista y disminuir el contador para ese nombre. Mi enfoque es tratar de simular una baraja de cartas, excepto mi terraza tenía muchas más tarjetas distintas y un número varing de cada tarjeta.

Cómo se almacenan las frecuencias reales con las filas?

La conversión de la álgebra de esa respuesta aceptada a MySQL no se moleste, si usted sabe qué valores utilizar para n. y sería lo que actualmente tiene ROUND(88799 * RAND(), 0) y x0,x1 = 1,88799 creo, aunque podría entenderlo mal. El operador de matemáticas solamente no estándar involucrados desde el punto de vista de T-SQL es ^ que es sólo POWER(x,y) == x^y.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top