Python 按分组并使用随机数据添加新行

Python 按分组并使用随机数据添加新行,python,pandas,dataframe,Python,Pandas,Dataframe,我有一个熊猫数据框,如下所示: id date variable value 1 2019 x 100 1 2019 y 50.5 1 2020 x 10.0 1 2020 y NA 现在,我想按id和date进行分组,并为每组添加3个变量a、b、c,这些变量的随机值为a+b+c=1.0和a>b>c。 因此,我的最终数据帧将如下所示: id date variable value 1 2019 x 100

我有一个熊猫数据框,如下所示:

id date variable value
 1 2019    x      100
 1 2019    y      50.5
 1 2020    x      10.0
 1 2020    y      NA
现在,我想按
id
date
进行分组,并为每组添加3个变量
a
b
c
,这些变量的随机值为
a+b+c=1.0
a>b>c
。 因此,我的最终数据帧将如下所示:

id date variable value
 1 2019    x      100
 1 2019    y      50.5
 1 2019    a      0.49
 1 2019    b      0.315
 1 2019    c      0.195
 1 2020    x      10.0
 1 2020    y      NA
 1 2020    a      0.55
 1 2020    b      0.40
 1 2020    c      0.05
更新 没有循环和附加数据帧是可能的

d = df.groupby(['date','id','variable'])['value'].mean().unstack('variable').reset_index()
x = np.random.random((len(d),3))
x /= x.sum(1)[:,None]
x[:,::-1].sort()
d[['a','b','c']] = pd.DataFrame(x)
pd.melt(d, id_vars=['date','id']).sort_values(['date','id']).reset_index(drop=True)
输出

   date  id variable       value
0  2019   1        x  100.000000
1  2019   1        y   50.500000
2  2019   1        a    0.367699
3  2019   1        b    0.320325
4  2019   1        c    0.311976
5  2020   1        x   10.000000
6  2020   1        y         NaN
7  2020   1        a    0.556441
8  2020   1        b    0.336748
9  2020   1        c    0.106812
   id  date variable       value
0   1  2019        x  100.000000
1   1  2019        y   50.500000
2   1  2019        a    0.378764
3   1  2019        b    0.366415
4   1  2019        c    0.254821
5   1  2020        x   10.000000
6   1  2020        y         NaN
7   1  2020        a    0.427007
8   1  2020        b    0.317555
9   1  2020        c    0.255439

循环求解 不优雅,但有效

gr = df.groupby(['id','date'])
l = []
for i,g in gr:
    d = np.random.random(3)
    d /= d.sum()
    d[::-1].sort()
    ndf = pd.DataFrame({
        'variable': list('abc'),
        'value': d
    })
    ndf['id'] = g['id'].iloc[0]
    ndf['date'] = g['date'].iloc[0]
    l.append(pd.concat([g, ndf], sort=False).reset_index(drop=True))
pd.concat(l).reset_index(drop=True)
输出

   date  id variable       value
0  2019   1        x  100.000000
1  2019   1        y   50.500000
2  2019   1        a    0.367699
3  2019   1        b    0.320325
4  2019   1        c    0.311976
5  2020   1        x   10.000000
6  2020   1        y         NaN
7  2020   1        a    0.556441
8  2020   1        b    0.336748
9  2020   1        c    0.106812
   id  date variable       value
0   1  2019        x  100.000000
1   1  2019        y   50.500000
2   1  2019        a    0.378764
3   1  2019        b    0.366415
4   1  2019        c    0.254821
5   1  2020        x   10.000000
6   1  2020        y         NaN
7   1  2020        a    0.427007
8   1  2020        b    0.317555
9   1  2020        c    0.255439
更新 没有循环和附加数据帧是可能的

d = df.groupby(['date','id','variable'])['value'].mean().unstack('variable').reset_index()
x = np.random.random((len(d),3))
x /= x.sum(1)[:,None]
x[:,::-1].sort()
d[['a','b','c']] = pd.DataFrame(x)
pd.melt(d, id_vars=['date','id']).sort_values(['date','id']).reset_index(drop=True)
输出

   date  id variable       value
0  2019   1        x  100.000000
1  2019   1        y   50.500000
2  2019   1        a    0.367699
3  2019   1        b    0.320325
4  2019   1        c    0.311976
5  2020   1        x   10.000000
6  2020   1        y         NaN
7  2020   1        a    0.556441
8  2020   1        b    0.336748
9  2020   1        c    0.106812
   id  date variable       value
0   1  2019        x  100.000000
1   1  2019        y   50.500000
2   1  2019        a    0.378764
3   1  2019        b    0.366415
4   1  2019        c    0.254821
5   1  2020        x   10.000000
6   1  2020        y         NaN
7   1  2020        a    0.427007
8   1  2020        b    0.317555
9   1  2020        c    0.255439

循环求解 不优雅,但有效

gr = df.groupby(['id','date'])
l = []
for i,g in gr:
    d = np.random.random(3)
    d /= d.sum()
    d[::-1].sort()
    ndf = pd.DataFrame({
        'variable': list('abc'),
        'value': d
    })
    ndf['id'] = g['id'].iloc[0]
    ndf['date'] = g['date'].iloc[0]
    l.append(pd.concat([g, ndf], sort=False).reset_index(drop=True))
pd.concat(l).reset_index(drop=True)
输出

   date  id variable       value
0  2019   1        x  100.000000
1  2019   1        y   50.500000
2  2019   1        a    0.367699
3  2019   1        b    0.320325
4  2019   1        c    0.311976
5  2020   1        x   10.000000
6  2020   1        y         NaN
7  2020   1        a    0.556441
8  2020   1        b    0.336748
9  2020   1        c    0.106812
   id  date variable       value
0   1  2019        x  100.000000
1   1  2019        y   50.500000
2   1  2019        a    0.378764
3   1  2019        b    0.366415
4   1  2019        c    0.254821
5   1  2020        x   10.000000
6   1  2020        y         NaN
7   1  2020        a    0.427007
8   1  2020        b    0.317555
9   1  2020        c    0.255439

你尝试了什么?这3个值是随机选择的?@azro是的,它们是随机选择的。这是为了什么?@RichieV,mikksu生成一些填充数据,这些数据至少遵循某种趋势,用于测试目的。我稍后会收到实际数据。您尝试了什么?3个值是随机选择的?@azro是的,它们是随机选择的。这是为了什么?@RichieV,mikksu生成一些填充数据,至少符合某些趋势,用于测试目的。稍后我将收到实际数据。+1,但是为什么
x[:,::-1].sort()会这样工作?我知道
np.array.sort()
是在适当的位置完成的,但它似乎是在排序后进行切片。。。这在python语法+1中并不明显,但是为什么
x[:,::-1].sort()
会这样工作呢?我知道
np.array.sort()
是在适当的位置完成的,但它似乎是在排序后进行切片。。。这在python语法中并不明显