Generating Random Datasets

Challenge

Quickly create random datasets with a specific column names and random data.
​
Since this is a recurring need, I do not want to spend time reinventing this wheel every time.

Use Cases

Currently, I have the following specific use cases in mind, though I believe that many more will present themselves.

Generating Unit Test Data

While I am a big believer in Test Driven Development, I often fail due to commitments made to produce something of value to clients. In order to more consistently, as well as more often, apply Test Driven Development principles, I need a way to quickly generate useable test data.
​
In order to avoid the false confidence that we can get from seeing the same set of unit tests succeed, when appropriate, I like to create additional unit tests using random data.

Generating Data For Proofs-of-Concepts and Examples

I often find myself needing a quick dataset for a proof-of-concept, create an example or to collaborate with others while keeping proprietary data private.

Generating Scaled Down Datasets for End-To-End Testing

I try to take the Test Driven Development strategy beyond unit testing. While it would be great to always use real-world data for testing, it is often not feasible. For example, I often work on applications that can take hours or even days to run. If I used real-world data in those situations, the time to complete a test-cycle could severely limit my productivity.

Getting Started Before The Client Gives Me Data

I sometimes find myself needing to get started before the data I need is available.

Solution

The Function

In[]:=
dsGenerateRandomDataset[assoc_Association,nRows_Integer]:=Block[​​{​​eval​​},​​eval[key_String,{f_,args_}]:=keyf[Sequence[args]];​​eval[key_String,{f_}]:=keyf[];​​​​Table[Prepend[Association[KeyValueMap[eval,assoc]],<|"ID"id|>],{id,1,nRows}]//Dataset​​​​];​​​​

Example Usage

Sales Data

If I am working on a project that will analyze product sales by region, I can use this function to generate a dataset of any size.
In[]:=
dsGenerateRandomDataset[​​<|​​"Region"{RandomChoice,{"North","South","East","West"}},​​"Product"{RandomChoice,{"T-Shrits","Pants","Hats","Dresses"}},"Sales"{RandomInteger,{0,100}}​​|>,​​10​​]​​
Out[]=
ID
Region
Product
Sales
1
South
Pants
95
2
West
Pants
93
3
West
Pants
40
4
South
Dresses
52
5
North
Pants
94
6
East
Pants
6
7
East
Pants
48
8
South
Pants
19
9
North
Dresses
88
10
North
Pants
39

Daily Observations

@Rohit_Namjoshi provided another use case. What if we need a dataset of random observations based on specific distributions. We can do something like:
In[]:=
randomNormal[]:=RandomVariate[NormalDistribution[]];​​randomPoisson[]:=RandomVariate[PoissonDistribution[3]];​​​​dsGenerateRandomDataset[​​<|​​"Ob 1"{randomNormal},​​"Ob 2"{randomPoisson}​​|>,​​10​​][​​All,​​<|​​"Date"DatePlus[DateObject[{2020,1,1}],#["ID"]],​​#​​|>&​​]
Out[]=
Date
ID
Ob 1
Ob 2
Thu 2 Jan 2020
1
-2.47345
6
Fri 3 Jan 2020
2
-0.0113048
3
Sat 4 Jan 2020
3
0.273767
2
Sun 5 Jan 2020
4
-1.09113
1
Mon 6 Jan 2020
5
-0.289086
5
Tue 7 Jan 2020
6
-1.70597
3
Wed 8 Jan 2020
7
-1.04887
3
Thu 9 Jan 2020
8
0.163549
7
Fri 10 Jan 2020
9
-0.519316
3
Sat 11 Jan 2020
10
-0.427402
3

Next Steps

Get Feedback from the Community

I am posting this to the community hoping to get feedback on:
◼
  • How are others implementing Test Driven Development strategies
  • ◼
  • My implementation? Are there better ways to do this?
  • ◼
  • Other use cases where this solution might apply
  • Refactor

    Since I can imagine other uses for the private eval[] function, I should consider making it a readily available reusable function.

    Expand this Concept Outside of Datasets

    Consider using this approach for other types of test data generation:
    ◼
  • Networks
  • ◼
  • Matrices
  • ◼
  • Hierarchical Lists/Associations
  • ◼
  • etc.