在没有元素出现在其原始位置(紊乱)的情况下随机播放数据帧值
Shuffle dataframe values on condition that no element appears in its original position (derangement)
Python3.10/Pandas1.1.3
鉴于此代码:
import pandas as pd
data = {'a': ['AA','BB','CC','DD', 'EE', 'FF', 'GG'],
'b': [11, 22, 33, 44, 55, 66, 77],
}
df = pd.DataFrame(data, columns=['a','b'])
df.a
print (df)
产生:
a b
0 AA 11
1 BB 22
2 CC 33
3 DD 44
4 EE 55
5 FF 66
6 GG 77
我需要了解如何打乱列 b
的值,条件是生成的数据帧不允许任何 b
值与其原始值相关联 a
值。
使用以下函数找到重新映射列的方法:
def derange(x):
res = x
while np.any(res == x):
res = np.random.permutation(x)
return res
然后将它应用到任意列:
df['b'] = derange(df['b'])
该方法是生成排列,直到一个排列足够好为止。预期的尝试次数是 (n/(n-1))^n
,很快就会收敛到 e
。
请注意,对于 n=1
,期望实际上趋于无穷大,这是有道理的,因为您不能对这样的列表进行排序。
也可以确定性地执行紊乱,因此为了完整起见,这里是:
def derange2(x):
n = len(x)
for i in range(n - 1):
j = random.randrange(i + 1, n)
x[i], x[j] = x[j], x[i]
此函数实际上就地转换列表。
您还可以有一个版本可以就地修改 pandas
列:
def derange3(df, col):
n = df.shape[0]
for i in range(n - 1):
j = random.randrange(i + 1, n)
df.iat[i, col], df.iat[j, col] = df.iat[j, col], df.iat[i, col]
让我们用numpy
def rnd(l):
l1 = l.copy()
while True:
np.random.shuffle(l1)
if any(l == l1):
break
else:
return l1
df.b = rnd(df.b.values)
您可以打乱索引,直到它不再与原始索引匹配,然后使用新打乱的索引对 df['b']
进行排序,并将这个新数组分配回 df['b']
:
idx = df.index.tolist()
while (idx == df.index).any():
np.random.shuffle(idx)
df['b'] = df['b'][idx].values
Python3.10/Pandas1.1.3
鉴于此代码:
import pandas as pd
data = {'a': ['AA','BB','CC','DD', 'EE', 'FF', 'GG'],
'b': [11, 22, 33, 44, 55, 66, 77],
}
df = pd.DataFrame(data, columns=['a','b'])
df.a
print (df)
产生:
a b
0 AA 11
1 BB 22
2 CC 33
3 DD 44
4 EE 55
5 FF 66
6 GG 77
我需要了解如何打乱列 b
的值,条件是生成的数据帧不允许任何 b
值与其原始值相关联 a
值。
使用以下函数找到重新映射列的方法:
def derange(x):
res = x
while np.any(res == x):
res = np.random.permutation(x)
return res
然后将它应用到任意列:
df['b'] = derange(df['b'])
该方法是生成排列,直到一个排列足够好为止。预期的尝试次数是 (n/(n-1))^n
,很快就会收敛到 e
。
请注意,对于 n=1
,期望实际上趋于无穷大,这是有道理的,因为您不能对这样的列表进行排序。
也可以确定性地执行紊乱,因此为了完整起见,这里是:
def derange2(x):
n = len(x)
for i in range(n - 1):
j = random.randrange(i + 1, n)
x[i], x[j] = x[j], x[i]
此函数实际上就地转换列表。
您还可以有一个版本可以就地修改 pandas
列:
def derange3(df, col):
n = df.shape[0]
for i in range(n - 1):
j = random.randrange(i + 1, n)
df.iat[i, col], df.iat[j, col] = df.iat[j, col], df.iat[i, col]
让我们用numpy
def rnd(l):
l1 = l.copy()
while True:
np.random.shuffle(l1)
if any(l == l1):
break
else:
return l1
df.b = rnd(df.b.values)
您可以打乱索引,直到它不再与原始索引匹配,然后使用新打乱的索引对 df['b']
进行排序,并将这个新数组分配回 df['b']
:
idx = df.index.tolist()
while (idx == df.index).any():
np.random.shuffle(idx)
df['b'] = df['b'][idx].values