pandas 如何根据平均值、中位数、第1和第9个十分位值生成数据集?

q35jwt9p  于 2023-02-02  发布在  其他
关注(0)|答案(2)|浏览(155)

我有以下描述数据集的值:

Number of Samples: 5388
Mean: 4173
Median: 4072
1st Decile: 2720
9th Decile: 5676

我需要生成任何数据集,将适合这些值。所有的例子,我发现需要你有标准差,我没有。如何才能做到这一点?谢谢!

zkure5ic

zkure5ic1#

有趣的问题!根据斯科特的建议,我很快地试了一下。
输入:

import random
import pandas as pd
import numpy as np

# fixing the random seed
random.seed(a=1, version=2)
# formating floats
pd.options.display.float_format = '{:.1f}'.format

# given inputs
count = 5388
mean = 4173
median = 4072

lower_percentile = 10
lower_percentile_value = 2720

upper_percentile = 90
upper_percentile_value = 5676

max_value = 6325
min_value = 2101

职能部门:

def generate_dataset(count, mean, median, lower_percentile, upper_percentile,
    lower_percentile_value, upper_percentile_value,
    min_value, max_value
    ):
        
    # Calculate the number of values that fall within each percentile
    p_1_size = int(float(lower_percentile) * float(count) / 100)
    p_4_size = int(count - (float(upper_percentile) * float(count) / 100))
    p_2_size = int((count / 2) - p_1_size)
    p_3_size = int((count / 2) - p_4_size)
    
    # can be used to adjust the mean
    mean_adjuster = 5790

    # randomly pick values of right size from a range 
    p_1 = random.choices(range(min_value, lower_percentile_value), k=p_1_size)
    p_2 = random.choices(range(lower_percentile_value, median), k=p_2_size)
    p_3 = random.choices(range(median, mean_adjuster), k=p_3_size)
    p_4 = random.choices(range(upper_percentile_value, max_value), k=p_4_size)
    
    return p_1 + p_2 + p_3 + p_4
    
dataset = generate_dataset(
    count, mean, median, lower_percentile, upper_percentile,
    lower_percentile_value, upper_percentile_value, min_value, max_value
    )

对比:

# converting into DataFrame
df = pd.DataFrame({"x": dataset})

new_count = len(df)
new_mean = np.mean(df.x)
new_median = np.quantile(df.x, 0.5)
new_lower_percentile = np.quantile(df.x, lower_percentile/100)
new_upper_percentile = np.quantile(df.x, upper_percentile/100)

compare = pd.DataFrame(
    {
        "value": ["count", "mean", "median", "low_p", "high_p"],
        "original": [count, mean, median, lower_percentile_value, upper_percentile_value],
        "new":[new_count, new_mean, new_median, new_lower_percentile, new_upper_percentile]
    }
)

print(compare)
    • 输出:**
value  original    new
0   count      5388 5388.0
1    mean      4173 4173.4
2  median      4072 4072.5
3   low_p      2720 2720.4
4  high_p      5676 5743.0

当所有的值都是整数而不是浮点数时,让这些值完全相等有点棘手。
您可以添加另一个变量来控制两个数字的平均值,或者更改随机种子,看看是否可以获得更接近的值。或者,您可以编写一个函数来更改种子,直到值相等。(可能需要几分钟或几个世纪:)
干杯!

n6lpvg4x

n6lpvg4x2#

中位数固定了第5388/2 ~ 2694和5388/2 + 1 ~ 2695个值(中间值)。因此,我们将它们都设为4072。第1个和第9个十分位数固定5388/10 ~ 538.8和95388/10 ~ 4849.2的值。十分位数有多种流行的公式,但将第538和第539个值都设置为2720是安全的。同样,我们可以通过将第4849和第4850个值固定为5676来获得正确的第9个十分位数。平均值提供的自由度少了一个,但计算平均值涉及整个数据集的实际值,因此我们将推迟到以后。首先,我们需要做的是使537个值小于2719。(几乎)如何设置无所谓,但最好将它们设置得非常低(将在后面解释)。然后,我们需要拨打2693-539(固定的第一个十分位数和固定的中值之间的值的数量)值在2720之间(第一个十分位数)和4072(中位数)。然后在4072和5676之间创建4848-2695个值。现在我们需要5388-4850(值的总数减去第9个十分位数和更低值)值大于5676,但请记住,我们还需要设置平均值。实际上,有无数种方法可以实现这一点,但其中一种方法是简单地使第9个十分位数以上的所有值相同。为此,我们可以计算较低的4850个值的平均值(我们已经有了),并意识到(5388 - 4850) X + 4850 * M = 4173,其中M是较低的4850个值的平均值。求解X以获得所需的值。由于X * 必须 * 大于5676,如果将第一个十分位数以下的值设置为较小值,则会很有帮助,因为这会给我们留出一些余地。另一种方法是为除一个值之外的所有值选择5676以上的随机数,然后选择最后一个值,以固定平均值(同样,明智的做法是选取不超过5676太多的随机值,因为可以使最后剩余的值任意大,以将平均值拖到正确的值)。
在任何情况下,在numpy中,您只需要生成一堆随机数。np.random.randint应该可以完成这项工作。

相关问题