Обновите PostgreSQL столбцы со случайными числами в соответствии с единым или нормальным законом - PullRequest
0 голосов
/ 02 мая 2020

Контекст

У меня есть таблица PostgreSQL, которая содержит несколько сотен тысяч строк и много столбцов.

Short : я хотел бы инициализировать случайные значения в некоторых столбцах в соответствии с равномерным распределением или нормальным распределением .


Равномерное распределение

У меня есть 3 пустых столбца, которые я хотел бы инициализировать с помощью одинаковых случайных чисел (т.е. согласно равномерное распределение по каждому столбцу).

Для этого я использую функцию PostgreSQL random(), но в документации неясно, выбраны ли сгенерированные числа из равномерного или нормального распределения:

PostgreSQL (unclear) documentation for the random function Источник: https://www.postgresql.org/docs/12/functions-math.html

Итак, я высказал (надеюсь правильную) гипотезу, что с сегодняшнего дня это равномерное распределение.


Нормальное распределение

И у меня есть 3 других пустых столбца, которые я хотел бы инициализировать с помощью нормальных случайных чисел (т.е. согласно нормальное распределение по каждому столбцу):

Normal distribution for each of the 3 columns


Результаты

Для равномерное распределение

Я сделал это (на самом деле я понял это во время написания этого поста);

UPDATE schema.tables
     SET col1 = (1 * random() + 1)::float4,
     col2 = (1 * random() + 1)::float4,
     col3 = (1 * random() + 1)::float4

Это немного медленно, но, похоже, работает, потому что вот пример сгенерированных данных :

3 columns of uniform random number

И гистограмма данных для одного столбца почти одинакова, поэтому я думаю, что все в порядке:

Example of a uniform distribution across one column

Но было бы замечательно установить целые значения столбцов в одном кадре, а не построчно (или, возможно, этот построчный способ обновления таблица действительно лучше работает в SQL. Я не знаю, но это скорее рассуждения по линейной алгебре, которые у меня на заднем плане).


Для нормального распределения

Я застрял в следующем запросе, вдохновленном предыдущим, но использующим функцию normal_rand из tablefun c расширение:

UPDATE schema.table
  SET col1 = (1 * normal_rand(1,50.0,20.0) + 2)::float4),
  col2 = (1 * normal_rand(1,50.0,20.0) + 2)::float4),
  col3 = (1 * normal_rand(1,50.0,20.0) + 2)::float4),

но здесь я сталкиваюсь со следующей ошибкой: set-returning functions are not allowed in UPDATE.

Итак, я предположил, что должен использовать SELECT Подзапрос, следовательно, я тоже попробовал это, но без особого успеха:

UPDATE schema.table
  SET col1 = sub.col
  FROM (SELECT (1 * normal_rand(1, 50.0, 20.0) + 2)::float4 as col) AS sub,
  col2 = sub.col
  FROM (SELECT (1 * normal_rand(1, 50.0, 10.0) + 2)::float4 as col) AS sub,
  col3 = sub.col
  FROM (SELECT (1 * normal_rand(1, 50.0, 5.0) + 2)::float4 as col) AS sub

Где я получаю syntax error at or near col2

Но если я играю с одним столбцом:

UPDATE schema.table
  SET col1 = sub.col
  FROM (SELECT (1 * normal_rand(1, 50.0, 20.0) + 2)::float4 as col) AS sub;

Он почти работает, запрос выполнен успешно, но у меня есть одинаковое число в каждой строке столбца, что явно не делает его нормальным распределением!

Так что моя мечта можно было бы обновить все столбцы целый за один раз, используя что-то вроде:

UPDATE schema.table 
SET col1 = sub.col 
FROM (
    SELECT (
        1 * normal_rand(
            SELECT count(*) FROM schema.table, 
            50.0, 
            20.0
            ) + 2
    ):: float4 AS col
) AS sub;

Но здесь я снова получил синтаксическую ошибку во 2-й позиции SELECT; syntax error at or near "select"

Вопрос

Как мне установить один или несколько целых столбцов со случайными числами в соответствии с нормальным распределением?

1 Ответ

0 голосов
/ 02 мая 2020

В крайнем случае, вы можете попробовать следующее решение:

((random() + random() + random() + random() + random() + random() + random() + random() + random() + random() + random() + random()) - 6)

Приведенная выше идиома использует двенадцать random() вызовов для генерации случайного числа, которое приближается к стандартному нормальному распределению (среднее значение 0 и стандартное отклонение). 1) и использует преимущества центральной предельной теоремы. Отчасти это приближение, потому что случайное число, сгенерированное таким образом, не будет меньше -6 или больше 6, тогда как нормальное распределение теоретически может принимать любое действительное число; однако числа меньше -6 или больше 6 встречаются настолько редко (примерно 1 на 500 миллионов), что в вашем случае они могут быть незначительными.

...