用不同的值填充 DataFrame 的一列的每一行(随机分布)

Filling each row of one column of a DataFrame with different values (a random distribution)

我有一个带有 aprox 的 DataFrame。 4 列和 200 行。我创建了具有空值的第 5 列:

df['minutes'] = np.nan 

然后,我想用 运行dom 逆对数正态值填充这个新列的每一行。 生成1个反对数正态的代码:

注意:如果下面的代码是 运行 多次,它将生成一个新的结果,因为 ppf() 中的值:random.random()

df['minutes'] = df['minutes'].fillna(stats.lognorm(0.5, scale=np.exp(1.8)).ppf(random.random()).astype(int))

当我这样做时发生的事情是 用相同的数字 填充 df['minutes'] 的所有 200 行,而不是为每个触发 random.random()正如我预期的那样。

我需要做什么?我尝试使用 for loop,但显然我没有得到正确的结果(给出相​​同的结果):

for i in range(1,len(df)):
df['minutes'] = df['minutes'].fillna(stats.lognorm(0.5, scale=np.exp(1.8)).ppf(random.random()).astype(int))

我做错了什么?

此外,如果另一列的值为 0 或 1,稍后我将需要更改上面 inverse log normal 的一些参数。如:

if df['type'] == 0:
     df['minutes'] = df['minutes'].fillna(stats.lognorm(0.5, scale=np.exp(1.8)).ppf(random.random()).astype(int))
elif df['type'] == 1:
     df['minutes'] = df['minutes'].fillna(stats.lognorm(1.2, scale=np.exp(2.7)).ppf(random.random()).astype(int))

提前致谢。

您在此处使用 fillna 的问题是此函数将 value 作为参数并将其应用于指定轴上的每个元素。所以你的统计值被计算一次然后分配到每一行。

你需要的是为轴上的每个元素调用你的函数,所以你的参数必须是函数本身而不是值。这是 apply 的工作,它接受一个函数并将其应用于沿轴的元素。

我直接跳到您的最终要求:

您可以仅在 minutes 列(作为 pandas.Series 方法)上使用带有 lambda 函数的 apply,然后将相应的结果分配给 type-列筛选行 minutes:

import numpy as np
import pandas as pd
import scipy.stats as stats
import random

# setup
df = pd.DataFrame(np.random.randint(0, 2, size=(8, 4)),
                  columns=list('ABC') + ['type'])
df['minutes'] = np.nan


df.loc[df.type == 0, 'minutes'] = \
    df['minutes'].apply(lambda _: stats.lognorm(
        0.5, scale=np.exp(1.8)).ppf(random.random()).astype(int),
                    convert_dtype=False))

df.loc[df.type == 1, 'minutes'] = \
    df['minutes'].apply(lambda _: stats.lognorm(
        1.2, scale=np.exp(2.7)).ppf(random.random()).astype(int),
                    convert_dtype=False))

... 或者您将 apply 用作 DataFrame 方法,并使用包装逻辑的函数来区分 type 列的值并将结果分配回 minutes -列:

def calc_minutes(row):
    if row['type'] == 0:
        return stats.lognorm(0.5, scale=np.exp(1.8)).ppf(random.random()).astype(int)
    elif row['type'] == 1:
        return stats.lognorm(1.2, scale=np.exp(2.7)).ppf(random.random()).astype(int)

df['minutes'] = df.apply(calc_minutes, axis=1)

设法以不同的心态完成一些步骤:

  • 创建了 2 个列表,每个列表都有我自己的参数
  • 二手NumPy's append 这样每一行都有一个不同的随机数

     lognormal_tone = []
     lognormal_ttwo = []
     for i in range(len(s)):
         lognormal_tone.append(stats.lognorm(0.5, scale=np.exp(1.8)).ppf(random.random()).astype(int))
         lognormal_ttwo.append(stats.lognorm(0.4, scale=np.exp(2.7)).ppf(random.random()).astype(int))
    

然后,将它们与之前创建的另一个列表一起包含在 DataFrame 中:

df = pd.DataFrame({'arrival':arrival,'minTypeOne':lognormal_tone, 'minTypeTwo':lognormal_two})