2016-10-24 3 views

ответ

8

Вы можете использовать numpy.random.choice для генерации mask:

import numpy as np 

mask = np.random.choice([True, False], size=df.shape, p=[.2,.8]) 

df.mask(mask) 

В одной строке:

df.mask(np.random.choice([True, False], size=df.shape, p=[.2,.8])) 

Протестировано с использованием timeit при ~ 770μs:

>>> python -m timeit -n 10000 
     -s "import pandas as pd;import numpy as np;df=pd.DataFrame(np.ones((10,10))*2)" 
     "df.mask(np.random.choice([True,False], size=df.shape, p=[.2,.8]))" 
10000 loops, best of 3: 770 usec per loop 
+2

Мне нравится это лучше, чем мой ответ. Чтобы сделать его более общим, вы можете использовать 'size = df.shape' вместо жесткого кодирования. – root

+0

Спасибо @root! Добавлено в ответ. – ASGM

+0

Я изначально толкал что-то очень похожее. Это гораздо более элегантный ответ. Я бы сказал, что на один шаг дальше, не намного лучше, но каждый бит помогает. используйте 'df.values.shape' – piRSquared

4

Вы можете использовать stack и unstack с sample, где фракцией вы хотите попробовать это доля ненулевых значений, которые вы хотите в результате кадра (то есть один минус доли нулевых значений).

df = df.stack().sample(frac=0.8).unstack() 

Полученный выход:

 A B C D E F G H I J 
a 2.0 2.0 2.0 2.0 2.0 NaN NaN 2.0 2.0 2.0 
b 2.0 NaN 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 
c 2.0 NaN NaN 2.0 2.0 2.0 NaN 2.0 2.0 2.0 
d 2.0 2.0 2.0 2.0 2.0 NaN 2.0 2.0 2.0 2.0 
e 2.0 2.0 2.0 2.0 2.0 NaN 2.0 NaN 2.0 NaN 
f 2.0 2.0 NaN NaN 2.0 NaN 2.0 2.0 2.0 2.0 
g 2.0 2.0 NaN 2.0 NaN 2.0 2.0 2.0 2.0 2.0 
h 2.0 2.0 2.0 2.0 2.0 2.0 2.0 NaN NaN 2.0 
i NaN 2.0 2.0 2.0 2.0 2.0 NaN 2.0 2.0 2.0 
j 2.0 2.0 2.0 2.0 NaN 2.0 2.0 2.0 2.0 2.0 

EDIT:

В зависимости от того, насколько мал ваш образец, описанный выше метод может привести к потере строк/столбцов, если они становятся все NaN. Если это нежелательно, то обходной путь будет добавить reindex в конце:

df = df.stack().sample(frac=0.8).unstack().reindex(index=df.index, columns=df.columns) 
Смежные вопросы