Блокировать рандомизацию с помощью Python?
У меня есть следующая таблица ввода (df):
Произвольно выбранные строки так, чтобы в каждой группе были все блоки (равномерно распределенные).
Что я пробовал до сих пор?
df = df.groupby('blocks').apply(lambda x: x.sample(frac=1,random_state=1234)).reset_index(drop=True)
treatment_groups = [f"A{i}" for i in range(1, n+1)]
df['Groups'] = (df.index // n).map(dict(zip(idx, treatment_groups)))
Это не рандомизируется по столбцу блоков. Как я могу это сделать?
3 ответа
Решение
Давайте попробуем определить функцию для генерации
random
образцы из каждого
block
:
def random_samples(n):
for i in range(1, n+1):
for _, g in df.groupby('Blocks'):
yield g.sample(n=1).assign(Groups=f'A{i}')
sampled = pd.concat(random_samples(4), ignore_index=True)
>>> sampled
ColumnA ColumnB Blocks Groups
0 A 12 1 A1
1 D 76 2 A1
2 I 76 3 A1
3 k 80 4 A1
4 n 67 5 A1
5 C 44 1 A2
6 G 65 2 A2
7 J 231 3 A2
8 l 55 4 A2
9 m 27 5 A2
10 B 32 1 A3
11 G 65 2 A3
12 H 87 3 A3
13 l 55 4 A3
14 m 27 5 A3
15 B 32 1 A4
16 F 123 2 A4
17 I 76 3 A4
18 l 55 4 A4
19 m 27 5 A4
В вашем коде
.sample(frac = 1)
возвращает 100% образцов, то есть все они. Вам нужна версия с
.sample(n=1)
, например, если вам нужна только одна группа, вы бы сделали
df.groupby('Blocks').apply(lambda x: x.sample(n=1, random_state=1234))
получить
ColumnA ColumnB Blocks
Blocks
1 0 A 12 1
2 3 D 76 2
3 7 H 87 3
4 10 k 80 4
5 12 m 27 5
чтобы получить, скажем, 5 групп, которые вы бы использовали
n=5
с
replace=True
(поскольку в некоторых группах меньше 5 элементов), а затем некоторые перегруппировки:
df = df.groupby('Blocks').apply(lambda x: x.sample(n=5, replace = True, random_state=1234)).reset_index(drop = True)
df['Groups'] = 'A' + df.groupby('Blocks').cumcount().astype(str)
df.sort_values('Groups')
производит
ColumnA ColumnB Blocks Groups
-- --------- --------- -------- --------
0 C 44 1 A0
20 o 34 5 A0
5 G 65 2 A0
15 l 55 4 A0
10 J 231 3 A0
1 B 32 1 A1
21 n 67 5 A1
6 G 65 2 A1
16 l 55 4 A1
11 I 76 3 A1
22 m 27 5 A2
17 k 80 4 A2
12 H 87 3 A2
7 F 123 2 A2
2 A 12 1 A2
13 H 87 3 A3
8 E 99 2 A3
18 l 55 4 A3
3 A 12 1 A3
23 m 27 5 A3
14 H 87 3 A4
9 D 76 2 A4
19 k 80 4 A4
4 A 12 1 A4
24 m 27 5 A4
- это действительно не случайно, но будет группироваться по вашему желанию
- порядок исходного фрейма данных будет влиять на порядок, в котором блоки назначаются группе
df = pd.DataFrame({'ColumnA': ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'k', 'l', 'm', 'n', 'o'],
'ColumnB': [12, 32, 44, 76, 99, 123, 65, 87, 76, 231, 80, 55, 27, 67, 34],
'Blocks': [1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5]})
# generate a series that is "A{n}" where "n" is occurrence# of "Block"
sg = df.groupby("Blocks").apply(lambda g: pd.Series([f"A{i+1}"
for i in range(len(g))],name="Group")).explode().reset_index(drop=True)
df.join(sg)