随机化 DataFrame 列中的值

Posted

技术标签:

【中文标题】随机化 DataFrame 列中的值【英文标题】:Randomize values within a DataFrame column 【发布时间】:2020-02-29 21:41:08 【问题描述】:

我有一个数据框 (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,但顺序不同。这个想法是使用这个字典来做一个 Excel“vlookup”类型的匹配。

    我创建了一个包含 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

我的两种方法似乎效果很好,但它们并没有遍历整个数据框。知道我哪里出错了吗?另外,欢迎任何更有效的方法

谢谢!

【问题讨论】:

【参考方案1】:

将随机映射存储在dict 然后map。在这种情况下,随机组的范围为 1-4,因为您只有 4 个唯一组。在您的真实数据中,如果您有 80 个组,这将是 1-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

【讨论】:

工作出色,谢谢!但我似乎无法理解为什么我的字典和地图的使用导致了 nan。 @JulienSalé 我也不清楚。您应该查看df.group.unique() 的输出。我的猜测是你可能遇到字符串和整数的问题。因此,也许您的专栏中有 1'1' 表示。我认为您应该将该列转换为int,然后我认为您的原始方法会起作用。我的工作是因为它使用group 的真实值,但还要检查上面的N 是什么。如果您有多个 strint 表示同一组,则 N 将成为 > 80 并且映射可能无法按您的意愿工作。【参考方案2】:

我所做的是每次生成随机组并检查原始组是否已分配到新组中。 这似乎对我有用:

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']

【讨论】:

以上是关于随机化 DataFrame 列中的值的主要内容,如果未能解决你的问题,请参考以下文章

随机化快速排序法

systemverilog中的随机化方法

临床试验随机化分组及其SAS实现-分层随机化

[HAOI2007]理想的正方形(随机化,骗分?)

随机化 Firebase 存储中的图像

pandas 轴索引的重命名,离散化,异常值的处理与随机方法