首页 > 解决方案 > 用不同的值填充 DataFrame 的一列的每一行(随机分布)

问题描述

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

df['minutes'] = np.nan 

然后,我想用随机逆对数正常值填充这个新列的每一行。生成 1 个逆对数 normal 的代码

注意:如果下面的代码运行多次,由于里面的值,它会生成一个新的结果ppf()random.random()

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

当我这样做时发生的事情是它用相同的 number填充所有 200 行df['minutes'],而不是像我预期的那样触发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))

我究竟做错了什么?

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

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))

提前致谢。

标签: pythonpandasnumpypandas-apply

解决方案


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

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

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

您可以apply仅在minutes带有 lambda 函数的 -column (作为 pandas.Series 方法)上使用,然后将相应的结果分配给typecolumn 的 -column 过滤行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 方法,以区分 -column 的值type并将结果分配回minutes-column:

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)

推荐阅读