我有一个值列表,我希望以这样的方式选择n
值,大多数元素都来自列表的开头,随着它在列表中的进一步减少(如图所示)下方链接)。
np.random.seed(0)
a = pd.Series(range(100))
np.random.shuffle(a)
a.values
array([26, 86, 2, 55, 75, 93, 16, 73, 54, 95, 53, 92, 78, 13, 7, 30, 22,
24, 33, 8, 43, 62, 3, 71, 45, 48, 6, 99, 82, 76, 60, 80, 90, 68,
51, 27, 18, 56, 63, 74, 1, 61, 42, 41, 4, 15, 17, 40, 38, 5, 91,
59, 0, 34, 28, 50, 11, 35, 23, 52, 10, 31, 66, 57, 79, 85, 32, 84,
14, 89, 19, 29, 49, 97, 98, 69, 20, 94, 72, 77, 25, 37, 81, 46, 39,
65, 58, 12, 88, 70, 87, 36, 21, 83, 9, 96, 67, 64, 47, 44])
选择这些数字的好方法是什么?
http://www.bydatabedriven.com/wp-content/uploads/2012/12/Screen-Shot-2012-12-03-at-8.12.36-PM.png
作为一个例子,如果n = 10,那么返回的值可能是(从列表的开头选择的更多数字与列表末尾的那些值相比):
26,2,16,92,8,45,61,99,94 39
答案 0 :(得分:3)
您可以使用np.random.choice
并直接或使用pd.Series.sample
传递适当形状的权重,因为您正在使用pandas。例如:
In [59]: s = pd.Series(range(100))
In [60]: chosen = s.sample(10**6, replace=True, weights=1.0/(1+np.arange(len(s)))) #typecast the weight to float
In [61]: chosen.hist(bins=50).get_figure().savefig("out.png")
给了我
您可以根据心脏的内容调整权重功能。这里我基本上使用了1 / i,因此第4个元素的选择可能性比第一个要低4倍。您可以将该表达式赋予某种能力,**2
使第4个元素被选中的可能性降低16倍,或**0.5
使第4个元素的一半可能被选为第一个元素。完全取决于你找到一个你满意的行为。
另请注意,我在这里使用replace=True
,因为我想选择大量的值来使情节看起来更好。如果您不希望两次选择相同的元素,请使用replace=False
。
答案 1 :(得分:0)
以下是从第一原则开始的方法。
random.random()
返回0到1之间的随机数。这意味着当random.random() < x
变得接近0时,表达式x
变得更少。
对于数组中的每个元素,比如说array[i]
,让我们定义元素被选中的几率
<强> odds_pick(i) = (1 - i / len(array)) * DAMP
。强>
这里,DAMP
是一个介于0和1之间的数字,用于减少拾取数字的几率。因此,
DAMP
。DAMP / len(array)
。i
变大,它们会减少。最后,为了得到这个合适的样本,迭代数组,并检查是否random.random() < odds_pick(i)
。如果是这样,请选择元素。
由于我们定义odds_pick(i)
的方式,随着i
的增加,它会变得越来越接近0,因此random.random() < odds_pick(i)
将越来越不真实。最终,这意味着我们最终会从前端而不是从末端更频繁地挑选元素。
<小时/>
import random
def sample_with_bias(arr, n, damping_factor=.3):
res = []
indexes_picked = []
n_picked = 0
while n_picked < n:
for i, x in enumerate(arr):
odds_pick = damping_factor * (1 - i * 1. / len(arr))
if i not in indexes_picked and random.random() < odds_pick:
print(odds_pick)
n_picked += 1
indexes_picked.append(i)
res.append(x)
return res
请注意,在数组上有多次传递以覆盖仅在一次传递中无法对n
个唯一元素进行采样的极端情况。
让我们进行一些实验:
def run_experiment(arr, damping_factor, num_pick=10, num_runs=100):
all_samples = []
for i in range(num_runs):
all_samples.extend(sample_with_bias(arr, num_pick, damping_factor=damping_factor))
dist = Counter(all_samples)
dist = sorted(list(dist.items()), key=lambda k: k[0])
k, v = zip(*dist)
plt.bar(k, v)
plt.title("Damping Factor = {0}".format(damping_factor))
plt.show()
和
for df in [0.10, 0.50, 0.99]:
np.random.seed(0)
a = pd.Series(range(100))
run_experiment(a, damping_factor=df)
<小时/>