def generate_data(self):
df = pd.DataFrame()
letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
self.pop_mean = random.randint(10, 50)
self.pop_sd = round(self.pop_mean * random.uniform(0.10, 0.30))
for group in range(self.groups):
mean = self.pop_mean
sd = self.pop_sd
same_diff = random.randint(0,3)
if same_diff >= 1:
effect = round(mean * random.uniform(0.10, 0.50))
mean += effect
samples = np.random.normal(mean, sd, self.n)
sample = np.round(samples).astype(int)
df[f'{letters[group]}'] = sample
return df2 Overview of the Underlying Code
2.1 Generating the Core Dataset for Each Problem
The core of each problem is managed in the RandomData class which takes three initial arguments:
- groups: integer value to specify the number of columns in the dataframe. defaults to
groups = 1 - n: integer value to define the nubmer of rows in the data frame. Also the number of scores in each condition. defaults to
n = 10 - distribution: written as a placeholder to allow specificaion the distribtuion from which to sample the data. defaults to (and can only handle)
distribution = "normal"
The actual dataframe is generated during class instantiation by calling the generate_data() method without any additional arguments. The full method is displayed below:
The variable letters holds the labels (e.g., A, B, C, …) that are used to define the columns.
The first variables to be defined are the population parameters \(\mu\) and \(\sigma\). The population mean (\(\mu\)) uses random.randint() to select a random integer between 10 and 50. The population standard deviation (\(\sigma\)) multiplies \(\mu\) by a random value between .10 and .30 using random.uniform() to select a \(\sigma\) that is between 10-30% of \(\mu\), rounded to the nearest whole number.
Sampling is based on the logic of null hypothesis significance testing (NHST). The null hypothesis (\(H_0\)) states that the independent variable (IV) has no effect on the (DV). If we have a treatatment (tx) and a control condition, then \(\mu_{control} = \mu_{tx}\). If the tx has an effect on the DV then it is assumed to add a constant to every score. Thus, \(\mu_{tx} = \mu_{control} + \text{effect of tx}\).
Samples are generated within a for loop. The start of the loop sets the population parameters as the source for the sample. Then a d3 is rolled (random.randint(0,3)) to determine if the sample is drawn from the population distribution or a different distribution. If the roll is 1 or 2 then the sample will be drawn from a new distribution. The size of the effect is randomized to be between 10 and 50% of the mean value, rounded to the nearest whole number, and then the new mean (e.g., \(\mu_A\)) is set as \(\mu\) + the effect.
Then \(n\) samples are pulled from a normal distribution with the defined parameters with each data point rounded to the nearest whole number.
2.2 Generating the Question
The generate_question() sets the question text based on…
the alpha level (\(\alpha\)) is set by calling the set_alpha() method and uses random.choice() to select one of two options: \(\alpha = 0.05\) or \(\alpha = 0.01\)
def set_alpha(self):
self.alpha = random.choice([0.05, 0.01])For tests where either one- or two-tailed tests are possilbe (z-scores and one-sample t-tests), this is set within the critical_value() method. The relevant section is displayed below. A d5 is rolled and a one-tailed test is selected if the result is 0, else a two-tailed test is used. This method sets a 20% probability of a one-tailed test and 80% for a two-tailed test
def critical_value(self):
roll = random.randint(0, 5)
self.tails = 1 if roll == 0 else 2
# the rest of the method is not displayed hereTBD - describe
def critical_value(self):
# ...
# excerpt
if self.test in ["one-way ANOVA", "repeated-measures ANOVA"]:
self.crit_values["direction"] = "increase"
else:
if self.tails == 1:
direction = random.choice(["increase", "decrease"])
self.crit_values["direction"] = direction
else:
return ValueError("tails must be 1 for directional crit values")
# end excerptthe value for the null \(H_0\) is set using the set_null_hypothesis() method (see below). For z-scores and one-sample t-tests, the null is set as the population mean \(\mu\). For all other tests, it is set to be 0.
def set_null_hypothesis(self):
if self.test in ["z", "one-sample t-test"]:
self.null = self.pop_mean
else:
self.null = 0