pandas 中每行的矢量化改组
vectorized shuffling per row in pandas
我想打乱 pandas 数据框的列。
但是,默认方法(样本)以相同的方式随机排列所有列。
如何有效地以不同方式排列每行的列?
import pandas as pd
df = pd.DataFrame({'foo':[1,4,7],'bar':[2,5,8],'baz':[3,6,9],})
display(df)
df.sample(frac=1, axis=1)
当然,基于 apply
的解决方案会起作用 - 但这不会被矢量化,因此速度很慢。
是否有一种快速(理想情况下矢量化)的方式来对每一行进行不同的采样?
快速检查给出了基准:
%%timeit
df.sample(frac=1, axis=1)
# 1000 loops, best of 5: 288 µs per loop
使用 apply
,如您所说,我们得到:
%%timeit
idx = np.random.choice([0, 1, 2], size=(3,), replace=False)
df.apply(lambda x: x.iloc[idx], axis=1)
# 1000 loops, best of 5: 1.47 ms per loop -> ~3700 times slower
我们宁愿使用 iloc
:
%%timeit
idx = np.random.choice([0, 1, 2], size=(3,), replace=False)
df.iloc[:, idx]
# 1000 loops, best of 5: 398 µs per loop -> ~1.4 times slower
如果您可以忍受大约 1.4 倍的速度下降,我认为 iloc
版本可以。
您可以试试这个解决方案:
def shuffle_columns_per_row(df):
arr = df.values
x, y = arr.shape
rows = np.indices((x,y))[0]
cols = [np.random.permutation(y) for _ in range(x)]
return pd.DataFrame(arr[rows, cols], columns=df.columns)
| foo | bar | baz |
|-----|-----|-----|
| 3 | 2 | 1 |
| 5 | 6 | 4 |
| 9 | 7 | 8 |
让我们尝试使用 np.random.rand
和 argsort
生成随机索引
i = np.random.rand(*df.shape).argsort(1)
df.values[:] = np.take_along_axis(df.to_numpy(), i, axis=1)
print(df)
foo bar baz
0 3 1 2
1 4 5 6
2 7 9 8
我想打乱 pandas 数据框的列。 但是,默认方法(样本)以相同的方式随机排列所有列。
如何有效地以不同方式排列每行的列?
import pandas as pd
df = pd.DataFrame({'foo':[1,4,7],'bar':[2,5,8],'baz':[3,6,9],})
display(df)
df.sample(frac=1, axis=1)
当然,基于 apply
的解决方案会起作用 - 但这不会被矢量化,因此速度很慢。
是否有一种快速(理想情况下矢量化)的方式来对每一行进行不同的采样?
快速检查给出了基准:
%%timeit
df.sample(frac=1, axis=1)
# 1000 loops, best of 5: 288 µs per loop
使用 apply
,如您所说,我们得到:
%%timeit
idx = np.random.choice([0, 1, 2], size=(3,), replace=False)
df.apply(lambda x: x.iloc[idx], axis=1)
# 1000 loops, best of 5: 1.47 ms per loop -> ~3700 times slower
我们宁愿使用 iloc
:
%%timeit
idx = np.random.choice([0, 1, 2], size=(3,), replace=False)
df.iloc[:, idx]
# 1000 loops, best of 5: 398 µs per loop -> ~1.4 times slower
如果您可以忍受大约 1.4 倍的速度下降,我认为 iloc
版本可以。
您可以试试这个解决方案:
def shuffle_columns_per_row(df):
arr = df.values
x, y = arr.shape
rows = np.indices((x,y))[0]
cols = [np.random.permutation(y) for _ in range(x)]
return pd.DataFrame(arr[rows, cols], columns=df.columns)
| foo | bar | baz |
|-----|-----|-----|
| 3 | 2 | 1 |
| 5 | 6 | 4 |
| 9 | 7 | 8 |
让我们尝试使用 np.random.rand
和 argsort
生成随机索引
i = np.random.rand(*df.shape).argsort(1)
df.values[:] = np.take_along_axis(df.to_numpy(), i, axis=1)
print(df)
foo bar baz
0 3 1 2
1 4 5 6
2 7 9 8