Рандомизировать значения в столбце DataFrame - PullRequest
1 голос
/ 04 ноября 2019

У меня есть датафрейм (df) и переменная, содержащая номер группы. Каждое наблюдение имеет номер группы от 1 до 80. Я хотел бы создать новую переменную под названием new_group, содержащую новые случайные числа от 1 до 80 для каждого наблюдения. Однако эти новые номера групп должны соответствовать исходным номерам групп в том смысле, что если бы 2 наблюдения были в группе 1, оба наблюдения должны иметь один и тот же новый случайный номер группы.

Пример:

observation    group   random_group
0                1         4
1                2         3
2                1         4
3                43        1
4                1         4
5                21        80
6                43        1

Я использую Python 3.7. Я попробовал следующее: 1. Я создал словарь с ключами от 1 до 80 и значениями от 1 до 80, но в другом случайном порядке. Идея состоит в том, чтобы использовать этот словарь для сопоставления типа "vlookup" в Excel.

Я создал новый фрейм данных с 2 столбцами: один столбец со значениями от 1 до 80, а другой столбец с числами от 1 до 80, но в другом случайном порядке. Идея состояла бы в том, чтобы объединить оригинальный фрейм данных с новым.

Вот что я сделал:

import random
ordered_group = list(range(1,81))
random_group = random.sample(range(1, 81), 80)
group_dict = dict(zip(ordered_group ,random_group))

df['new_group'] = df.group.map(group_dict)

В столбце new_group есть только nan

Я также пробовал это вместо последней строки:

df['new_group'] = df["group"].apply(lambda x: group_dict .get(x))

Теперь он правильно отображает все 80 групп один раз, но не проходит все наблюдения.

Я также пытался использовать merge вместо map

import random
random_group= list(range(1,81))
random_group= pd.DataFrame(random_group)
random_group['new_group'] = random.sample(range(1, 81), 80)
random_group.rename(columns={0:'group'},inplace=True )


df= df.merge(random_group, on = 'group', how = 'outer')

Этоправильно отображает все 80 групп один раз, но он не проходит через все наблюдения

Итак, я получаю что-то вроде этого:

observation    group   random_group
0                1         4
1                2         3
2                1         nan
3                43        1
4                1         nan
5                21        80
6                43        nan

Мои два метода, кажется, работают хорошо, но они не проходят черезвесь кадр данных. Есть идеи, где я ошибся? Также приветствуется любой более эффективный метод

Спасибо!

Ответы [ 2 ]

3 голосов
/ 04 ноября 2019

Сохраните случайное отображение в dict, а затем map. В этом случае случайная группа колеблется от 1 до 4, потому что у вас есть только 4 уникальные группы. В ваших реальных данных это будет 1-80, если у вас есть 80 групп.

import numpy as np

grps = df.group.unique()
N = df.group.nunique()

d = dict(zip(np.random.choice(grps, N, replace=False), range(1, N+1)))
#{1: 3, 2: 2, 21: 4, 43: 1}

df['random_group'] = df['group'].map(d)
#   observation  group  random_group
#0            0      1             3
#1            1      2             2
#2            2      1             3
#3            3     43             1
#4            4      1             3
#5            5     21             4
#6            6     43             1
0 голосов
/ 04 ноября 2019

Я каждый раз генерировал случайную группу и проверял, была ли исходная группа уже назначена в новой группе или нет. Кажется, это работает для меня:

import pandas as pd
import random
data=pd.read_csv('file.csv')
processed_group=[]
for obs in data['observation']:
   x = int(random.randrange(1,80))
   if data.loc[obs,'group'] not in processed_group:
       data.loc[obs,'new_group']=x
       processed_group.append(data.loc[obs,'group'])
   elif data.loc[obs,'group'] in processed_group:
       index = data.index[data['group']== data.loc[obs,'group']].tolist()
       data.loc[obs,'new_group'] = data.loc[index[0],'new_group']
...