我有大约10,000行的数据框。每个记录都包含一个Recordid和一个整数,该整数表示自该RecordID开始以来的天数。例如:
df = pd.DataFrame( {
"RecordID" : ["id1", "id2", "id3", "id4", "id5" , "id1", "id2", "id3", "id4", "id5" ] ,
"number_of_days" : [1,1,1,1,1,2,2,2,2,2]})
df
RecordID number_of_days
0 id1 1
1 id2 1
2 id3 1
3 id4 1
4 id5 1
5 id1 2
6 id2 2
7 id3 2
8 id4 2
9 id5 2
我想添加一列,其中包含1到100之间的随机数。但是我需要为每个ID将随机数比先前的随机值更高。这是我想要得到的一个例子:
RecordID number_of_days random_value
0 id1 1 10
1 id1 2 13
2 id1 3 45
3 id1 4 50
4 id1 5 62
5 id1 6 80
6 id1 7 81
7 id1 8 82
8 id1 9 92
9 id1 10 99
10 id2 2 12
11 id2 4 31
我看到有关创建具有随机值的字段的帖子。不过,我没有找到能够解决增加随机值的任何方法。
答案 0 :(得分:4)
您可以生成随机数,进行排序,然后分配给df,
df = pd.DataFrame( {
"RecordID" : ["id1", "id2", "id3", "id4", "id5" , "id1", "id2", "id3", "id4", "id5" ] ,
"number_of_days" : [1,1,1,1,1,2,2,2,2,2]})
df['random_value'] = np.sort(np.random.randint(1,100, len(df)))
RecordID number_of_days random_value
0 id1 1 5
1 id2 1 7
2 id3 1 19
3 id4 1 34
4 id5 1 45
5 id1 2 53
6 id2 2 67
7 id3 2 72
8 id4 2 72
9 id5 2 80
编辑:如果您希望按组对random_value进行分类,则可以按ID对数据进行分组,然后分配已排序的随机数,
df.groupby('RecordID').apply(lambda x: pd.Series(np.sort(np.random.randint(1,100, len(x))))).reset_index(name = 'random_value')
答案 1 :(得分:1)
生成所有随机数,根据组大小对其进行适当切片,对每个切片进行排序,然后分配回来。首先,我们需要对DataFrame进行排序,以便正确进行分配。
import numpy as np
import pandas as pd
df = df.sort_values('RecordID')
arr = np.array_split(np.random.randint(1, 100, len(df)),
df.groupby('RecordID').size().cumsum()[:-1])
df['Random_Value'] = np.sort(arr, axis=1).ravel()
RecordID number_of_days Random_Value
0 id1 1 19
5 id1 2 41
1 id2 1 53
6 id2 2 56
2 id3 1 33
7 id3 2 68
3 id4 1 57
8 id4 2 67
4 id5 1 39
9 id5 2 49
一如既往,最好避免使用groupby.apply(lambda x: ...
,因为这是整个组的缓慢循环。
N = 10000
df = pd.DataFrame({"RecordID": list(range(N))*10,
"number_of_days": np.repeat(range(10), N)})
def ALollz(df):
df = df.sort_values(['RecordID', 'number_of_days'])
arr = np.array_split(np.random.randint(1, 100, len(df)),
df.groupby('RecordID').size().cumsum()[:-1])
df['Random_Value'] = np.sort(arr, axis=1).ravel()
return df
%timeit ALollz(df)
#54 ms ± 1.64 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit df.assign(random_value=df.groupby('RecordID').transform(lambda x: np.sort(np.random.randint(1,100, len(x))))).sort_values('RecordID')
#15.9 s ± 124 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit df.groupby('RecordID').apply(lambda x: pd.Series(np.sort(np.random.randint(1,100, len(x))))).reset_index()
#1.23 s ± 25.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
答案 2 :(得分:0)
这句话the random to be higher than the previous random value for each ID
使我明白,每个唯一ID
的随机数中不允许有重复项。据我了解,np.random.randint
将生成随机数而没有任何防止重复的选项,因此我想出了使用tranform
和np.random.choice
的解决方案。
np.random.seed(0) #For showing consistent output. Take this line out in production.
s = (df.groupby('RecordID')
.RecordID
.transform(lambda x: np.sort(np.random.choice(np.arange(1,100),
x.shape[0], replace=False))))
Out[262]:
0 3
1 17
2 27
3 55
4 56
5 74
6 76
7 87
8 93
9 95
10 19
11 30
Name: RecordID, dtype: int32
df['random_value'] = s
Out[264]:
RecordID number_of_days random_value
0 id1 1 3
1 id1 2 17
2 id1 3 27
3 id1 4 55
4 id1 5 56
5 id1 6 74
6 id1 7 76
7 id1 8 87
8 id1 9 93
9 id1 10 95
10 id2 2 19
11 id2 4 30