用不同的值填充 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})
我有一个带有 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})