gpt4 book ai didi

python - groupby.agg 中的本福德定律测试函数

转载 作者:行者123 更新时间:2023-11-28 17:26:45 29 4
gpt4 key购买 nike

下面是我的数据框的一个小样本,它有 25000 奇数行长:

 In [58]: df
Out[58]:
Send_Agent Send_Amount
0 ADR000264 361.940000
1 ADR000264 12.930000
2 ADR000264 11.630000
3 ADR000264 12.930000
4 ADR000264 64.630000
5 ADR000264 12.930000
6 ADR000264 77.560000
7 ADR000264 145.010000
8 API185805 112.34
9 API185805 56.45
10 API185805 48.97
11 API185805 85.44
12 API185805 94.33
13 API185805 116.45

有 2 个 Send_Agents ADR000264 和 API185805。我正在尝试对 Send_Amount 应用本福德定律测试。当我尝试所有 Send_Amount 而不管 Send_Agent 时,我都能成功地做到这一点。下面是我提取前导数字的函数。

def leading_digit(x,dig=1):
x = str(x)
out = int(x[dig-1])
return out

此函数在应用于 Send_Amount 列时效果很好:

  In [75]: df['Send_Amount'].apply(leading_digit)
Out[75]:
0 3
1 1
2 1
3 1
4 6
5 1
6 7
7 1
8 1

它给出一个系列的输出,并从 Send_Amount 列中提取前导数字。

但是当我在按 Send_Agent 分组后尝试相同的函数时,我得到了错误的结果:

In [74]: df['Send_Amount'].groupby(df['Send_Agent']).apply(leading_digit)
Out[74]:
Send_Agent
ADR000264 0
API185805 6
dtype: int64

同groupby.agg

In [59]: grouped = df.groupby('Send_Agent')
In [60]: a = grouped.agg({'Send_Amount':leading_digit})

In [61]: a
Out[61]:
Send_Amount
Send_Agent
ADR000264 0
API185805 6

编辑:

所以,现在我们有了前导数字的计数。

   In [16]: result = df.assign(Leading_Digit =    df['Send_Amount'].astype(str).str[0]).groupby('Send_Agent')['Leading_Digit'].value_counts(sort=False)

In [17]: result
Out[17]:
Send_Agent Leading_Digit
ADR000264 1 5509
2 4748
3 2090
4 2497
5 979
6 1206
7 529
8 549
9 729
API185805 1 1707
2 1966
3 744
4 1218
5 306
6 605
7 138
8 621
9 76

数据类型:int64

        In [18]: type(result)
Out[18]: pandas.core.series.Series

我不需要绘制图表。我只需要从本福德值中减去计数。

   In [22]: result = result.to_frame()

In [29]: result.columns = ['Count']

In [32]: result
Out[32]:
Count
Send_Agent Leading_Digit
ADR000264 1 5509
2 4748
3 2090
4 2497
5 979
6 1206
7 529
8 549
9 729
API185805 1 1707
2 1966
3 744
4 1218
5 306
6 605
7 138
8 621
9 76

In [33]: result['Count'] = (result['Count'])/(result['Count'].sum())

In [34]: result
Out[34]:
Count
Send_Agent Leading_Digit
ADR000264 1 0.210131
2 0.181104
3 0.079719
4 0.095244
5 0.037342
6 0.046001
7 0.020178
8 0.020941
9 0.027806
API185805 1 0.065110
2 0.074990
3 0.028379
4 0.046458
5 0.011672
6 0.023077
7 0.005264
8 0.023687
9 0.002899

In [35]: result.unstack()
Out[35]:
Count \
Leading_Digit 1 2 3 4 5 6
Send_Agent
ADR000264 0.210131 0.181104 0.079719 0.095244 0.037342 0.046001
API185805 0.065110 0.074990 0.028379 0.046458 0.011672 0.023077


Leading_Digit 7 8 9
Send_Agent
ADR000264 0.020178 0.020941 0.027806
API185805 0.005264 0.023687 0.002899

So , benford values for 1 to 9 as follows
d = 0.30103, 0.176091, 0.124939, 0.09691, 0.0791812, 0.0669468, 0.0579919, 0.0511525, 0.0457575

我需要做的就是从 result[count] 中减去它们。

我对 Pandas 和 Python 还是很陌生。那么,我该怎么做。

最佳答案

很酷的项目。我将使用随机生成的数据集进行说明:

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)})

看起来像这样:

df.head()
Out[104]:
Send_Agent Send_Amount
0 ADR000264 370394
1 ADR000264 239323923
2 API185805 6364712
3 ADR000264 98
4 ADR000264 56926

现在,如果将该函数应用于 Send_Amount 系列,它将返回另一个带有前导数字的系列。如果先将它们分组,则需要指定每个组的结果类型。该函数并非旨在获取一个组并返回该组的结果。它只返回数字的前导数字。

相反,验证Benford's law ,您需要检查前导数字的频率分布。由于您已经为前导数字创建了一个列,现在您可以按 Send_Agent 分组并对该列调用 value_counts。在一行中,它看起来像这样:

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

您也可以使用 df.groupby('Send_Agent')['Leading_Digit'].value_counts(sort=False) 完成此操作(在创建列之后)。我只是一步完成了它们。最终,分布将(希望)如下所示:

result.unstack(level=0).plot.bar(subplots=True)

enter image description here

要找到理论概率和观察到的频率之间的差异,您可以这样做:

result = df.assign(Leading_Digit = df['Send_Amount'].astype(str).str[0]).groupby('Send_Agent')['Leading_Digit'].value_counts(sort=False, normalize=True)

请注意,我传递了 normalize=True,以便它计算比例而不是频率。

现在您可以通过以下方式来区别:

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

在这里,unstack 将 Send_Agent 带到列中。 np.log10(1+(1/np.arange(1, 10))) 计算理论概率。您也可以传递先前定义的数组。由于我们想要按行减去元素,因此 subtract 方法有 axis=0 参数。最后,.abs() 取结果的绝对值。

关于python - groupby.agg 中的本福德定律测试函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38338864/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com