<p>很酷的项目。我将使用随机生成的数据集进行说明:</p>
<pre><code>import numpy as np
import pandas as pd
np.random.seed(0)
Send_Amount = 10**(np.random.randint(1, 9, 10**6)) * \
(np.random.choice(np.arange(1, 10),
p=np.log10(1+(1/np.arange(1, 10))),
size=10**6) +
np.random.rand(10**6))
Send_Agent = np.random.choice(['ADR000264', 'API185805'], 10**6)
df = pd.DataFrame({'Send_Agent': Send_Agent, 'Send_Amount': Send_Amount.astype(int)})
</code></pre>
<p>看起来像这样:</p>
^{pr2}$
<p>现在,如果将该函数应用于序列<code>Send_Amount</code>,它将返回另一个带前导数字的序列。如果首先对它们进行分组,则需要为每个分组指定所需的结果类型。该函数不是为获取一个组并返回该组的结果而设计的。它只返回一个数字的前导数字。在</p>
<p>相反,为了验证<a href="https://en.wikipedia.org/wiki/Benford%27s_law" rel="nofollow noreferrer">Benford's law</a>,您需要检查前导数字的频率分布。因为您已经为前导数字创建了一个列,现在可以通过Send_Agent进行分组并对该列调用<code>value_counts</code>。总而言之,它是这样的:</p>
<pre><code>result = df.assign(Leading_Digit = df['Send_Amount'].astype(str).str[0]).groupby('Send_Agent')['Leading_Digit'].value_counts(sort=False)
print(result)
Out[105]:
Send_Agent Leading_Digit
ADR000264 1 150522
2 87739
3 62460
4 48204
5 39757
6 33791
7 29024
8 25567
9 23044
API185805 1 150575
2 87994
3 62173
4 48323
5 39452
6 33720
7 29141
8 25538
9 22976
Name: Leading_Digit, dtype: int64
</code></pre>
<p>您也可以使用<code>df.groupby('Send_Agent')['Leading_Digit'].value_counts(sort=False)</code>完成此操作(在创建列之后)。我只是一步到位。最终,分布将(希望)如下所示:</p>
<pre><code>result.unstack(level=0).plot.bar(subplots=True)
</code></pre>
<p><a href="https://i.stack.imgur.com/vpd0Y.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/vpd0Y.png" alt="enter image description here"/></a></p>
<p>要找出理论概率和观测频率之间的差异,可以执行以下操作:</p>
<pre><code>result = df.assign(Leading_Digit = df['Send_Amount'].astype(str).str[0]).groupby('Send_Agent')['Leading_Digit'].value_counts(sort=False, normalize=True)
</code></pre>
<p>请注意,我传递了<code>normalize=True</code>以便它计算比例而不是频率。在</p>
<p>现在,您可以用以下方法进行区别:</p>
<pre><code>result.unstack(level=0).subtract(np.log10(1+(1/np.arange(1, 10))), axis=0).abs()
Out[16]:
Send_Agent ADR000264 API185805
Leading_Digit
1 0.000051 0.000185
2 0.000651 0.000065
3 0.000046 0.000566
4 0.000523 0.000243
5 0.000316 0.000260
6 0.000621 0.000508
7 0.000044 0.000303
8 0.000030 0.000065
9 0.000321 0.000204
</code></pre>
<p>在这里,unstack将Send_代理程序带到列。<code>np.log10(1+(1/np.arange(1, 10)))</code>计算理论概率。您也可以传递先前定义的阵列。由于我们要逐行减去元素,因此<code>subtract</code>方法有<code>axis=0</code>参数。最后,<code>.abs()</code>取结果的绝对值。在</p>