熊猫中随机增加的列

时间:2019-12-12 18:51:16

标签: pandas dataframe random

我有大约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

我看到有关创建具有随机值的字段的帖子。不过,我没有找到能够解决增加随机值的任何方法。

3 个答案:

答案 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将生成随机数而没有任何防止重复的选项,因此我想出了使用tranformnp.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