使用随机数为每行填充一个总数的pandas列

4

我有一个类似这样的pandas数据框:

     id  foo  
 0   A   col1 
 1   A   col2  
 2   B   col1  
 3   B   col3  
 4   D   col4  
 5   C   col2  

我想基于 foo 列中的唯一值创建四个额外列。新列名分别为col1col2col3col4

     id  foo   col1 col2 col3 col4
 0   A   col1   75   20   5    0
 1   A   col2   20   80   0    0
 2   B   col1   82   10   8    0
 3   B   col3   5    4   80   11
 4   D   col4   0    5   10   85
 5   C   col2   12   78   5    5

创建列的逻辑如下:
如果 foo = col1,则 col1 包含在 75-100 之间的随机数,其他列 (col2, col3, col4) 包含随机数,以便每行的总和为 100
我可以手动创建一个新列并分配一个随机数,但我不确定如何包含每行总和为 100 的逻辑。
感谢任何帮助!
4个回答

3

我的建议

d=[]
s=np.random.randint(75,100,size=6)

for x in 100-s:
    a=np.random.randint(100, size=3)
    b=np.random.multinomial(x, a /a.sum())
    d.append(b.tolist())
s=[np.random.choice(x,4,replace= False) for x in np.column_stack((s,np.array(d))) ]


df=pd.concat([df,pd.DataFrame(s,index=df.index)],1)
df

  id   foo   0   1   2   3
0  A  col1  16   1   7  76
1  A  col2   4   2  91   3
2  B  col1   4   4   1  91
3  B  col3  78   8   8   6
4  D  col4   8  87   3   2
5  C  col2   2   0  11  87

2

IIUC,

df['col1'] = df.apply(lambda x: np.where(x['foo'] == 'col1', np.random.randint(75,100), np.random.randint(0,100)), axis=1)

df['col2'] = df.apply(lambda x: np.random.randint(0,100-x['col1'],1)[0], axis=1)

df['col3'] = df.apply(lambda x: np.random.randint(0,100-x[['col1','col2']].sum(),1)[0], axis=1)

df['col4'] = 100 - df[['col1','col2','col3']].sum(1).astype(int)

df[['col1','col2','col3','col4']].sum(1)

输出:

  id   foo col1  col2  col3  col4
0  A  col1   92     2     5     1
1  A  col2   60    30     0    10
2  B  col1   89     7     3     1
3  B  col3   72    12     0    16
4  D  col4   41    52     3     4
5  C  col2   72     2    22     4

2

我的方法

最初的回答
import numpy as np

def weird(lower, upper, k, col, cols):
    first_num = np.random.randint(lower, upper)
    delta = upper - first_num
    the_rest = np.random.rand(k - 1)
    the_rest = the_rest / the_rest.sum() * (delta)
    the_rest = the_rest.astype(int)
    the_rest[-1] = delta - the_rest[:-1].sum()

    key = lambda x: x != col
    return dict(zip(sorted(cols, key=key), [first_num, *the_rest]))


def f(c): return weird(75, 100, 4, c, ['col1', 'col2', 'col3', 'col4'])

df.join(pd.DataFrame([*map(f, df.foo)]))

  id   foo  col1  col2  col3  col4
0  A  col1    76     2    21     1
1  A  col2    11    76    11     2
2  B  col1    75     4    10    11
3  B  col3     0     1    97     2
4  D  col4     5     4    13    78
5  C  col2     9    77     6     8

0
如果我们将 75-100 之间的数字减去 75,问题就变成了生成一个随机数表格,其中每一行的和为 25,范围在 0-25 之间。这可以通过反向 cumsum 来解决:
num_cols = 4

# generate random number and sort them in each row
a = np.sort(np.random.randint(0,25, (len(df), num_cols)), axis=1)

# create a dataframe and attach a last column with values 25
new_df = pd.DataFrame(a)
new_df[num_cols] = 25

# compute the difference, which are our numbers and add to the dummies:
dummies = pd.get_dummies(df.foo) * 75
dummies += new_df.diff(axis=1).fillna(new_df[0]).values

而dummies是

   col1  col2  col3  col4
0  76.0  13.0   2.0   9.0
1   1.0  79.0   2.0   4.0
2  76.0   5.0   8.0   9.0
3   1.0   3.0  79.0  10.0
4   1.0   2.0   1.0  88.0
5   1.0  82.0   1.0   7.0

可以将其连接到原始数据框中。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接