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

时间:2018-07-25 21:58:10

标签: python pandas numpy pandas-apply

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

df['minutes'] = np.nan 

然后,我想用随机逆对数正态值填充此新列的每一行。 正常生成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))

提前谢谢。

2 个答案:

答案 0 :(得分:0)

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

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

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

您可以将apply仅用于具有lambda函数的minutes列(作为pandas.Series方法),然后将各自的结果分配给经过过滤的typeminutes列的行:

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)

答案 1 :(得分:0)

设法以不同的心态执行一些步骤:

  • 创建了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})