我有一个带有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))
提前谢谢。
答案 0 :(得分:0)
此处使用fillna
的问题在于此函数将值作为参数并将其应用于指定轴上的每个元素。因此,您的统计信息值只计算一次,然后分配到每一行。
您需要的是为轴上的每个元素调用的函数,因此您的参数必须是函数本身,而不是值。这是apply
的工作,它需要一个函数并将其应用于沿轴的元素上。
我直接跳到您的最终要求:
您可以将apply
仅用于具有lambda函数的minutes
列(作为pandas.Series方法),然后将各自的结果分配给经过过滤的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)
答案 1 :(得分:0)
设法以不同的心态执行一些步骤:
已使用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})