如何生成可以求和为特定值的随机数?
how to generate random numbers that can be summed to a specific value?
我有 2 个数据框如下:
import pandas as pd
import numpy as np
# Create data set.
dataSet1 = {'id': ['A', 'B', 'C'],
'value' : [9,20,20]}
dataSet2 = {'id' : ['A', 'A','A','B','B','B','C'],
'id_2': [1, 2, 3, 2,3,4,1]}
# Create dataframe with data set and named columns.
df_map1 = pd.DataFrame(dataSet1, columns= ['id', 'value'])
df_map2 = pd.DataFrame(dataSet2, columns= ['id','id_2'])
df_map1
id value
0 A 9
1 B 20
2 C 20
df_map2
id id_2
0 A 1
1 A 2
2 A 3
3 B 2
4 B 3
5 B 4
6 C 1
其中 id_2 可以有重复的 id。 (即 id_2 是 id 的子集)
#doing a quick merge, based on id.
df = df_map1.merge(df_map2 ,on=['id'])
id value id_2
0 A 9 1
1 A 9 2
2 A 9 3
3 B 20 2
4 B 20 3
5 B 20 4
6 C 20 1
我可以表示id和id_2的关系如下
id_ref = df.groupby('id')['id_2'].apply(list).to_dict()
{'A': [1, 2, 3], 'B': [2, 3, 4], 'C': [1]}
现在,我想生成随机整数,比如 0 到 3 将列表(例如 5 个元素)放入 pandas df 并展开。
import numpy as np
import random
df['random_value'] = df.apply(lambda _: np.random.randint(0,3, 5), axis=1)
id value id_2 random_value
0 A 9 1 [0, 0, 0, 0, 1]
1 A 9 2 [0, 2, 1, 2, 1]
2 A 9 3 [0, 1, 2, 2, 1]
3 B 20 2 [2, 1, 1, 2, 2]
4 B 20 3 [0, 0, 0, 0, 0]
5 B 20 4 [1, 0, 0, 1, 0]
6 C 20 1 [1, 2, 2, 2, 1]
生成此 random_value 列表的条件是列表的总和必须等于 9。
这意味着,对于 id : A,如果我们将列表中的所有元素相加,我们总共有 13 个,如下所述,但我们想要的是 9:
id B 和 C 的相同概念......等等....
有没有办法实现这个?
# i was looking into multinomial from np.random function... seems this should be the solution but im not sure how to apply this with pandas.
np.random.multinomial(9, np.ones(5)/5, size = 1)[0]
=> array([2,3,3,0,1])
2+3+3+0+1 = 9
ATTEMPT/IDEA ...
鉴于我们有 id_2 的列表。 ie) id: A 有 3 个不同的元素 [1,2,3].
所以 id A 被映射到 3 个不同的元素。所以我们可以得到
3 * 5 = 15(这将是我们的长列表)
3: 列表长度
5: 创建列表的 5 个元素
因此
list_A = np.random.multinomial(9,np.ones(3*5)/(3*5) ,size = 1)[0]
然后我们均匀 distribute/split 列表。
使用此列表理解:
[list_A [i:i + n] for i in range(0, len(list_A ), n)]
但我仍然不确定如何动态执行此操作。
核心思想如您所说(关于获得 3*5=15 个数字),再加上将其重塑为一个二维数组,其行数与 id
在数据框中的行数相同。下面的函数就是这样做的,
def generate_random_numbers(df):
value = df['value'].iloc[0]
list_len = 5
num_rows = len(df)
num_rand = list_len*num_rows
return pd.Series(
map(list, np.random.multinomial(value, np.ones(num_rand)/num_rand).reshape(num_rows, -1)),
df.index
)
并应用它:
df['random_value'] = df.groupby(['id', 'value'], as_index=False).apply(generate_random_numbers).droplevel(0)
我有 2 个数据框如下:
import pandas as pd
import numpy as np
# Create data set.
dataSet1 = {'id': ['A', 'B', 'C'],
'value' : [9,20,20]}
dataSet2 = {'id' : ['A', 'A','A','B','B','B','C'],
'id_2': [1, 2, 3, 2,3,4,1]}
# Create dataframe with data set and named columns.
df_map1 = pd.DataFrame(dataSet1, columns= ['id', 'value'])
df_map2 = pd.DataFrame(dataSet2, columns= ['id','id_2'])
df_map1
id value
0 A 9
1 B 20
2 C 20
df_map2
id id_2
0 A 1
1 A 2
2 A 3
3 B 2
4 B 3
5 B 4
6 C 1
其中 id_2 可以有重复的 id。 (即 id_2 是 id 的子集)
#doing a quick merge, based on id.
df = df_map1.merge(df_map2 ,on=['id'])
id value id_2
0 A 9 1
1 A 9 2
2 A 9 3
3 B 20 2
4 B 20 3
5 B 20 4
6 C 20 1
我可以表示id和id_2的关系如下
id_ref = df.groupby('id')['id_2'].apply(list).to_dict()
{'A': [1, 2, 3], 'B': [2, 3, 4], 'C': [1]}
现在,我想生成随机整数,比如 0 到 3 将列表(例如 5 个元素)放入 pandas df 并展开。
import numpy as np
import random
df['random_value'] = df.apply(lambda _: np.random.randint(0,3, 5), axis=1)
id value id_2 random_value
0 A 9 1 [0, 0, 0, 0, 1]
1 A 9 2 [0, 2, 1, 2, 1]
2 A 9 3 [0, 1, 2, 2, 1]
3 B 20 2 [2, 1, 1, 2, 2]
4 B 20 3 [0, 0, 0, 0, 0]
5 B 20 4 [1, 0, 0, 1, 0]
6 C 20 1 [1, 2, 2, 2, 1]
生成此 random_value 列表的条件是列表的总和必须等于 9。
这意味着,对于 id : A,如果我们将列表中的所有元素相加,我们总共有 13 个,如下所述,但我们想要的是 9:
id B 和 C 的相同概念......等等....
有没有办法实现这个?
# i was looking into multinomial from np.random function... seems this should be the solution but im not sure how to apply this with pandas.
np.random.multinomial(9, np.ones(5)/5, size = 1)[0]
=> array([2,3,3,0,1])
2+3+3+0+1 = 9
ATTEMPT/IDEA ...
鉴于我们有 id_2 的列表。 ie) id: A 有 3 个不同的元素 [1,2,3].
所以 id A 被映射到 3 个不同的元素。所以我们可以得到
3 * 5 = 15(这将是我们的长列表)
3: 列表长度
5: 创建列表的 5 个元素
因此
list_A = np.random.multinomial(9,np.ones(3*5)/(3*5) ,size = 1)[0]
然后我们均匀 distribute/split 列表。 使用此列表理解:
[list_A [i:i + n] for i in range(0, len(list_A ), n)]
但我仍然不确定如何动态执行此操作。
核心思想如您所说(关于获得 3*5=15 个数字),再加上将其重塑为一个二维数组,其行数与 id
在数据框中的行数相同。下面的函数就是这样做的,
def generate_random_numbers(df):
value = df['value'].iloc[0]
list_len = 5
num_rows = len(df)
num_rand = list_len*num_rows
return pd.Series(
map(list, np.random.multinomial(value, np.ones(num_rand)/num_rand).reshape(num_rows, -1)),
df.index
)
并应用它:
df['random_value'] = df.groupby(['id', 'value'], as_index=False).apply(generate_random_numbers).droplevel(0)