我正在遵循R和Python中“进行贝叶斯数据分析”中的练习.
下面的问题很简单,但是可以很好地测试不同的方法:
ex 4.3
Determine the exact probability of drawing a 10 from a shuffled pinochle deck. (In a pinochle deck, there are 48 cards. There are six values: 9, 10, Jack, Queen, King, Ace. There are two copies of each value in each of the standard four suits: hearts, diamonds, clubs, spades.)
(A) What is the probability of getting a 10?
当然,答案是1/6.
我能找到的最快解决方案(与R的速度相当)是使用np.random.choice生成大量的纸牌抽奖,然后应用计数器.我不喜欢不必要地创建数组的想法,因此我尝试使用字典和for循环,一次绘制一张卡,并增加该卡类型的数量.令我惊讶的是,它慢得多!
下面是我测试的3种方法的完整代码. _有没有一种方法可以像method1()一样执行,但是使用恒定空间呢?
Python代码:(Google Colab link)
deck = [c for c in ['9','10','Jack','Queen','King','Ace'] for _ in range(8)]
num_draws = 1000000
def method1():
draws = np.random.choice(deck, size=num_draws, replace=True)
df = pd.DataFrame([Counter(draws)])/num_draws
print(df)
def method2():
card_counts = defaultdict(int)
for _ in range(num_draws):
card_counts[np.random.choice(deck, replace=True)] += 1
df = pd.DataFrame([card_counts])/num_draws
print(df)
def method3():
card_counts = defaultdict(int)
for _ in range(num_draws):
card_counts[deck[random.randint(0, len(deck)-1)]] += 1
df = pd.DataFrame([card_counts])/num_draws
print(df)
Python timeit()结果:
方法1:1.2997
方法2:23.0626
方法3:5.5859
R代码:
card = sample(deck, numDraws, replace=TRUE)
print(as.data.frame(table(card)/numDraws))
解决方法:
def unique():
unq,ids = np.unique(deck, return_inverse=True)
all_ids = np.random.choice(ids, size=num_draws, replace=True)
ar = np.bincount(all_ids)/num_draws
return pd.DataFrame(ar[None], columns=unq)
NumPy在这里有何帮助?
有两项重大改进正在帮助我们:
>我们将字符串数据转换为数字. NumPy可以很好地处理此类数据.为此,我们使用np.unique.
>我们使用np.bincount代替计数步骤.再次,它很好地适用于数字数据,并且在此方法开始时我们已经从数字转换中获得了它.
>通常,NumPy可以很好地处理大数据.
给定样本数据集的时间与最快的方法进行比较1-
In [177]: %timeit method1()
328 ms ± 16.3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
In [178]: %timeit unique()
12.4 ms ± 265 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)