Панды заполняют столбец случайными числами с итогом для каждой строки - PullRequest
3 голосов
/ 11 июля 2019

У меня есть такой фрейм данных для панд:

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

Я хотел бы создать четыре дополнительных столбца на основе уникальных значений в столбце foo.col1, col2, col3, col4

     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

Логика создания столбцов следующая:

if foo = col1 then col1 содержит случайное число между 75-100, а другие столбцы (col2, col3, col4) содержат случайные числа, так что сумма для каждой строки составляет 100

.вручную создайте новый столбец и назначьте случайное число, но я не уверен, как включить логику суммы для каждой строки 100.

Оцените любую помощь!

Ответы [ 4 ]

3 голосов
/ 11 июля 2019

Мои два цента

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 голосов
/ 11 июля 2019

Мой подход

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
2 голосов
/ 11 июля 2019

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
0 голосов
/ 11 июля 2019

Если мы вычтем числа между 75-100 на 75, проблема станет в создании таблицы случайных чисел между 0-25, каждая строка которой равна 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

И чайники это

   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

, который можно объединить с исходным фреймом данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...