Repository: NVIDIA-Merlin/NVTabular

Issue:
[BUG] Bug in generating data with Power Law in data_gen.py
**Describe the bug**
In data_gen.py data generation script, the method for for generating data using Power Law Distribution seems to be using an incorrect formula, because of which it's ignoring the min. values. What the distribution should look like:

Reference: https://mathworld.wolfram.com/RandomNumber.html

![image](https://user-images.githubusercontent.com/20920371/129838989-b0c3c5e3-3dad-4939-b37b-1fb8524bcc30.png)

Current Implementation:

```
def create_col(self, num_rows, dtype=np.float32, min_val=0, max_val=1):
    gamma = 1 - self.alpha
    # range 1.0 - 2.0 to avoid using 0, which represents unknown, null, None
    ser = cudf.Series(cupy.random.uniform(0.0, 1.0, size=num_rows))
    factor = (cupy.power(max_val, gamma) - cupy.power(min_val, gamma)) + cupy.power(
        min_val, gamma
    )
    ser = ser * factor.item()
    exp = 1.0 / gamma
    ser = ser.pow(exp)
    # replace zeroes saved for unknown
    # add in nulls if requested
    # select indexes
    return ser.astype(dtype)
```
Here, the "factor" completely ignores the influence of min_val

What it should look like
```
def create_col(self, num_rows, dtype=np.float32, min_val=0, max_val=1):
    gamma = 1 - self.alpha
    # range 1.0 - 2.0 to avoid using 0, which represents unknown, null, None
    ser = cudf.Series(cupy.random.uniform(0.0, 1.0, size=num_rows))
    factor = (cupy.power(max_val, gamma) - cupy.power(min_val, gamma))
    ser = (ser * factor.item()) + cupy.power(min_val, gamma).item()
    exp = 1.0 / gamma
    ser = ser.pow(exp)
    # replace zeroes saved for unknown
    # add in nulls if requested
    # select indexes
    return ser.astype(dtype)
```

**Steps/Code to reproduce bug**
Simply generate data using PowerLaw with min_val > 1, and see the distribution and the minimum value generated
Before fix. Simple test:


```
p = datagen.PowerLawDistro(0.1) 
col = p.create_col(num_rows=10000000, min_val=5, max_val=1000)
```

In one instance col.min() returns a value 1.6266105e-06. It should be greater than 5.

**Expected behavior**
A clear and concise description of what you expected to happen.

**Environment details (please complete the following information):**
 - Environment location: 1xA100-80GB 
 - Method of NVTabular install: Docker, nvcr.io/nvidia/merlin/merlin-tensorflow-training:0.5.3

**Additional context**
Found this problem while trying to plot the data generated.



Discussion:

Resolving patch:
diff --git a/nvtabular/tools/data_gen.py b/nvtabular/tools/data_gen.py
--- a/nvtabular/tools/data_gen.py
+++ b/nvtabular/tools/data_gen.py
@@ -46,10 +46,8 @@ def create_col(self, num_rows, dtype=np.float32, min_val=0, max_val=1):
         gamma = 1 - self.alpha
         # range 1.0 - 2.0 to avoid using 0, which represents unknown, null, None
         ser = cudf.Series(cupy.random.uniform(0.0, 1.0, size=num_rows))
-        factor = (cupy.power(max_val, gamma) - cupy.power(min_val, gamma)) + cupy.power(
-            min_val, gamma
-        )
-        ser = ser * factor.item()
+        factor = cupy.power(max_val, gamma) - cupy.power(min_val, gamma)
+        ser = (ser * factor.item()) + cupy.power(min_val, gamma).item()
         exp = 1.0 / gamma
         ser = ser.pow(exp)
         # replace zeroes saved for unknown


Test patch: